Webpack 优化总结

336 阅读2分钟

速度优化

利用缓存

1. babel-loader

使用loader: 'babel-loader?cacheDirectory=true'开启缓存,babel-loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,之后的 webpack 构建将会尝试读取缓存,来避免在每次执行时可能产生的高性能消耗的 Babel 重新编译过程。

{
    test: /\.js$/,
    exclude: /(node_modules)/,
    loader: 'babel-loader?cacheDirectory=true',
},

2. HardSourceWebpackPlugin

HardSourceWebpackPlugin 可以对模块进行缓存,对于二次构建的速度提升非常显著。

多进程构建

1. thread-loader

thread-loader 可以使其之后的 loader 在一个单独的 worker pool 中运行,每个 worker 都是一个单独的有 600ms 限制的 node.js 进程

{
    test: /\.js$/,
    exclude: /(node_modules)/,
    use: [
      'thread-loader',
      'babel-loader?cacheDirectory=true',
    ],
},

2. happypack

happypack 会在 webpack 每次解析一个模块时都会拿到该模块和它的依赖,将它们分发给多个 node 子进程,处理完后再将结果返回给主进程。

3. 并行压缩

webpack 在 production 环境默认使用 TerserPlugin 压缩 js,配置选项 parallel: true 开启并行压缩:

optimization: {
    minimizer: [
        new TerserPlugin({
            parallel: true,
        }),
    ],
},

预编译

通过使用 DLLPlugin 和 DLLReferencePlugin 拆分 bundles大大提升构建的速度。通常像 vue 这样不常发生变动的库可以预编译为单独的包给 html 引用,这样就避免 webpack 频繁地构建这些库,大大节省编译时间。

1.使用如下单独配置打包 dll.js

// webpack.dll.js
module.exports = {
    mode: 'none',
    entry: {
        vendors: [
            'vue',
            'vue-router',
        ],
    },
    output: {
        path: path.join(__dirname, './static/lib'),
        filename: '[name].dll.js',
        library: '[name]_[hash:8]',
    },
    plugins: [
        new webpack.DllPlugin({
            name: '[name]_[hash:8]',
            path: path.join(__dirname, './static/lib/[name]-manifest.json'),
        }),
    ],
}

2.在 webpack 配置中添加 DllReferencePlugin 插件:

new webpack.DllReferencePlugin({
    manifest: require('./static/lib/vendors-manifest.json'),
}),

3.在 html 中引入 dll.js:

<script src="../static/lib/vendors.dll.js"></script>

体积优化

提取公共模块

SplitChunksPlugin 是 webpack4 升级的最重要的配置之一,它的作用是进行代码拆分,我们可以立利用它提取公共模块。

optimization: {
    splitChunks: {
        chunks: 'all',
        name: 'commons',
    },
},

预编译

同上。

其他

webpack 在 production 会默认开启一些优化功能:

  • tree shaking
  • scope hoisting

代码/性能优化

1. 动态导入

动态导入 (dynamic import) 是 webpack 实现 懒加载(按需加载)的方式,会先把代码在一些逻辑断点处分离开,然后在主代码块中完成某些操作后,通过 requireEnsure 方法动态创建 script 标签加载相应 js。vue 中可以使用 异步组件 实现组件的懒加载。

2. 预取/预加载模块

Webpack v4.6.0+ 增加了对预获取和预加载 (prefetch/preload module) 的支持。

在使用上述动态导入是通过魔术注释告知 webpack 。例如下面的 vue 异步组件,通过 /* webpackPrefetch: true */ 标记为需要 prefetch 的模块资源:

{
	components: {
        MyText: () => import(/* webpackPrefetch: true */ './components/MyText'),
    },
}

就会在页面 head 中添加:

<link rel="prefetch" as="script" href="components/MyText.chunk.js">

webpack 官网也提供了一些改进构建/编译性能的实用技巧:构建性能