umi项目优化

此场景在项目中遇见,一看文档,二看 umi 开发社区中的大佬的优化,三结合自己以前的 webpack 配置经验总结而出。

为防止文档链接失效,笔者准备有些必要时候能抄就抄,保存文章整体性。

注意:此项目主要是笔者的经验之谈以及代码大小优化部分。

介绍完毕,准备开干:

查看包结构

首先,要查看代码尺寸,最直观的方式是 build 它,查看生成文件大小,不过 umi 中自带了查看包大小的 webpack 插件 analyze,所以我们需要在 package.json 中配置 script 脚本:

{
  "script": {
    "analyze": "cross-env  ANALYZE=1 umi dev",
    "build:analyze": "cross-env  ANALYZE=1 umi build"
  }
}

执行 umi devumi build 时,增加环境变量ANALYZE=1 可查看产物的依赖占比

配置 externals

这个在 webpack 中常用到,就是比如基本库,可以通过 externals 的配置引入相关的 umd 文件,减少编译消耗

比如 react 和 react-dom:

export default {
  // 配置 external
  externals: {
    react: "window.React",
    "react-dom": "window.ReactDOM",
  },
  // 引入被 external 库的 scripts
  // 区分 development 和 production,使用不同的产物
  scripts:
    process.env.NODE_ENV === "development"
      ? [
          "https://gw.alipayobjects.com/os/lib/react/16.8.6/umd/react.development.js",
          "https://gw.alipayobjects.com/os/lib/react-dom/16.8.6/umd/react-dom.development.js",
        ]
      : [
          "https://gw.alipayobjects.com/os/lib/react/16.8.6/umd/react.production.min.js",
          "https://gw.alipayobjects.com/os/lib/react-dom/16.8.6/umd/react-dom.production.min.js",
        ],
};

减少补丁尺寸

因为本项目为移动端项目,所以这块的配置如下

targets: {
    chrome: 49,
    firefox: 45,
    safari: 10,
    edge: 13,
    ios: 10,
},

调整 splitChunks 策略,减少整体尺寸

做一块的前提是将dynamicImport(按需加载),在没开启按需加载前,umi 只会生成一个 js 和一个 css,即 umi.jsumi.css 。优点是省心,部署方便,缺点是对用户来说初次打开网站会比较慢。这显然是要优化的,因为前端优化中按需加载是肯定要做的,具体如何做可以查看 UmiJS 的官网,这里不做描述。

但如果开了 dynamicImport,产物特别大,每个出口文件都包含了相同的依赖,比如 自己的 UI 库,可尝试通过 splitChunks 配置调整公共依赖的提取策略

比如:

export default {
  chunks: ["vendors", "umi"],
  chainWebpack: function (config, { webpack }) {
    config.merge({
      optimization: {
        splitChunks: {
          chunks: "all",
          minSize: 30000,
          minChunks: 3,
          automaticNameDelimiter: ".",
          cacheGroups: {
            vendor: {
              name: "vendors",
              test({ resource }) {
                return /[\\/]node_modules[\\/]/.test(resource);
              },
              priority: 10,
            },
          },
        },
      },
    });
  },
};

图片资源压缩

UI 提供图片素材后,可通过 TinyPNG(https://tinypng.com/) 或者 pngquant 等网站对图片经验进一步压缩

选用可替代的依赖库

大的依赖包能换就换,例如 monent 库比较大,我们可以替换成 dayjs,或者如果只用到其中的几个方法(例如 lodash 中的防抖节流)完成可以自己写

开启 gzip 压缩

下载 webpack 插件

npm i compression-webpack-plugin @types/compression-webpack-plugin --save

进入 umi 的配置文件中,引入并配置 gzip 压缩

import CompressionPlugin from 'compression-webpack-plugin';
import { defineConfig } from 'umi';
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i;

export default defineConfig({
    ...
    chainWebpack(memo: any, args: any) {
        memo.plugin('CompressionPlugin').use(
            new CompressionPlugin({
                filename: '[path].gz[query]',
                algorithm: 'gzip',
                test: productionGzipExtensions,
                threshold: 10240,
                minRatio: 0.8,
                deleteOriginalAssets: false,
            }),
        );
    },
})

以上就是 umi 项目的优化方案。

经过压缩后,30 个页面的代码从没优化前的 3M 代码,压缩到 2.5M(含 gzip),虽然压缩大小没怎么变化,但是用户体验有了质的飞跃。

配合 nginx 的 gzip 压缩以及缓存策略,更能加快页面访问

参考资料