import { a, x, y } from "./a";
import * as b from "./b";
import("./lazy").then(function(lazy) {
console.log(a, b.a(), x, y, lazy.c, lazy.d.a, lazy.x, lazy.y);
});
lazy.js
export * from "./c";
import * as d from "./d";
export { d };
a.js
// module a
export var a = "a";
export * from "./shared";
b.js
// module b
export function a() {
return "b";
};
c.js
// module c
import { c as e } from "./cjs";
export var c = String.fromCharCode(e.charCodeAt(0) - 2);
export { x, y } from "./shared";
d.js
// module d
export var a = "d";
cjs.js
// module cjs (commonjs)
exports.c = "e";
shared.js
// shared module
export var x = "x";
export * from "./shared2";
webpack3之Scope Hoisting
介绍
在webpack2发布半年不到,webpack3又发布了,这次的发布版本虽然跨度比较大,但是不同于webpack2的升级,它对于向下的兼容性还是要好很多的,但是由于内部的突破性变化导致某些插件的使用,根据官方的数据表明,目前为止,至少98%的用户都没有遇到升级过程中不兼容的问题。
在这次升级中,有以下特性:
作用域的提升(Scope Hoisting)
魔法注释(Magic Comments)
我们在这篇文章中,主要的对象是作用域的提升scope hoisting
如果对于webpack前两个版本了解的同学,应该知道,在打包后的文件里面,每个模块都会被包装在一个单独的函数闭包中,这些闭包会导致你JS在浏览器中的执行速度变慢,并且会导致内存占用率增加,而另外的打包工具rollup则是将所有的模块包装在一个大的闭包中
所以在webpack3中增加了这个功能,我们可以在配置项中添加对应的配置来开启该功能
并且该功能也会让代码打包的体积变得更小,加快运行的速度
Scope Hoisting 和 Code splitting
我们都知道webpack有一个核心功能是Code-splitting, 并且在webpack2也开始支持了原生ES6的模块加载方案,那么对于按需加载的模块,肯定是在打包过程中,形成另外的打包文件的,那么webpack 是怎么做到 code splitting的呢?
所以在webpack中不能将所有所有的模块直接放在同一个作用域下,有以下几个原因:
可能说起来比较抽象,我们举个例子,来对比下webpack2和webpack3再打包同样的代码后生成的代码
webpack2 VS webpack3
我们都统一建立如下关系的文件,分别用webpack2和webpack3打包,观察下生成的打包文件的不同


上图中实现表示的是同步的依赖关系,大箭头表示的是异步的依赖关系
根据我们上文中所说的规则,webpack会使用一种称为 “局部范围提升”的方法,该方法会选择可以展开的最大的ES模块进行变量提升,会将它们和webpack的默认原函数相连接
所以上述的模块之间的关系会变成下图:
index.js
lazy.js
a.js
b.js
c.js
d.js
cjs.js
shared.js
shared2.js
webopack2打包的代码
上述代码可以发现,每个文件都被视为一个module,并且使用了闭包函数把它们分别进行了包裹
webpack3打包代码
从代码上分析,是符合我们上面的图所划分的进行的作用域提升的
结论
通过webpack2和webpack3的所形成的打包文件的对比来看,在代码的体积上,和性能上是有所提升的,对于一个很大型且复杂的项目来说,webpack3的性能速度有所提升和打包后的代码体积更小。