TreeShaking

TreeShaking

除了Webpack之外,还有很多其他优秀的模块打包工具,譬如BrowserifyRollup.js等。Rollup.jsRich Harris开发并且开源,其发布之处主打的特性是支持所谓的TreeShaking,仅在最后的生成包体中仅包含使用到的代码而并非全部代码都打包进来。在Webpack 1中其并未支持ES6importsexports语法,而是需要转化为var module = require('module');不过在Webpack 2中其已经能够原生支持ES6模块的语法,意味着可以引入像TreeShaking这样的模块优化机制了,在后续的Webpack 3中通过Scope Hoisting等方案可以解决小模块问题。我们以一个简单的例子来介绍TreeShaking的机制,假设我们的应用包含两个文件:index.jsmodule.js,在后者中我们导出了两个辅助函数:

// module.js
export const sayHello = name => `Hello ${name}!`;
export const sayBye = name => `Bye ${name}!`;

而在index.js中我们仅引入了sayHello函数:

// index.js
import { sayHello } from "./module";
sayHello("World");

虽然我们同样暴露了sayBye这个函数,但是从未使用过,那么基于TreeShaking优化机制,最后的打包文件如下所示:

// bundle.js
const sayHello = name => `Hello ${name}!`;
sayHello('World');

通过这个小例子相信大家能够明白TreeShaking的机制,形象化来考虑,我们将应用看做某个依赖关系图谱,也就是一棵依赖树,每个export都可以看做一根树枝。我们通过摇晃这棵树来让那些没有使用的、假死状态的树枝脱落。在Webpack中我们往往使用babel-loader来转换所有的JavaScript文件使其能够运行在较低版本的浏览器上,不过同样其会将ES6的模块语法转化为AMD或者CommonJS规范等,我们需要在Webpack 2中进行如下配置来避免Babel对模块语法进行转换:

// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  output: { filename: "bundle.js", path: "dist" },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          presets: [["es2015", { modules: false }]]
        }
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({ title: "Tree-shaking" })]
};
下一页