先来看tree-shaking的几种使用情况
情况一
// ./common/util.js
import lodash from 'lodash-es';
var func1 = function(v) {
alert('111');
}
var func2 = function(v) {
return v;
};
export {
func1,
func2
}
// ./index.js
import { func2 } from '../common/util';
var a = func2(222);
console.log('this is index page');
结果:在开启生产模式tree-shaking时,打包结果不包含lodash
情况二
// ./common/util.js
import lodash from 'lodash-es';
var func1 = function(v) {
alert('111');
return lodash.isArray(v);
}
var func2 = function(v) {
return v;
};
export {
func1,
func2
}
// ./index.js
import { func2 } from '../common/util';
var a = func2(222);
console.log('this is index page');
结果:在开启生产模式tree-shaking时,打包结果包含lodash
情况三
// ./common/util.js
import lodash from 'lodash-es';
var func1 = function(v) {
alert('111');
return lodash.isArray(v);
}
var func2 = function(v) {
return v;
};
export {
func1,
func2
}
// ./index.js
import { func2 } from '../common/util';
var a = func2(222);
console.log('this is index page');
使用webpack-deep-scope-plugin做作用域深度遍历后
结果:在开启生产模式tree-shaking时,打包结果不包含lodash
tree-shaking
tree-shaking是一个概念,指的是将纯ES模块中,将未被导入的成员标记,然后使用代码压缩工具删除未使用成员以及安全删除副作用代码的过程。
tree-shaking针对的是纯的ES模块,才能去除掉那些未使用的代码或成员以及导入的其他模块。
什么是纯的ES模块
- 纯ES模块内部或其内部成员不依赖于其他ES模块
- 纯ES模块不导入其他非ES模块
- 纯ES模块除了导入和导出,没有多余的代码
对纯ES模块的操作
对sideEffects字段未声明的模块(或声明false表示全都是纯ES模块),tree-shaking认为是没有副作用的模块,会进行静态分析,删除未被使用的导出成员和副作用的代码。
- 但如果副作用代码引用了外部模块,外部模块的导入却不会被删除。
对副作用模块的操作
被sideEffects字段声明有副作用的模块,tree-shaking会完整保留这些模块的代码
tree-shaking的局限性
-
因为webpack是先加载资源,再根据静态分析的结果删除无用代码。因此,只要资源被导入后使用了,该资源就会被打包。在删除未使用成员和副作用代码时,如果未使用成员或副作用代码使用了导入的模块,则该模块会被webpack打包到结果中,但实际上该模块未被使用,这样就造成了打包多余的模块。
-
tree-shaking在做静态分析时,是无法标记副作用代码和函数内部代码对于模块的使用,因此如果使用了模块,则该模块会被打包。
-
因此,tree-shaking需要增加一项功能,就是对未使用成员或副作用代码使用的其他模块也一并从打包结果中删除。
如何清除未使用的模块
使用webpack-deep-scope-plugin做作用域深度遍历,在tree-shaking基础上加上webpack-deep-scope-plugin插件。