内容提要
webpack 的 scope hoisting(作用域提升)由 webpack3 引入,webpack4 中需启用 ModuleConcatenationPlugin。它将被引入的 ES6 模块直接合并到引入者顶部,而非用 __webpack_require__ 分开调用,从而减少代码量、降低内存占用、提升运行速度。但使用非 ES6 模块或异步 import() 时不会提升,模块仍会拆分。
延伸解读
作用域提升的适用条件
文章指出,scope hoisting 并非对所有模块都生效。当使用非 ES6 模块(如 CommonJS)或异步 import() 时,webpack 不会应用作用域提升,模块仍会被拆分开。这意味着在混合模块类型或动态导入的场景下,优化效果可能受限,开发者需注意模块规范的一致性。
启用方式与版本差异
scope hoisting 由 webpack3 引入,但在 webpack4 中需要手动添加 ModuleConcatenationPlugin 插件才能启用。文章示例中,该插件被配置在开发环境下,生产环境则未显式添加。这提示开发者,若想在生产构建中受益,需确认插件是否已正确配置。
优化效果与原理
通过将引入的 ES6 模块直接合并到引入者顶部,scope hoisting 减少了 __webpack_require__ 的调用次数,从而带来代码量减少、内存占用降低和运行速度提升。文章中的打包示例显示,多个模块被合并到入口模块中,变量声明直接内联,直观体现了作用域提升的效果。
Q&A
webpack 的 scope hoisting 是什么?
scope hoisting 是 webpack3 引入的「作用域提升」功能,webpack 会把被引入的 ES6 模块直接合并到引入者的顶部,而不是用 __webpack_require__ 分开调用。
在 webpack4 中如何启用 scope hoisting?
在 webpack4 中需要添加 ModuleConcatenationPlugin 插件,例如在配置中 plugins: [new webpack.optimize.ModuleConcatenationPlugin()]。
scope hoisting 能带来哪些好处?
启用后代码量明显减少,减少多个函数后内存占用减少,并且不用多次使用 __webpack_require__ 调用模块,运行速度也会得到提升。
什么情况下 scope hoisting 不会生效?
当使用非 ES6 模块或使用异步 import() 时,不会应用作用域提升,模块依然会拆分开,不过具体代码会跟正常的引入有一点差异。
scope hoisting 和 JavaScript 的函数提升、变量提升有什么关系?
类似 JavaScript 把函数和变量声明提升到当前作用域顶部,scope hoisting 是 webpack 把引入的 js 文件“提升到”它的引入者顶部。
启用 scope hoisting 后打包结果有什么变化?
打包后会把需要导入的文件直接移入导入者顶部,例如入口模块中直接内联了 shouldImport、one、two 等模块的代码,而不是通过 __webpack_require__ 分开调用。