什么是 Tree-Shaking
用来在打包编译成 bundle 时消除 ES6 Module 语法中未使用到的代码和模块。
比如入口文件引入这个math.js模块,有add,min方法,只引入add方法,但是打包后的文件中还自动引入了min方法,多次一举,浪费性能,使用tree-shaking(树摇)去除未被导入的代码
import { add } from './math.js';
Tree Shaking
使用
Tree Shaking
可以用来剔除 JavaScript
中用不上的死代码。它依赖静态的 ES6
模块化语法,例如通过 import
和 export
导入导出。
需要注意的是要让 Tree Shaking
正常工作的前提是 JavaScript
代码必须采用 ES6
模块化语法,因为 ES6
模块化语法是静态的,这让 Webpack
可以简单的分析出哪些 export
的被 import
过了。不支持commonJs模块导入
接下来配置 Webpack
让 Tree Shaking
生效
webpack4
默认保留ES6模块化语句,并没有通过Babel将其转换
修改 .babelrc
文件为如下:
//.babelrc { "presets": [["@babel/preset-env",{ "useBuiltIns": "usage", "corejs": 2, "modules":false //关闭 Babel 的模块转换功能,保留原本的 ES6 模块化语法 //默认是auto,取值还可以是 amd, umd, systemjs, commonjs,auto等 }]] }
修改 webapck.config.js
, 开发环境默认没有树摇功能,需要加配置, 生产环境默认有树摇功能,可以去除optimization配置
module.exports={ mode: 'development', optimization: { //开发坏境使用tree shaking时加usedExports: true usedExports: true }, }
还需通过 package.json
的 "sideEffects"
属性来告诉webpack哪些模块是可以忽略掉,如果没有则设置为 false
,来告知webpack,它可以安全地删除未用到的 export
。
修改 package.json
{ "name": "your-project", "sideEffects": false }
有的模块没有导出模块(export default XXX),在 Tree Shaking
模式下就会被忽略(比如import './style.css'),所以我们需要把这些模块做处理,不需要 Tree Shaking
对这些模块进行处理,可以改为一个数组:
{ "name": "your-project", "sideEffects": ["*.css"] } "sideEffects": ["*.css"] 表示不对所以css模块使用 Tree Shaking 处理。
index.js
//tree shaking import export import {cube} from './math.js' let component = () => { let element = document.createElement('pre') element.innerHTML = [ 'Hello webpack!', '2 cubed is equal to ' + cube(2) ].join('\n\n'); console.log(cube) return element; } document.body.appendChild(component());
main.js
export let square= (x) => { console.log(x) return x * x; } export let cube = (x) => { console.log(x) return x * x * x; }
运行 npm run build
,然后打开打包后的js文件:main.js找到下面这段文字
/*!*********************!*\ !*** ./src/math.js ***! \*********************/ /*! exports provided: square, cube */ /*! exports used: cube */ /***/
从上面这段文字可以看出 Tree Shaking
生效了,但是在开发环境下,并没有把没有用的代码删掉,因为开发环境下还需要对代码进行调试。
我们已经找出需要删除的“未引用代码(dead code)”,然而,不仅仅是要找出,还要删除它们。生产环境中会删除没引入的代码,我们需要将 mode
配置选项设置为 production
,将optimization对象删掉,修改 devtool
配置选项
webpack.config.js
module.exports = { mode: 'production', devtool: 'cheap-module-source-map' }
运行 npm run build
,查看打包结果就可以看到没有用的代码被删掉了。