webpack从入门到进阶(二)—— webpack打包优化

738 阅读3分钟

前言

随着项目的不断变大,webpack的打包性能就会影响开发体验,阻碍开发效率提升,webpack打包优化也就变成了至关重要的一环。不得不说的是,webpack打包优化是一个很复杂与繁琐的过程,而且会因不同的项目产生不同的差异,这就导致webpack的打包优化灵活多变。

不过,webpack打包优化总结下来就两个大的方向:

  • 压缩打包体积
  • 提升打包速度

下面就从这两个方向出发,介绍一下如何对 webpack 项目进行优化。

环境

  • "node": "16.5.0"
  • "webpack": "^5.64.2",
  • "webpack-cli": "^4.9.1",
  • "webpack-dev-server": "^4.5.0",

压缩打包体积

1. 打包体积分析工具

webpack-bundle-analyzer:一个 plugin 和 CLI 工具,它将 bundle 内容展示为一个便捷的、交互式、可缩放的树状图形式,便于对打包后的代码进行分析。

npm i webpack-bundle-analyzer -D

包含各个 bundle 的体积分析,效果如下:

image.png

2. 代码压缩

  • js压缩

webpack5 内置了terser-webpack-plugin插件,无需安装。

    new TerserPlugin({
        exclude: /node_modules/, // 排除node_modules
        parallel: true, // 开启多线程
        extractComments: false, // 不生成 license.text
        terserOptions: {
          toplevel: true, // 最高级别,删除无用代码
        }
    }),
  • css压缩

通过安装 css-minimizer-webpack-plugin,使用 cssnano 优化和压缩 CSS。

npm i css-minimizer-webpack-plugin -D

具体配置如下:

    new CssMinimizerPlugin({
        parallel: true, // 开启并行压缩
        exclude: /node_modules/,
    }),

3. 代码分离

通过将公共代码或者第三方库依赖提取出来好处有多个:

  • 可以有效的减少重复打包代码,减少打包体积
  • 第三方库基本不变,减少重复打包次数
  • 减少bundle体积,加快资源加载

具体配置内容:

    splitChunks: {
        // 分块策略(common chunk strategy)
        // priority 优先级
        cacheGroups: {
            // loadsh: {
            //   test: /[\\/]node_modules[\\/](loadsh)[\\/]/,
            //   name: 'loadsh',
            //   chunks: 'initial',
            //   priority: -30,
            // },
            // react: {
            //   test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
            //   name: 'react',
            //   chunks: 'initial',
            //   priority: -40,
            // },
            vendors: {
              test: /[\\/]node_modules[\\/]/,
              name: 'vendors',
              chunks: 'initial',
              priority: -50,
              reuseExistingChunk: true,
            },
            commons: {
              name: 'commons',
              chunks: 'initial',
              minChunks: 2,
              priority: -60,
              reuseExistingChunk: true,
            },
        }
    },

4. css抽离

通过配置mini-css-extract-plugin,将css抽取到独立的css文件中,然后通过link的方式引入。

npm i mini-css-extract-plugin -D

具体配置如下:

    new MiniCssExtractPlugin({
      filename: '[name].[contenthash:8].css',
      chunkFilename: '[id].css',
    }),

5. 外部依赖扩展

将一些体积大、不需要修改的第三方库单独剥离,而不是打包到bundle中去,然后通过cdn引入,提升打包速度的同时,优化资源加载体验。

具体配置:

    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM',
        'loadsh': '_',
    },

6. tree sharking

通过webpack内置的tree sharking对无用的代码进行剔除。通过在package.json中配置sideEffects来标记文件为副作用。

注意,所有导入文件都会受到 tree shaking 的影响。这意味着,如果在项目中使用类似 css-loader 并 import 一个 CSS 文件,则需要将其添加到 side effect 列表中,以免在生产模式中无意中将它删除

具体配置:

    "sideEffects": [
        "**/*.scss"
    ]

提升打包速度

1. 打包速度查看工具

speed-measure-webpack-plugin: 测量webpack构建速度。

效果如下:

image.png

2. 控制loader的打包范围

loader 支持通过配置 test、include和exclude属性来控制打包范围,有效级依次为 exclude > include > test;

我个人倾向于配置exclude, 具体配置以 babel-loader 为例:

    {
        test: /\.(t|j)sx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true, // 开启 babel-loader 缓存
            },
          },
        ]
    }

3. 忽略依赖

通过配置 noParse,防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中 不应该含有 importrequiredefine 的调用,或任何其他导入机制。

具体配置:

    noParse: /react|react-dom|lodash/,

4. 配置缓存

  • webpack5提供了 cache 属性,缓存生成的 webpack 模块和 chunk,来改善构建速度。

具体配置:

    cache: {
        type: 'filesystem',
        compression: 'gzip',
    },
  • babel-loader 配置 cacheDirectory

cacheDirectory: true

5. 开启多线程

  • 通过使用 thread-loader 来开启多进程,将耗时的 loader 放在一个独立的 worker 池中运行,加快 loader 构建速度。

项目体积不大的话,不建议配置thread-loader开启多进程

以babel-loader为例,具体配置如下:

    test: /\.(t|j)sx?$/,
        exclude: /node_modules/,
        use: [
            "thread-loader",
            {
                loader: 'babel-loader',
                options: {
                    cacheDirectory: true, // 开启 babel-loader 缓存
                },
            },
        ]
    }
  • 通过配置happypack开启多个子进程进行编译,来提升打包速度

不建议使用,相关库已不维护

webpack内置打包优化

  1. Scope Hoisting
  • 将模块代码内置,而不是包装在单独的闭包函数中
  • 减少代码体积
  • 提升代码运行速度

相关文章推荐:

模块化的演变与实现

代码仓库地址