用webpack4和一些插件提升代码编译速度

对于现在的前端项目而言,编译发布几乎是必需操作,有的编译只需要几秒钟,快如闪电,有的却需要10分钟,甚至更多,慢如蜗牛。特别是线上热修复时,分秒必争,响应速度直接影响了用户体验,用户不会有耐心等那么长时间,让你慢慢编译;如果涉及到支付操作,产品损失更是以秒计,每提前哪怕一秒钟发布,在腾讯海量用户面前,都能挽回不小的损失。不仅如此,编译效率的提升,带来的最直观收益就是,开发效率与开发体验双重提升。

那么,到底是什么拖慢了webpack打包效率,我们又能做哪些提升呢?

webpack 是目前非常受欢迎的打包工具,截止6天前,webpack4 已更新至 4.28.3 版本,10 个月的时间,小版本更新达几十次之多,可见社区之繁荣。

webpack4 发布时,官方也曾表示,其编译速度提升了 60% ~ 98%。

天下武功,唯快不破

由于本地项目升级到 webpack4 有几个月了,为了获得测试数据,手动将 webpack 降级为 3.12.0 版本,其它配置基本不做改动。

测试时,Mac仅运行常用的IM、邮箱、终端、浏览器等,为了尽可能避免插件对数据的影响,我关闭了一些优化插件,只保留常用的loader、js压缩插件。

以下是分别在 webpack@3.12.0 及 webpack@4.26.1 两种场景下各测 5 次的运行截图。

数据分析如下(单位ms):

第1次第2次第3次第4次第5次平均速度提升
webpack3582936097157263589936045959195.8-
webpack4423464038640138403304032340704.645%

纯粹的版本升级,编译速度提升为 45%,这里我选取的是成熟的线上运行项目,构建速度的提升只有建立在成熟项目上才有意义,demo 项目由于编译文件基数小,难以体现出构建环境的复杂性,测试时也可能存在较大误差。同时与官方数据的差距,主要是因为基于的项目及配置不同。

无论如何,近 50% 的编译速度提升,都值得你尝试升级 webpack4!当然,优化才刚刚开始,请继续往下读。

新特性

为了更流畅的升级 webpack4,我们先要了解它。

webpack4 在大幅度提升编译效率同时,引入了多种新特性:

  1. 受 Parcel 启发,支持 0 配置启动项目,不再强制需要 webpack.config.js 配置文件,默认入口 ./src/ 目录,默认entry ./src/index.js ,默认输出 ./dist 目录,默认输出文件 ./dist/main.js
  2. 开箱即用 WebAssembly,webpack4提供了wasm的支持,现在可以引入和导出任何一个 Webassembly 的模块,也可以写一个loader来引入C++、C和Rust。(注:WebAssembly 模块只能在异步chunks中使用)
  3. 提供mode属性,设置为 development 将获得最好的开发体验,设置为 production 将专注项目编译部署,比如说开启 Scope hoisting 和 Tree-shaking 功能。
  4. 全新的插件系统,提供了针对插件和钩子的新API,变化如下:
    • 所有的 hook 由 hooks 对象统一管理,它将所有的hook作为可扩展的类属性
    • 添加插件时,你需要提供一个名字
    • 开发插件时,你可以选择插件的类型(sync/callback/promise之一)
    • 通过 this.hooks = { myHook: new SyncHook(…) } 来注册hook
更多插件的工作原理,可以参考:<a href="https://medium.com/webpack/the-new-plugin-system-week-22-23-c24e3b22e95" target="_blank" rel="external noopener">新插件系统如何工作</a>。 </ol> 

### **快上车,升级前的准备** {#快上车,升级前的准备}

首先,webpack-dev-server 插件需要升级至最新,同时,由于webpack-cli 承担了webpack4 命令行相关的功能,因此 webpack-cli 也是必需的。

与以往不同的是,mode属性必须指定,否则按照 `约定优于配置` 原则,将默认按照 `production` 生产环境编译,如下是警告原文。

> WARNING in configuration  
> The ‘mode’ option has not been set, webpack will fallback to ‘production’ for this value. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for each environment.  
> You can also set it to ‘none’ to disable any default behavior. Learn more: <a href="https://webpack.js.org/concepts/mode/" target="_blank" rel="external noopener">https://webpack.js.org/concepts/mode/</a>

有两种方式可以加入mode配置。

  * 在package.json script中指定–mode: 
    ```

“scripts”: { “dev”: “webpack-dev-server –mode development –inline –progress –config build/webpack.dev.config.js”, “build”: “webpack –mode production –progress –config build/webpack.prod.config.js” }


      * 在配置文件中加入mode属性 
        ```
module.exports = {
  mode: 'production' // 或 development
};
升级至webpack4后,一些默认插件由 optimization 配置替代了,如下:

  * CommonsChunkPlugin废弃,由 optimization.splitChunks 和 optimization.runtimeChunk 替代,前者拆分代码,后者提取runtime代码。原来的CommonsChunkPlugin产出模块时,会包含重复的代码,并且无法优化异步模块,minchunks的配置也较复杂,splitChunks解决了这个问题;另外,将 optimization.runtimeChunk 设置为true(或{name: “manifest”}),便能将入口模块中的runtime部分提取出来。
  * NoEmitOnErrorsPlugin 废弃,由 optimization.noEmitOnErrors 替代,生产环境默认开启。
  * NamedModulesPlugin 废弃,由 optimization.namedModules 替代,生产环境默认开启。
  * ModuleConcatenationPlugin 废弃,由 optimization.concatenateModules 替代,生产环境默认开启。
  * optimize.UglifyJsPlugin 废弃,由 optimization.minimize 替代,生产环境默认开启。

不仅如此,optimization 还提供了如下默认配置:

```

optimization: { minimize: env === ‘production’ ? true : false, // 开发环境不压缩 splitChunks: { chunks: “async”, // 共有三个值可选:initial(初始模块)、async(按需加载模块)和all(全部模块) minSize: 30000, // 模块超过30k自动被抽离成公共模块 minChunks: 1, // 模块被引用>=1次,便分割 maxAsyncRequests: 5, // 异步加载chunk的并发请求数量<=5 maxInitialRequests: 3, // 一个入口并发加载的chunk数量<=3 name: true, // 默认由模块名+hash命名,名称相同时多个模块将合并为1个,可以设置为function automaticNameDelimiter: ‘~’, // 命名分隔符 cacheGroups: { // 缓存组,会继承和覆盖splitChunks的配置 default: { // 模块缓存规则,设置为false,默认缓存组将禁用 minChunks: 2, // 模块被引用>=2次,拆分至vendors公共模块 priority: -20, // 优先级 reuseExistingChunk: true, // 默认使用已有的模块 }, vendors: { test: /[\/]node_modules[\/]/, // 表示默认拆分node_modules中的模块 priority: -10 } } } }


    splitChunks是拆包优化的重点,如果你的项目中包含 element-ui 等第三方组件(组件较大),建议单独拆包,如下所示。
    
    ```
splitChunks: {
    // ...
    cacheGroups: {    
        elementUI: {
            name: "chunk-elementUI", // 单独将 elementUI 拆包
            priority: 15, // 权重需大于其它缓存组
            test: /[\/]node_modules[\/]element-ui[\/]/
        }
    }
}

其更多用法,请参考以上注释或官方文档 <a href="https://webpack.js.org/plugins/split-chunks-plugin/" target="_blank" rel="external noopener">SplitChunksPlugin</a>。

### **升级避坑指南** {#升级避坑指南}

> webpack4不再支持Node 4,由于使用了JavaScript新语法,Webpack的创始人之一,Tobias,建议用户使用Node版本 >= 8.94,以便使用最优性能。

正式升级后,你可能会遇到各种各样的错误,其中,下面一些问题较为常见。

vue-loader v15 需要在 webpack 中添加 VueLoaderPlugin 插件,参考如下。

```

const { VueLoaderPlugin } = require(“vue-loader”); // const VueLoaderPlugin = require(“vue-loader/lib/plugin”); // 两者等同

//… plugins: [ new VueLoaderPlugin() ]


    升级到 webpack4 后,mini-css-extract-plugin 替代 extract-text-webpack-plugin 成为css打包首选,相比之前,它有如下优势:
    
      1. 异步加载
      2. 不重复编译,性能更好
      3. 更容易使用
    
    缺陷,不支持css热更新。因此需在开发环境引入 css-hot-loader,以便支持css热更新,如下所示:
    
    ```
{
    test: /\.scss$/,
    use: [
        ...(isDev ? ["css-hot-loader", "style-loader"] : [MiniCssExtractPlugin.loader]),
        "css-loader",
        postcss,
        "sass-loader"
    ]
}

发布到生产环境之前,css是需要优化压缩的,使用 optimize-css-assets-webpack-plugin 插件即可,如下。

```

const OptimizeCssAssetsPlugin = require(‘optimize-css-assets-webpack-plugin’);

//… plugins: [ new OptimizeCssAssetsPlugin({ cssProcessor: cssnano, cssProcessorOptions: { discardComments: { removeAll: true } } }) ]


    ### **持续加速** {#持续加速}
    
    文章开始,我曾提到,优化才刚刚开始。是的,随着项目越来越复杂,webpack也随之变慢,一定有办法可以进一步压榨性能。
    
    经过很长一段时间的多个项目运行以及测试,以下几点经验**非常有效**。
    
      1. 缩小编译范围,减少不必要的编译工作,即 modules、mainFields、noParse、includes、exclude、alias全部用起来。 
        ```
const resolve = dir => path.join(__dirname, '..', dir);

// ...
resolve: {
    modules: [ // 指定以下目录寻找第三方模块,避免webpack往父级目录递归搜索
        resolve('src'),
        resolve('node_modules'),
        resolve(config.common.layoutPath)
    ],
    mainFields: ['main'], // 只采用main字段作为入口文件描述字段,减少搜索步骤
    alias: {
        vue$: "vue/dist/vue.common",
        "@": resolve("src") // 缓存src目录为@符号,避免重复寻址
    }
},
module: {
    noParse: /jquery|lodash/, // 忽略未采用模块化的文件,因此jquery或lodash将不会被下面的loaders解析
    // noParse: function(content) {
    //     return /jquery|lodash/.test(content)
    // },
    rules: [
        {
            test: /\.js$/,
            include: [ // 表示只解析以下目录,减少loader处理范围
                resolve("src"),
                resolve(config.common.layoutPath)
            ],
            exclude: file => /test/.test(file), // 排除test目录文件
            loader: "happypack/loader?id=happy-babel" // 后面会介绍
        },
    ]
}
  2. 想要进一步提升编译速度,就要知道瓶颈在哪?通过测试,发现有两个阶段较慢:① babel 等 loaders 解析阶段;② js 压缩阶段。loader 解析稍后会讨论,而 js 压缩是发布编译的最后阶段,通常webpack需要卡好一会,这是因为压缩 JS 需要先将代码解析成 AST 语法树,然后需要根据复杂的规则去分析和处理 AST,最后将 AST 还原成 JS,这个过程涉及到大量计算,因此比较耗时。如下图,编译就看似卡住。 
    <a class="fancy-ctn fancybox" title="ParallelUglify" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-ParallelUglify.png" rel="fancy-group"><img title="ParallelUglify" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-ParallelUglify.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-ParallelUglify.png?x-oss-process=image/format,webp" /></a>
    
    实际上,搭载 webpack-parallel-uglify-plugin 插件,这个过程可以倍速提升。[我们](https://www.w3cdoc.com)都知道 node 是单线程的,但node能够fork子进程,基于此,webpack-parallel-uglify-plugin 能够把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程,从而实现并发编译,进而大幅提升js压缩速度,如下是配置。
    
    ```

const ParallelUglifyPlugin = require(‘webpack-parallel-uglify-plugin’);

// … optimization: { minimizer: [ new ParallelUglifyPlugin({ // 多进程压缩 cacheDir: ‘.cache/’, uglifyJS: { output: { comments: false, beautify: false }, compress: { warnings: false, drop_console: true, collapse_vars: true, reduce_vars: true } } }), ] }


        当然,我分别测试了五组数据,如下是截图:
        
        <a class="fancy-ctn fancybox" title="ParallelUglifyPlugin插件启用后编译速度分析" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-0-happyPack-0-dll-1-parallel.34.png" rel="fancy-group"><img title="ParallelUglifyPlugin插件启用后编译速度分析" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-0-happyPack-0-dll-1-parallel.34.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-0-happyPack-0-dll-1-parallel.34.png?x-oss-process=image/format,webp" /></a>
        
        数据分析如下(单位ms): </ol> 
        
        |                                  | 第1次   | 第2次   | 第3次   | 第4次   | 第5次   | 平均      | 速度提升    |
        | -------------------------------- | ----- | ----- | ----- | ----- | ----- | ------- | ------- |
        | webpack3                         | 58293 | 60971 | 57263 | 58993 | 60459 | 59195.8 | - |
        | webpack3搭载ParallelUglifyPlugin插件 | 44380 | 39969 | 39694 | 39344 | 39295 | 40536.4 | 46%     |
        | webpack4                         | 42346 | 40386 | 40138 | 40330 | 40323 | 40704.6 | - |
        | webpack4搭载ParallelUglifyPlugin插件 | 31134 | 29554 | 31883 | 29198 | 29072 | 30168.2 | 35%     |
        
        搭载 webpack-parallel-uglify-plugin 插件后,webpack3 的构建速度能够提升 46%;即使升级到 webpack4 后,构建速度依然能够进一步提升 35%。
        
          1. 现在[我们](https://www.w3cdoc.com)来看看,loader 解析速度如何提升。同 webpack-parallel-uglify-plugin 插件一样,HappyPack 也能实现并发编译,从而可以大幅提升 loader 的解析速度, 如下是部分配置。 
            ```
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
const createHappyPlugin = (id, loaders) => new HappyPack({
    id: id,
    loaders: loaders,
    threadPool: happyThreadPool,
    verbose: process.env.HAPPY_VERBOSE === '1' // make happy more verbose with HAPPY_VERBOSE=1
});

        那么,对于前面 `loader: "happypack/loader?id=happy-babel"` 这句,便需要在 plugins 中创建一个 `happy-babel` 的插件实例。
        
        ```

plugins: [ createHappyPlugin(‘happy-babel’, [{ loader: ‘babel-loader’, options: { babelrc: true, cacheDirectory: true // 启用缓存 } }]) ]


            如下,happyPack开启了3个进程(默认为CPU数-1),运行过程感受下。
            
            <a class="fancy-ctn fancybox" title="happyPack" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-happyPack.gif" rel="fancy-group"><img title="happyPack" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-happyPack.gif" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-happyPack.gif?x-oss-process=image/format,webp" /></a>
            
            另外,像 vue-loader、css-loader 都支持 happyPack 加速,如下所示。
            
            ```
plugins: [
    createHappyPlugin('happy-css', ['css-loader', 'vue-style-loader']),
    new HappyPack({
        loaders: [{
            path: 'vue-loader',
            query: {
                loaders: {
                    scss: 'vue-style-loader!css-loader!postcss-loader!sass-loader?indentedSyntax'
                }
            }
        }]
    })
]

        基于 webpack4,搭载 webpack-parallel-uglify-plugin 和 happyPack 插件,测试截图如下:
        
        <a class="fancy-ctn fancybox" title="搭载两款插件后编译速度分析" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-0-dll-1-parallel.w4.png" rel="fancy-group"><img title="搭载两款插件后编译速度分析" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-0-dll-1-parallel.w4.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-0-dll-1-parallel.w4.png?x-oss-process=image/format,webp" /></a>
        
        数据分析如下(单位ms): </ol> 
        
        |                                    | 第1次   | 第2次   | 第3次   | 第4次   | 第5次   | 平均      | 速度提升 |
        | ---------------------------------- | ----- | ----- | ----- | ----- | ----- | ------- | ---- |
        | 仅搭载ParallelUglifyPlugin            | 31134 | 29554 | 31883 | 29198 | 29072 | 30168.2 | 35%  |
        | 搭载ParallelUglifyPlugin 和 happyPack | 26036 | 25884 | 25645 | 25627 | 25794 | 25797.2 | 17%  |
        
        可见,在搭载 webpack-parallel-uglify-plugin 插件的基础上,happyPack 插件依然能够提升 17% 的编译速度,实际上由于 sass 等 loaders 不支持 happyPack,happyPack 的性能依然有提升空间。更多介绍不妨参考 <a href="http://taobaofed.org/blog/2016/12/08/happypack-source-code-analysis/" target="_blank" rel="external noopener">happypack 原理解析</a>。
        
          1. [我们](https://www.w3cdoc.com)都知道,webpack打包时,有一些框架代码是基本不变的,比如说 babel-polyfill、vue、vue-router、vuex、axios、element-ui、fastclick 等,这些模块也有不小的 size,每次编译都要加载一遍,比较费时费力。使用 DLLPlugin 和 DLLReferencePlugin 插件,便可以将这些模块提前打包。 
            为了完成 dll 过程,[我们](https://www.w3cdoc.com)需要准备一份新的webpack配置,即 webpack.dll.config.js。
            
            ```

const webpack = require(“webpack”); const path = require(‘path’); const CleanWebpackPlugin = require(“clean-webpack-plugin”); const dllPath = path.resolve(__dirname, “../src/assets/dll”); // dll文件存放的目录

module.exports = { entry: { // 把 vue 相关模块的放到一个单独的动态链接库 vue: [“babel-polyfill”, “fastclick”, “vue”, “vue-router”, “vuex”, “axios”, “element-ui”] }, output: { filename: “[name]-[hash].dll.js”, // 生成vue.dll.js path: dllPath, library: “dll[name]” }, plugins: [ new CleanWebpackPlugin(["*.js"], { // 清除之前的dll文件 root: dllPath, }), new webpack.DllPlugin({ name: “dll[name]”, // manifest.json 描述动态链接库包含了哪些内容 path: path.join(__dirname, “./”, “[name].dll.manifest.json”) }), ], };


                接着, 需要在 package.json 中新增 dll 命令。
                
                ```
"scripts": {
    "dll": "webpack --mode production --config build/webpack.dll.config.js"
}

            运行 `npm run dll` 后,会生成 `./src/assets/dll/vue.dll-[hash].js` 公共js 和 `./build/vue.dll.manifest.json` 资源说明文件,至此 dll 准备工作完成,接下来在 wepack 中引用即可。
            
            ```

externals: { ‘vue’: ‘Vue’, ‘vue-router’: ‘VueRouter’, ‘vuex’: ‘vuex’, ’elemenct-ui’: ‘ELEMENT’, ‘axios’: ‘axios’, ‘fastclick’: ‘FastClick’ }, plugins: [ …(config.common.needDll ? [ new webpack.DllReferencePlugin({ manifest: require("./vue.dll.manifest.json") }) ] : []) ]


                dll 公共js轻易不会变化,假如在将来真的发生了更新,那么新的dll文件名便需要加上新的hash,从而避免[浏览器](https://www.w3cdoc.com)缓存老的文件,造成执行出错。由于 hash 的不确定性,[我们](https://www.w3cdoc.com)在 html 入口文件中没办法指定一个固定链接的 script 脚本,刚好,add-asset-html-webpack-plugin 插件可以帮[我们](https://www.w3cdoc.com)自动引入 dll 文件。
                
                ```
const autoAddDllRes = () => {
    const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
    return new AddAssetHtmlPlugin([{ // 往html中注入dll js
        publicPath: config.common.publicPath + "dll/",  // 注入到html中的路径
        outputPath: "dll", // 最终输出的目录
        filepath: resolve("src/assets/dll/*.js"),
        includeSourcemap: false,
        typeOfAsset: "js" // options js、css; default js
    }]);
};

// ...
plugins: [
    ...(config.common.needDll ? [autoAddDllRes()] : [])
]

            搭载 dll 插件后,webpack4 编译速度进一步提升,如下截图:
            
            <a class="fancy-ctn fancybox" title="搭载三款插件后编译速度分析" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-1-dll-1-parallel.w4.png" rel="fancy-group"><img title="搭载三款插件后编译速度分析" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-1-dll-1-parallel.w4.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-1-happyPack-1-dll-1-parallel.w4.png?x-oss-process=image/format,webp" /></a>
            
            数据分析如下(单位ms): </ol> 
            
            |                                         | 第1次   | 第2次   | 第3次   | 第4次   | 第5次   | 平均      | 速度提升 |
            | --------------------------------------- | ----- | ----- | ----- | ----- | ----- | ------- | ---- |
            | 搭载ParallelUglifyPlugin 和 happyPack      | 26036 | 25884 | 25645 | 25627 | 25794 | 25797.2 | 17%  |
            | 搭载ParallelUglifyPlugin 、happyPack 和 dll | 20792 | 20963 | 20845 | 21675 | 21023 | 21059.6 | 22%  |
            
            可见,搭载 dll 后,webpack4 编译速度仍能提升 22%。
            
            综上,[我们](https://www.w3cdoc.com)汇总上面的多次数据,得到下表:
            
            |                                         | 第1次   | 第2次   | 第3次   | 第4次   | 第5次   | 平均      | 速度提升    |
            | --------------------------------------- | ----- | ----- | ----- | ----- | ----- | ------- | ------- |
            | webpack3                                | 58293 | 60971 | 57263 | 58993 | 60459 | 59195.8 | - |
            | webpack4                                | 42346 | 40386 | 40138 | 40330 | 40323 | 40704.6 | 45%     |
            | 搭载ParallelUglifyPlugin 、happyPack 和 dll | 20792 | 20963 | 20845 | 21675 | 21023 | 21059.6 | 181%    |
            
            升级至 webpack4 后,通过搭载 ParallelUglifyPlugin 、happyPack 和 dll 插件,编译速度可以提升181%,整体编译时间减少了将近 2/3,为开发节省了大量编译时间!而且随着项目发展,这种编译提升越来越可观。
            
            实际上,为了获得上面的测试数据,我关闭了 babel、ParallelUglifyPlugin 的缓存,开启缓存后,第二次编译时间平均为 12.8s,由于之前缓存过,编译速度相对 webpack3 将提升362%,即使你已经升级到 webpack4,搭载上述 3 款插件后,编译速度仍能获得 218% 的提升!
            
            ### **编译结果分析** {#编译结果分析}
            
            当然,编译速度作为一项指标,影响的更多是开发者体验,与之相比,编译后文件大小更为重要。webpack4 编译的文件,比之前版本略小一些,为了更好的追踪文件 size 变化,开发环境和生产环境都需要引入 webpack-bundle-analyzer 插件,如下图。
            
            <a class="fancy-ctn fancybox" title="analyzer" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.png" rel="fancy-group"><img title="analyzer" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.png?x-oss-process=image/format,webp" /></a>
            
            文件 size 如下图所示:
            
            <a class="fancy-ctn fancybox" title="analyzer.size" href="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.size_.png" rel="fancy-group"><img title="analyzer.size" src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.size_.png" data-src="https://haomou.oss-cn-beijing.aliyuncs.com/upload/2019/05/webpack-analyzer.size_.png?x-oss-process=image/format,webp" /></a>
            
            ### **面向tree-shaking,约束编码** {#面向tree-shaking,约束编码}
            
            **sideEffects**
            
            从 webpack2 开始,tree-shaking 便用来消除无用模块,依赖的是 ES Module 的静态结构,同时通过在. babelrc 文件中设置 `"modules": false` 来开启无用的模块检测,相对粗暴。webapck4 灵活扩展了无用代码检测方式,主要通过在 `package.json` 文件中设置 `sideEffects: false` 来告诉编译器该项目或模块是 pure 的,可以进行无用模块删除,因此,开发公共组件时,可以尝试设置下。
            
            为了使得 tree-shaking 真正生效,引入资源时,仅仅引入需要的组件尤为重要,如下所示:
            
            ```

import { Button, Input } from “element-ui”; // 只引入需要的组件

                
                ### **结尾** {#结尾}
                
                升级 webpack4 的过程,踩坑是必须的,关键是踩坑后,你能得到什么?
                
                另外,除了文中介绍的一些优化方法,更多的优化策略,正在逐步验证中…
                
                原文:[使用webpack4提升180%编译速度][1]

 [1]: http://louiszhai.github.io/2019/01/04/webpack4/


请遵守《互联网环境法规》文明发言,欢迎讨论问题
扫码反馈

扫一扫,反馈当前页面

咨询反馈
扫码关注
返回顶部