定义

参考链接

Scope Hoisting 可以让 Webpack 打包出来的代码文件更小、运行的更快, 它又译作 “作用域提升”,是在 Webpack3 中新推出的功能。
由于最初的webpack转换后的模块会包裹上一层函数,import会转换成require,因为函数会产生大量的作用域,运行时创建的函数作用域越多,内存开销越大。而Scope Hoisting 会分析出模块之间的依赖关系,尽可能的把打包出来的模块合并到一个函数中去,然后适当地重命名一些变量以防止命名冲突。

开启Scope Hoisting

使用Scope Hoisting非常简单,webpack已经内置了对应的模块:

  • production模式 下,这个模块默认就会启用
  • development模式 下,我们需要手动开启这个模块。 ```javascript const webpack = require(‘webpack’);

plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ]

  1. <a name="vUVfk"></a>
  2. ## 举例说明
  3. 假如现在有两个文件分别是 util.js 和入口文件 main.js。
  4. ```javascript
  5. export default 'Hello,Webpack';
import str from './util.js';
console.log(str);

development模式下,未开启Scope Hoisting的情况。webpack打包后输出中的部分代码如下所示。

[
  (function (module, __webpack_exports__, __webpack_require__) {
    var __WEBPACK_IMPORTED_MODULE_0__util_js__ = __webpack_require__(1);
    console.log(__WEBPACK_IMPORTED_MODULE_0__util_js__["a"]);
  }),
  (function (module, __webpack_exports__, __webpack_require__) {
    __webpack_exports__["a"] = ('Hello,Webpack');
  })
]

开启 Scope Hoisting 后,同样的源码输出的部分代码如下所示。

[
  (function (module, __webpack_exports__, __webpack_require__) {
    var util = ('Hello,Webpack');
    console.log(util);
  })
]

从中可以看出开启 Scope Hoisting 后,函数申明由两个变成了一个,util.js 中定义的内容被直接注入到了 main.js 对应的模块中。
这样做的好处是:

  • 代码体积更小,因为函数申明语句会产生大量代码;
  • 代码在运行时因为创建的函数作用域更少了,内存开销也随之变小

Scope Hoisting的实现原理

分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余。
因此只有那些被引用了一次的模块才能被合并。

注意!!!由于 Scope Hoisting 需要分析出模块之间的依赖关系,因此源码必须采用 ES6 模块化语句,不然它将无法生效。
如果你使用非ES6模块或使用异步import() 的时候,并不会应用作用域提升(即使你开启了Scope Hoisting),模块依然会被拆分开,不过具体代码会跟正常引入得稍微有一点差异。
原因和4-10 使用 TreeShaking 中介绍的类似。