Open kangyana opened 1 year ago
module
module.exports
__webpack_require__
__webpack_modules__
在 webpack 中,通过 import() 可实现 code spliting。 假设我们有以下文件:
import()
index.js
import("./sum").then((m) => { m.default(3, 4); });
sum
const sum = (x, y) => x + y; export default sum;
我们将使用以下简单的 webpack 配置进行打包,具体示例可参考 node-examples:code-spliting(opens new window)
{ entry: './index.js', mode: 'none', output: { filename: '[name].[contenthash].js', chunkFilename: 'chunk.[name].[id].[contenthash].js', path: path.resolve(__dirname, 'dist/deterministic'), clean: true }, optimization: { moduleIds: 'deterministic', chunkIds: 'deterministic' } }
通过观察打包后的文件 dist/deterministic/main.xxxxxx.js,可以发现: 使用 import() 加载数据时,以上代码将被 webpack 编译为以下代码:
dist/deterministic/main.xxxxxx.js
__webpack_require__ .e(/* import() | sum */ 644) .then(__webpack_require__.bind(__webpack_require__, 709)) .then((m) => { m.default(3, 4); });
此时 644 为 chunkId,观察 chunk.sum.xxxx.js 文件,以下为 sum 函数所构建而成的 chunk:
644
chunk.sum.xxxx.js
"use strict"; (self["webpackChunk"] = self["webpackChunk"] || []).push([ [644], { /***/ 709: /***/ ( __unused_webpack_module, __webpack_exports__, __webpack_require__ ) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ default: () => __WEBPACK_DEFAULT_EXPORT__, /* harmony export */ }); const sum = (x, y) => x + y; /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = sum; /***/ }, }, ]);
以下两个数据结构是加载 chunk 的关键:
document.createElement('script')
__webpack_require__.e
实际上,在 webpack 中可配置 output.chunkLoading 来选择加载 chunk 的方式,比如选择通过 import()的方式进行加载。 (由于在生产环境需要考虑 import 的兼容性,目前还是 JSONP 方式较多)
output.chunkLoading
import
{ entry: './index.js', mode: 'none', output: { filename: 'main.[contenthash].js', chunkFilename: '[name].chunk.[chunkhash].js', path: path.resolve(__dirname, 'dist/import'), clean: true, // 默认为 `jsonp` chunkLoading: 'import' } })
可参考示例 webpack 运行时代码 (opens new window)中查看加载一个 chunk 的实现。
1. 一个 webpack 的运行时,包括最重要的两个数据结构:
module
,module.exports
,__webpack_require__
) 对模块进行包裹构成。__webpack_modules__
中的包裹函数,执行并返回module.exports
,并缓存。2. code spliting
在 webpack 中,通过
import()
可实现 code spliting。 假设我们有以下文件:index.js
sum
我们将使用以下简单的 webpack 配置进行打包,具体示例可参考 node-examples:code-spliting(opens new window)
3. 运行时解析
通过观察打包后的文件
dist/deterministic/main.xxxxxx.js
,可以发现: 使用import()
加载数据时,以上代码将被 webpack 编译为以下代码:此时
644
为 chunkId,观察chunk.sum.xxxx.js
文件,以下为sum
函数所构建而成的 chunk:以下两个数据结构是加载 chunk 的关键:
document.createElement('script')
异步加载 chunk 并封装为 Promise。__webpack_modules__
,并将__webpack_require__.e
的 Promise 进行 resolve。实际上,在 webpack 中可配置
output.chunkLoading
来选择加载 chunk 的方式,比如选择通过import()
的方式进行加载。 (由于在生产环境需要考虑import
的兼容性,目前还是 JSONP 方式较多)可参考示例 webpack 运行时代码 (opens new window)中查看加载一个 chunk 的实现。