Skip to content

鼓励作者:欢迎 star 或打赏犒劳

Webpack 4 打包优化(CRA 项目)

react-app-rewired + customize-cra 方案为例

使用 dayjs 替换 moment

sh
yarn add -D antd-dayjs-webpack-plugin
# OR
npm install -D antd-dayjs-webpack-plugin

修改 config-overrides.js 文件

js
const { override, addWebpackPlugin } = require('customize-cra')
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin')

module.exports = override(addWebpackPlugin(new AntdDayjsWebpackPlugin()))

修改 项目入口 index.js 文件

js
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'

dayjs.locale('zh-cn')

相关资料

修改 optimization 配置

原因

  1. Webpack 4 默认分包配置
    1. 新的 chunk 可以被共享,或者模块来自于 node_modules 文件夹
    2. 新的 chunk 体积大于 30kb(在进行 min+gz 之前的体积)
    3. 当按需加载 chunks 时,并行请求的最大数量小于或等于 5
    4. 当加载初始化页面时,并发请求的最大数量小于或等于 3
  2. CRA 默认配置只有 chunksname

优化过程

1. 在 CRA 默认配置下

在 CRA 默认配置下

通过分析可以看到最终包大小为 5.43MB,同时 antd 的 table 组件被重复打包了多次,这就不符合默认配置的规则 1 和规则 2

2. 修改 splitChunks.maxAsyncRequests 为 10 时

修改 splitChunks.maxAsyncRequests 为 10 时

通过分析可以看到最终包大小为 2.65MB,同时 antd 的 table 被分离了出来,这说明 Webpack 4 默认分包规则中后面两条并行请求限制规则会影响前两条规则

所以 Webpack 4 中上述配置造成的影响: 一个组件被多个页面,这个组件会被打包到每个页面的 bundle 中,如果这个组件够小,我们可以忽略不计;但是在后台管理系统这种场景下,这个默认的打包配置非常不合理了,我们在使用 antdtable 组件时,这个组件在 min+gz 前有 66kb,在默认配置下会走 【新的 chunk 可以被共享,或者模块来自于 node_modules 文件夹】 这条策略,但是因为还有并行请求这条策略的限制,当并行请求超过 5 时,还是会把 table 组件打包到页面的 bundle 中,这样就十分浪费资源,所以就需要我们优化这个默认策略了

缓存组配置

  1. 分离不常更新的 node_modules 模块
    1. 基础库
    2. 第三方 ui 组件库
  2. 根据上一步分离的模块大小判断具体分几个包
  3. 在细分缓存组配置时要考虑 HTTP 1.x 的并发限制

修改 config-overrides.js 文件

js
const { override } = require('customize-cra')

const customWebpackConfig = (config) => {
  // 不生成 runtime-main
  config.optimization.runtimeChunk = false
  // 配置缓存组
  config.optimization.splitChunks = {
    chunks: 'all',
    cacheGroups: {
      // react 相关基础库
      libs: {
        test: /[\\/]node_modules[\\/](react|react-dom|react-router(-dom)?)[\\/]/,
        name: 'libs',
        chunks: 'all',
        enforce: true, // 忽略 splitChunks.minSize、splitChunks.minChunks、splitChunks.maxAsyncRequests 和 splitChunks.maxInitialRequests 选项,并始终为此缓存组创建 chunk
        priority: 100 // 一个模块可以属于多个缓存组。分包优化将优先考虑具有更高 priority(优先级)的缓存组
      },
      // antd 中的 rc 模块
      rc: {
        test: /[\\/]node_modules[\\/]rc-/,
        name: 'rc',
        chunks: 'all',
        enforce: true,
        priority: 90
      },
      // antd 和 @ant-design 图标
      antd: {
        test: /[\\/]node_modules[\\/](antd|@ant-design)[\\/]/,
        name: 'antd',
        chunks: 'all',
        enforce: true,
        priority: 90
      },
      // 其他 node_modules 包
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        chunks: 'all',
        enforce: true
      }
    }
  }
  return config
}

module.exports = override(customWebpackConfig)

优化图

相关资料

如有转载或 CV 的请标注本站原文地址