Tree Shaking从字面上理解就是树摇晃。就是当我们在一个js文件中写入了多个导出的方法,但是引用时只使用了一部分,其他方法不应该被打包进来。

1.举例

文件结构

myProject
 |-dist
 |-node_modules
 |-src
+    |-util
+       |-math.js
     |-assets
        |-css
            |-index.css
        |-less
            |-index.less     
        |-sass
            |-index.scss
        |-images
            |-wali_logo.png
     |-index.html
     |-index.js
 |-package.json
 |-webpack.config.js
 |-postcss.config.js
 |-.babelrc

src/util/math.js

export const add = (x,y) =>{
    return x + y;
}

export const minus = (x,y) =>{
    return x - y;
}

src/index.js

import { add } from "./util/math";

add(1,2)

运行webpack

yarn run build

打开dist/main.js文件

...
...

/***/ "./src/util/math.js":
/*!*********************************!*\
  !*** ./src/util/math.js ***!
  \*********************************/
/*! exports provided: add, minus */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"add\", function() { return add; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"minus\", function() { return minus; });\n/**\r\n * Created by Administrator on 2019/5/28.\r\n */\nconst add = (x, y) => {\n  return x + y;\n};\nconst minus = (x, y) => {\n  return x - y;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXNzZXRzL3V0aWwvbWF0aC5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3NyYy9hc3NldHMvdXRpbC9tYXRoLmpzPzAwNWYiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIENyZWF0ZWQgYnkgQWRtaW5pc3RyYXRvciBvbiAyMDE5LzUvMjguXHJcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZCA9ICh4LCB5KSA9PiB7XG4gIHJldHVybiB4ICsgeTtcbn07XG5leHBvcnQgY29uc3QgbWludXMgPSAoeCwgeSkgPT4ge1xuICByZXR1cm4geCAtIHk7XG59OyJdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/util/math.js\n");

/***/ })

...
...

上面这段代码就是webpack打包生成的代码,我们看到在math.js中将add,minus方法都打包进来。这样就会导致我们最终生成的文件特别大。tree shaking概念可以帮助我们将没有用的代码给摇晃掉。

2.配置webpack

package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "webpack测试",
+  "sideEffects":[
+	  "*.css"
+  ],
  "main": "index.js",
  "author": "wali",
  "private": true,
  "license": "MIT",
  "scripts": {
    "dev": "npx webpack-dev-server --mode=development --colors",
    "dist": "npx webpack --mode=production",
    "build": "npx webpack --mode=development --colors"
  },
  "dependencies": {
    "@babel/core": "^7.4.5",
    "@babel/plugin-transform-runtime": "^7.4.4",
    "@babel/preset-env": "^7.4.5",
    "@babel/runtime": "^7.4.5",
    "@babel/runtime-corejs2": "^7.4.5",
    "autoprefixer": "^9.5.1",
    "babel-loader": "^8.0.6",
    "clean-webpack-plugin": "^2.0.2",
    "css-loader": "^2.1.1",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^3.0.1",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "image-webpack-loader": "^4.6.0",
    "less": "^3.9.0",
    "less-loader": "^5.0.0",
    "lodash": "^4.17.11",
    "node-sass": "^4.12.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "webpack": "^4.32.0",
    "webpack-cli": "^3.3.2",
    "webpack-dev-server": "^3.4.1"
  }
}

webpack.config.js

module.exports = {
  ...
+  optimization: {
+    usedExports: true
+  }
  ...
};

这里需要特别强调下,...是说之前webpack.config.js的代码还在,只是添加了几行代码。随着功能越来越多,webpack.config.js文件的代码会越来越长,全部贴出来实在是太费篇幅了,后面小菜就都采用这种方式。

运行webpack

yarn run build

打开dist/main.js文件

...
...
/***/ "./src/util/math.js":
/*!*********************************!*\
  !*** ./src/util/math.js ***!
  \*********************************/
/*! exports provided: add, minus */
/*! exports used: add */
/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval("/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"a\", function() { return add; });\n/* unused harmony export minus */\n/**\r\n * Created by Administrator on 2019/5/28.\r\n */\nconst add = (x, y) => {\n  return x + y;\n};\nconst minus = (x, y) => {\n  return x - y;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXNzZXRzL3V0aWwvbWF0aC5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3NyYy9hc3NldHMvdXRpbC9tYXRoLmpzPzAwNWYiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIENyZWF0ZWQgYnkgQWRtaW5pc3RyYXRvciBvbiAyMDE5LzUvMjguXHJcbiAqL1xuZXhwb3J0IGNvbnN0IGFkZCA9ICh4LCB5KSA9PiB7XG4gIHJldHVybiB4ICsgeTtcbn07XG5leHBvcnQgY29uc3QgbWludXMgPSAoeCwgeSkgPT4ge1xuICByZXR1cm4geCAtIHk7XG59OyJdLCJtYXBwaW5ncyI6IkFBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/util/math.js\n");

/***/ }),

...
...

我们发现exports used: add说明webpack已经知道在index.js文件只引用了add方法,但是没有删除,没有删除的原因是因为我们开发模式,开发模式下如果删除就会对代码行数产生影响不利定位错误,当我们把webpack模式改为生产模式,minus方法就会删除掉。

webpack.config.js

module.exports = {
  ...  
-  devtool:'cheap-eval-source-map',
+  devtool:'cheap-source-map',
  ...
};

运行生产webpack

yarn run dist

ssl

我们看到在生成环境下,就只有add方法被引入进来,而minus方法就会被摇晃掉

3.代码回滚

测试完后,我们将代码回滚下,以便后续我们继续演示。

webpack.config.js

module.exports = {
  ...  
+  devtool:'cheap-eval-source-map',
-  devtool:'cheap-source-map',
  ...
};

webpack4.x 教程

webpack 准备工作(1) webpack 手写最基本的配置(2) webpack 打包样式(3) webpack 让打包更便捷(4) webpack 打包图片(5) webpack iconfont打包(6) webpack devServer本地开发(7) webpack 处理ES6语法(8) webpack SourceMap配置(9) webpack Tree Shaking(10) webpack js代码分割(11) webpack 懒加载(12) webpack 打包分析,Preloading,Prefetching(13) webpack 模块化区分开发和生产(14) webpack 样式文件的代码分割(15) webpack 浏览器缓存(16) webpack shimming(17) webpack 环境变量(18) webpack Esline(19) webpack 解析resolve(20) webpack Library的打包(21) webpack dll(22) webpack 多页面打包配置(23) webpack 搭建vue脚手架(24)