webpack使用技巧之构建优化

184 阅读31分钟

前言

webpack是现在流行的工程化工具,本篇文章将介绍webpack使用的优化技巧,提高程序的构建速度

缓存 : 

将第三方库独立成单独的块,利用浏览器的缓存达到优化性能的目的

It's also good practice to extract third-party libraries, such as lodash or react, to a separate vendor chunk as they are less likely to change than our local source code. This step will allow clients to request even less from the server to stay up to date. This can be done by using the cacheGroups option of the SplitChunksPlugin demonstrated in Example 2 of SplitChunksPlugin. Lets add optimization.splitChunks with cacheGroups with next params and build:

建构优化:

webpack.js.org/guides/buil…

通用优化 

1.使用最新版本的webpack;保持node.js 和包管理器(npm or yarn)更新也是有帮助的

2.将加载器只用于要打包的模块,如

Use the include field to only apply the loader modules that actually need to be transformed by it:

const path = require('path');

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

3.使用较少的loader和plugin (每个loader/plugin都有启动时间

Each additional loader/plugin has a bootup time. Try to use as few tools as possible

4.resolve

官网resolve配置项介绍

resolve常用配置项

The following steps can increase resolving speed:

Dlls

Use the DllPlugin to move code that is changed less often into a separate compilation. This will improve the application's compilation speed, although it does increase complexity of the build process.

Smaller = Faster

Decrease the total size of the compilation to increase build performance. Try to keep chunks small.

  • Use fewer/smaller libraries.
  • Use the SplitChunksPlugin in Multi-Page Applications.
  • Use the SplitChunksPlugin in async mode in Multi-Page Applications.
  • Remove unused code.
  • Only compile the part of the code you are currently developing on.

Worker Pool

The thread-loader can be used to offload expensive loaders to a worker pool.

Warning

Don't use too many workers, as there is a boot overhead for the Node.js runtime and the loader. Minimize the module transfers between worker and main process. IPC is expensive.

Persistent cache

官方文档

Use cache option in webpack configuration. Clear cache directory on "postinstall" in package.json.

Tip

We support yarn PnP version 3 yarn 2 berry for persistent caching.

Custom plugins/loaders

Profile them to not introduce a performance problem here.

Progress plugin

It is possible to shorten build times by removing ProgressPlugin from webpack's configuration. Keep in mind, ProgressPlugin might not provide as much value for fast builds as well, so make sure you are leveraging the benefits of using it.

开发优化

以下配置针对开发环境特别有效

Incremental Builds

Use webpack's watch mode. Don't use other tools to watch your files and invoke webpack. The built-in watch mode will keep track of timestamps and passes this information to the compilation for cache invalidation.

In some setups, watching falls back to polling mode. With many watched files, this can cause a lot of CPU load. In these cases, you can increase the polling interval with watchOptions.poll.

Compile in Memory

The following utilities improve performance by compiling and serving assets in memory rather than writing to disk:

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

stats.toJson speed

Webpack 4 outputs a large amount of data with its stats.toJson() by default. Avoid retrieving portions of the stats object unless necessary in the incremental step. webpack-dev-server after v3.1.3 contained a substantial performance fix to minimize the amount of data retrieved from the stats object per incremental build step.

Devtool

Be aware of the performance differences between the different devtool settings.

  • "eval" has the best performance, but doesn't assist you for transpiled code.
  • The cheap-source-map variants are more performant if you can live with the slightly worse mapping quality.
  • Use a eval-source-map variant for incremental builds.
Tip

In most cases, **eval-cheap-module-source-map** is the best option.

Avoid Production Specific Tooling

Certain utilities, plugins, and loaders only make sense when building for production. For example, it usually doesn't make sense to minify and mangle your code with the TerserPlugin while in development. These tools should typically be excluded in development:

  • TerserPlugin
  • [fullhash]/[chunkhash]/[contenthash]
  • AggressiveSplittingPlugin
  • AggressiveMergingPlugin
  • ModuleConcatenationPlugin

Minimal Entry Chunk

Webpack only emits updated chunks to the filesystem. For some configuration options, (HMR, [name]/[chunkhash]/[contenthash] in output.chunkFilename, [fullhash]) the entry chunk is invalidated in addition to the changed chunks.

Make sure the entry chunk is cheap to emit by keeping it small. The following configuration creates an additional chunk for the runtime code, so it's cheap to generate:

module.exports = {
  // ...
  optimization: {
    runtimeChunk: true,
  },
};

Avoid Extra Optimization Steps

Webpack does extra algorithmic work to optimize the output for size and load performance. These optimizations are performant for smaller codebases, but can be costly in larger ones:

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

Output Without Path Info

Webpack has the ability to generate path info in the output bundle. However, this puts garbage collection pressure on projects that bundle thousands of modules. Turn this off in the options.output.pathinfo setting:

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

Node.js Versions 8.9.10-9.11.1

There was a performance regression in Node.js versions 8.9.10 - 9.11.1 in the ES2015 Map and Set implementations. Webpack uses those data structures liberally, so this regression affects compile times.

Earlier and later Node.js versions are not affected.

TypeScript Loader

To improve the build time when using ts-loader, use the transpileOnly loader option. On its own, this option turns off type checking. To gain type checking again, use the ForkTsCheckerWebpackPlugin. This speeds up TypeScript type checking and ESLint linting by moving each to a separate process.

module.exports = {
  // ...
  test: /\.tsx?$/,
  use: [
    {
      loader: 'ts-loader',
      options: {
        transpileOnly: true,
      },
    },
  ],
};
Tip

There is a full example on the ts-loader GitHub repository.