UMI 配置优化 - 优化打包体积,提高打包速度、提高热更新速度etc

8,531 阅读3分钟

UMI 配置优化 - 提高打包速度、提高开发速度、减少打包体积

项目越来越大,打包后的体积很大,打包时间也很长;开发时每次运行也需要很久,随便改动一个地方都要等2分钟以上才能看到效果(热更新太慢)。针对这些问题,是时候展示我真正的水平了(伊泽瑞尔)。

优化打包体积

优化前的模块分析图如下

image.png

可以看到总的打包体积为 23.82MB, gizped 后也有 7.03MB。 再看每个chunk,可以发现有很多公共的模块出现在多个chunk里面,比如ant相关的,lodash相关的等,那我们把那些公共的依赖单独打包到一起即可。

// config/plugin.ts
const webpackPlugin = (config: any) => {
  config.merge({
    optimization: {
      minimize: true,
      splitChunks: {
        chunks: 'async',
        minSize: 30000,
        minChunks: 1,
        automaticNameDelimiter: '.',
        cacheGroups: {
          lfpantdesigns: {
            name: 'antdesigns',
            chunks: 'all',
            test: /[\\/]node_modules[\\/](@antv|antd|@ant-design)/,
            priority: 10,
          },
          lfpvendors: {
            name: 'vendors',
            chunks: 'all',
            test: /[\\/]node_modules[\\/](lodash|moment|react|dva|postcss|mapbox-gl)/,
            priority: 10,
          },
          // // 最基础的
          // 'async-commons': {
          //   // 其余异步加载包
          //   name: 'async-commons',
          //   chunks: 'async',
          //   minChunks: 2,
          //   priority: 2,
          // },
          lfpcommons: {
            name: 'commons',
            // 其余同步加载包
            chunks: 'all',
            minChunks: 2,
            priority: 1,
            // 这里需要注意下,webpack5会有问题, 需加上这个 enforce: true,
            // refer: https://github.com/webpack-contrib/mini-css-extract-plugin/issues/257#issuecomment-432594711
            enforce: true,
          },
        },
      },
    },
  });
};
// config/config.ts
import { defineConfig } from 'umi';
import webpackPlugin from './plugin';

// 这里因为 local 开发环境不需要这些,所以做了区分
export default defineConfig({
  chunks:
    REACT_APP_ENV === 'local'
      ? undefined
      : ['antdesigns', 'vendors', 'commons', 'umi'],
  chainWebpack: REACT_APP_ENV === 'local' ? undefined : webpackPlugin,
}

经过优化后的重新打包分析,得到如下图:

image.png

可以看到总的打包体积为 3.32.82MB, gizped 后只有 1.01MB。分别优化了 86%85.6%,very good! 【对症下药很有效,哈哈!】

ps: 还可以把常用的公共依赖如 antdreact等放到extenals里面,然后在index.html里额外引入。因为我们有其他考虑,所以没有做这一步。

提高打包速度

提到打包速度,当然少不了多线程打包(happypack),如下:

const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({
  size: require('os').cpus().length,
});

const webpackPlugin = (config: any) => {
  config.plugin('HappyPack').use(HappyPack, [
    {
      id: 'js',
      loaders: ['babel-loader'],
      threadPool: happyThreadPool,
    },
  ]);
  // ... 其他配置
};

提高打包速度2

wepback5 可以使用自带的 cache 配置就可以到的 webpack4 中的各种 cache效果,配置也很简单。原理就是把打包后的文件缓存起来,通常我们会选择缓存到 filesystem(如果是开发环境,缓存到memery)。配置如下:

const webpackPlugin = (config: any) => {
   config.cache({
    type: 'filesystem',
    allowCollectingMemory: true,
    buildDependencies: {
      config: [__filename],
    },
  });
  // ... 其他配置
};

提高热更新速度

Umi 3.5 开始就可以开启 mfsu (模块联邦速度提升),开启后热更新速度大大提升!!它会检测哪些地方有更改,只热更新那一部分的模块。

image.png

image.png 使用之后开发体验大幅度上升,但是发现切换分支后重新npm run start会报错:

经过我的排查是因为每次生成的 .umi 文件在作怪,如果每次 npm run start 之前就把这个文件删除又能正常跑起来!

但是手动删除 .umi 文件很麻烦,还容易忘记,自动化才是最好的。于是我利用 package.json 里面的scripts 配置了一个 prestart,可以在每次 start 之前就执行,命令如下:

"prestart": "rm -rf ./src/.umi",

image.png

这样切换分支之后每次 npm run start 都没有问题了,前端同学表示真香!

因为每次改动代码后 umi 会自动重新跑代码,切换分支也是。这就导致一切换分支就会重跑,还没来得及运行 prestart, 但也不是每次都会失败(还是看2个分支有多大的区别,看最终 .umi 改动多大),如果失败那就手动删除一下 .umi 文件即可。

给出我的 config/config.ts 文件配置

import { defineConfig } from 'umi';
import defaultSettings from './defaultSettings';
import routes from './routes';
import env from './env';
import webpackPlugin from './plugin';

const { REACT_APP_ENV, PORT } = process.env;
const eConfig = env[REACT_APP_ENV || 'dev'];

export default defineConfig({
  hash: true,
  // devtool: 'inline-source-map', // Default: cheap-module-source-map in dev, false in build
  publicPath: eConfig.publicPath,
  runtimePublicPath: true,
  antd: {},
  dva: {
    hmr: true,
  },
  history: {
    type: 'hash',
  },
  mock: false,
  locale: false,
  dynamicImport: {
    loading: '@/components/PageLoading/index',
  },
  targets: {
    chrome: 90,
    firefox: 88,
    ie: 11,
    safari: false,
    ios_saf: false,
    opera: false,
    edge: false,
    ios: false,
  },
  define: {
    REACT_APP_ENV: REACT_APP_ENV || 'dev',
    eConfig: eConfig,
    PORT,
  },
  routes,
  theme: {
    'primary-color': defaultSettings.primaryColor,
  },
  title: false,
  ignoreMomentLocale: true,
  manifest: {
    basePath: '/',
  },
  chunks:
    REACT_APP_ENV !== 'local'
      ? undefined
      : ['antdesigns', 'vendors', 'commons', 'umi'],
  chainWebpack: REACT_APP_ENV !== 'local' ? undefined : webpackPlugin,
  webpack5: {},
  mfsu: {},
  esbuild: {},
});