宁波市网站建设_网站建设公司_Linux_seo优化
2026/1/16 21:23:46 网站建设 项目流程

Webpack 在异步请求 JS 文件时获取 JS Bundle 的机制

Webpack 在处理代码分割(Code Splitting)后产生的异步 chunk(通常是import()动态导入)时,浏览器最终是怎么知道要去请求哪个 .js 文件,以及**请求回来后怎么正确执行**,这个过程主要依赖以下几个核心机制:

核心机制概览(2024~2025 主流方式)

机制主要文件作用谁负责生成当前主流方式
manifestruntime chunkchunkId → 文件名映射表webpack(内置)绝大多数项目都有
publicPathruntime 或配置决定请求的 URL 前缀用户配置 + runtime 推断非常重要
webpack_require.pruntime就是 publicPath 的运行时变量runtime 注入核心变量
webpack_require.uruntimechunkId → chunk 文件名 的函数webpack(新版本更智能)现代主流
webpack_require.eruntime真正发起 chunk 加载的函数webpack异步加载入口
JSONP / script tag浏览器实际发起 .js 请求的方式浏览器仍然是默认(2025年)

详细流程(以最常见的 JSONP + webpackChunkName 方式为例)

1. 代码里写: import(/* webpackChunkName: "user-detail" */ './user-detail.js') 2. 打包后生成的文件大致如下: - main.js ← 入口文件 + runtime - 123.user-detail.js ← 异步 chunk(chunkId=123) - 456.other-page.js ← 另一个异步 chunk 3. webpack 在 main.js(或单独的 runtime chunk)中注入了一段类似这样的代码: // 简化的伪代码 var installedChunks = { 0: 0 }; // 已加载的 chunk 标记 __webpack_require__.e = function requireEnsure(chunkId) { var promises = []; // 检查是否已经加载过 if (!installedChunks[chunkId]) { var promise = new Promise(function(resolve, reject) { // 记录 promise,后面 onload 会 resolve var callbacks = installedChunks[chunkId] = [resolve, reject]; // 重要!决定文件名的地方 ↓↓↓ var filename = __webpack_require__.u(chunkId); // ← 得到 "123.user-detail.js" var fullUrl = __webpack_require__.p + filename; // ← publicPath + 文件名 // 创建 script 标签 var script = document.createElement('script'); script.charset = 'utf-8'; script.timeout = 120; script.src = fullUrl; // 错误处理 script.onerror = script.onload = function(event) { // ... 处理成功/失败,把 promise resolve/reject }; document.head.appendChild(script); }); promises.push(promise); } return Promise.all(promises); } 4. 当代码执行到 import() 时,实际上调用的是: __webpack_require__.e("123").then(function() { // chunk 已经加载完成,可以使用模块了 var module = __webpack_require__("./src/user-detail.js"); // ... })

几个关键问题解答

问题答案来源说明
文件名是怎么知道的?__webpack_require__.u(chunkId)webpack 打包时把 chunkId → 文件名映射写死或生成函数
请求路径前缀从哪来?__webpack_require__.p(publicPath)通常来自 output.publicPath 配置
publicPath 是相对路径怎么办?runtime 会尝试推断(script.src 位置)现代 webpack 5 有比较智能的推断逻辑
CDN + 版本号怎么办?output.publicPath = ‘https://cdn.com/v1.2.3/’直接写死或通过环境变量注入
如何知道 chunk 加载成功了?script.onload + JSONP 回调chunk 内部会调用 webpackJsonp.push
多个 chunk 同时加载会不会冲突?webpackJsonp 是全局数组,push 的时候带 chunkId基本不会冲突
开发环境和生产环境的区别?开发环境通常用 webpack-dev-server 的内存文件系统 + sockjs生产环境才是真正的 .js 文件请求

2024-2025 年现代趋势对比表

方式chunk 名控制方式publicPath 处理推荐场景备注
JSONP(默认)webpackChunkName / id自动推断 + 配置绝大多数项目兼容性最好
importScripts基本不用Service Worker特殊场景
SystemJS/Federation远程模块名由 host 决定Module Federation微前端
ESM + import()浏览器原生type=“module”实验性、全 ESM 项目未来方向,但目前还需 polyfill

总结一句话

Webpack 异步 chunk 的加载机制本质上是:
通过运行时注入的__webpack_require__.e函数 + chunkId → 文件名映射 + publicPath 前缀,动态创建<script>标签去请求对应的 js 文件,文件执行后通过全局 webpackJsonp 回调通知 webpack 该 chunk 已就绪。

如果你想深入了解某个特殊场景(CDN 部署、Module Federation、publicPath 动态计算、chunk loading 错误重试、预加载 prefetch/preload 等),可以告诉我,我可以继续展开说明。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询