Webpack构建性能优化指南

本指南翻译自webpack官方性能指南文档:https://webpack.js.org/guides/build-performance/

构建性能

本指南涵盖了对增进构建或编译性能的一些有效的提示。


General

以下提示对开发环境或者生产环境都有效。

Stay Up to Date

保持最新的webpack版本。我们总是在改进webpack的性能。目前最新的webpack版本为:v4.41.4
使用最新的Node.js也可以提升性能。同样的,保持npm或者yarn这样的包管理器的版本也同样可以提升性能。新版本拥有更高效的模块树与更快的解析速度。

Loaders

对需要的模块采用对应Loader,例如:

module.exports = {
  //...
  module: {
    rules: [
      {
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        loader: 'babel-loader',
      },
    ],
  },
};

以上示例通过include属性圈定了babel-loader的作用范围,如果不使用该属性,则babel-loader将会对所有的js文件作业。

Bootstrap

每一个额外的Loader或者插件都会消耗一定的启动时间,尝试使用尽可能少的工具。

Resolving

以下几点可以提升解析速度:

  • 降低resolve.modules、resolve.extensions、resolve.mainFiles、resolve.descriptionFiles这些选项中item的数量,因为它们会导致更频繁的IO。
  • 如果不使用symlinks(例如npm link或yarn link),那么将resolve.symlinks设为false。
  • 如果使用了自定义的插件,则将resolve.cacheWithContext设置为false。

Dlls

使用DllPlugin插件将不常变更的代码进行单独编译。尽管这会增加构建的复杂度,但会提高应用的编译速度。

Smaller = Faster

降低被编译文件的体积同样可以提升构建性能。想办法使chunk更小。

  • 使用体积更小/熟练更少的库。
  • 在多页应用中使用SplitChunksPlugin插件。
  • 在多页应用中的async模式下使用SplitChunksPlugin插件。
  • 移除未被使用的代码。
  • 只编译当前你正在开发的代码。

Worker Pool

thread-loader可将开销昂贵的loader转移至线程池执行。不过不能使用太多的线程,这对node.js运行时来说引发过载。另外也要降低线程与主进程模块之间的信息传输,因为IPC是昂贵的。

Persistent cache

通过cache-loader开启持续缓存的能力。

Custom plugins/loaders

对于自定义的插件与loader,请自行分析优化性能。

Progress plugin

移除ProgressPlugin可能会缩短少许的构建时间。但是要记住,这并不会带来可观的构建速度优化,所以在移除该插件之前要平衡好取舍。

Development

以下优化手段在开发环境是尤其有效的。

Incremental Builds

使用webpack的watch模式,别使用其它工具来监听文件的变化再来调用webpack。webpack内建的watch模式会保留时间戳的信息并将该信息给到编译器以使缓存失效。

在一些设置中,监听是靠轮询来完成的。随着监听文件数量的增多,这会增加大量CPU的计算量。在这种情况下,可以通过watchOptions.poll来增加轮询间隔。

Compile in Memory

以下工具通过内存编译以及内存伺服的方式提升了性能,可以尝试使用:

  • webpack-dev-server
  • webpack-hot-middleware
  • webpack-dev-middleware

stats.toJson speed

webpack4默认情况下会通过stats.toJson()输出大量数据。除非在增量步骤中是必须的,否则避免检索stats对象。webpack-dev-server在v3.1.3之后的版本针对于这一问题做了大量的性能方面的优化。

Devtool

不同的devtool设置所引起的性能是不同的,要有这个意识。

  • "eval"拥有最好的性能,不过它不会保留源代码。
  • "cheap-source-map"带来的性能损耗还可以,它会有一些性能损耗。
  • "eval-source-map"用来增量构建。
    在大多数情况下,cheap-module-eval-source-map是最适中的方案。

Avoid Production Specific Tooling

确保工具、插件、loader只是用于生产环境而不是开发环境,否则会带来不需要的资源开销。例如,在开发环境下通常不需要对代码做混淆与压缩,比如使用TerserPlugin来实现这个能力,开发环境下是不需要的。下面这些工具在开发环境下一般都是需要被摘出来的:

  • TerserPlugin
  • ExtractTextPlugin
  • [hash]/[chunkhash]
  • AggressiveSplittingPlugin
  • ModuleConcatenationPlugin

Minimal Entry Chunk

WebPack仅向文件系统发送更新的chunks。对于一些配置选项,(例如:HMR,[name]/[chunkhash]inOutput.chunkfilename,[hash])除更改的chunks外,入口chunk是无效的。

使入口chunk保持小的体量才能使更新的成本更低。下面的代码块会抽取一个包含仅仅是在运行时包含其它子块的chunk:

new CommonsChunkPlugin({
  name: 'manifest',
  minChunks: Infinity,
});

Avoid Extra Optimization Steps

webpack会进行额外的逻辑运算工作来优化输出代码的体量与加载性能。下面优化选项对于小型的项目代码来说是有效的,不过对于大型项目来说那就不太适用了:

module.exports = {
  // ...
  optimization: {
    removeAvailableModules: false,
    removeEmptyChunks: false,
    splitChunks: false,
  },
};

Output Without Path Info

webpack有能力在输出的Bundle中携带路径信息。然而,在有上千个组件的项目中会导致垃圾收集器的压力。可使用以下选项将这个功能关闭:

module.exports = {
  // ...
  output: {
    pathinfo: false,
  },
};

Node.js Versions 8.9.10-9.11.1

在Node.js 8.9.10 ~ 9.11.1的版本区间内,Map和Set的实现在性能方面表现很差,所以这影响到了webpack的编译时间。在这之前与之后的版本都没有受到影响,所以要避免使用这个版本内的Node.js。

#Production
以下优化选项尤其适用于生产环境

Multiple Compilations

当使用多重编译时,下面这些工具可能会帮到你:

  • parallel-webpack 可以在线程池中完成编译。
  • cache-loader 缓存可在多次编译中共享。

Source Maps

SourceMap是非常昂贵的,你真的需要它吗?

一些工具的问题

下面这些工具含有一些问题,这些问题会导致性能上有一些影响:

Babel

  • 降低preset/plugin的数量。

TypeScript

  • 在单独的进程中使用fork-ts-checker-webpack-plugin用于类型检查。
  • 配置loader跳过类型检查。
  • 在happyPackMode: true或transpileOnly: true中使用ts-loader。

Sass

  • node-sass有一个Bug,这个bug会阻断Node.js线程池中的线程。当通过thread-loader使用它时,请将workerParallelJobs设置为2。
发布了72 篇原创文章 · 获赞 126 · 访问量 64万+

猜你喜欢

转载自blog.csdn.net/u011064099/article/details/103684050