2020-09-12

umi.js

如果遇到编译慢,增量编译慢,内存爆掉,OOM 等问题,可尝试以下方法。

配置 nodeModulesTransform 为 { type: 'none' }

需要 Umi 3.1 。

Umi 默认编译 node_modules 下的文件,带来一些收益的同时,也增加了额外的编译时间。如果不希望 node_modules 下的文件走 babel 编译,可通过以下配置减少 40% 到 60% 的编译时间。

export default {

  nodeModulesTransform: {

    type: 'none',

    exclude: [],

  },

}

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


配置 externals

对于一些大尺寸依赖,比如图表库、antd 等,可尝试通过 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.13.1/umd/react.development.js',

    'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.development.js',

  ] : [

    'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',

    'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',

  ],

}

注意:

如果要支持 IE10 或以下,external react 还需要额外引入补丁,比如 https://gw.alipayobjects.com/os/lib/alipay/react16-map-set-polyfill/1.0.2/dist/react16-map-set-polyfill.min.js

如果 external antd,需同时 external 额外的 moment、react 和 react-dom,并在 antd 前引入

减少补丁尺寸

Umi 默认会包含以下浏览器及其版本的补丁,

chrome: 49,

firefox: 64,

safari: 10,

edge: 13,

ios: 10,

选择合适的浏览器版本,可减少不少尺寸,比如配成以下这样,预计可减少 90K (压缩后未 gzip)的尺寸。

export default {

  targets: {

    chrome: 79,

    firefox: false,

    safari: false,

    edge: false,

    ios: false,

  },

}

注意:

把浏览器设为 false 则不会包含他的补丁

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

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

比如:

export default {

  chunks: ['vendors', 'umi'],

  chainWebpack: function (config, { webpack }) {

    config.merge({

      optimization: {

        minimize: true,

        splitChunks: {

          chunks: 'all',

          minSize: 30000,

          minChunks: 3,

          automaticNameDelimiter: '.',

          cacheGroups: {

            vendor: {

              name: 'vendors',

              test({ resource }) {

                return /[\\/]node_modules[\\/]/.test(resource);

              },

              priority: 10,

            },

          },

        },

      }

    });

  },

}

通过 NODE_OPTIONS 设置内存上限

如果出现 OOM,也可以通过增加内存上限尝试解决。比如 NODE_OPTIONS=--max_old_space_size=4096 设置为 4G。

调整 SourceMap 生成方式

如果 dev 时慢或者修改代码后增量编译慢,可尝试禁用 SourceMap 生成或者调整为更低成本的生成方式,

// 禁用 sourcemap

export default {

  devtool: false,

};

或者,

// 使用最低成本的 sourcemap 生成方式,默认是 cheap-module-source-map

export default {

  devtool: 'eval',

};

monaco-editor 编辑器打包

编辑器打包,建议使用如下配置,避免构建报错:

export default {

  chainWebpack: (config) => {

    config.plugin('monaco-editor-webpack-plugin').use(

      // 更多配置 https://github.com/Microsoft/monaco-editor-webpack-plugin#options

      new MonacoWebpackPlugin(),

    );

    config

    .plugin('d1-ignore')

      .use(

        // eslint-disable-next-line

        require('webpack/lib/IgnorePlugin'), [

          /^((fs)|(path)|(os)|(crypto)|(source-map-support))$/, /vs(\/|\\)language(\/|\\)typescript(\/|\\)lib/

        ]

      )

    .end()

    .plugin('d1-replace')

      .use(

        // eslint-disable-next-line

        require('webpack/lib/ContextReplacementPlugin'),

        [

          /monaco-editor(\\|\/)esm(\\|\/)vs(\\|\/)editor(\\|\/)common(\\|\/)services/,

          __dirname,

        ]

      )

    return config;

  }

}

替换压缩器为 esbuild

试验性功能,可能有坑,但效果拔群。

以依赖了全量 antd 和 bizcharts 的项目为例,在禁用 Babel 缓存和 Terser 缓存的基础上进行了测试,效果如图:


先安装依赖,

$ yarn add @umijs/plugin-esbuild

然后在配置里开启,

export default {

  esbuild: {},

}

不压缩

不推荐,紧急情况下使用。

编译慢中压缩时间占了大部分,所以如果编译时不压缩可节约大量的时间和内存消耗,但尺寸会增加不少。通过环境变量 COMPRESS=none 可跳过压缩。

$ COMPRESS=none umi build

内置 react、react-router 等

功能完备的路由约定,同时支持配置的路由方式

 TypeScript 支持

迁移 create-react-app 到 umi

依赖处理

在 package.json 中修改依赖并修改项目启动命令,更多 umi cli 的信息,可以查看我们的文档

{

  "scripts": {

-    "start": "react-scripts start",

+    "start": "umi dev",

-    "build": "react-scripts build",

+    "build": "umi build",

-    "test": "react-scripts test",

+    "test": "umi-test"

-    "eject": "react-scripts eject"

  },

  "dependencies": {

-    "react-scripts": "3.4.2"

+    "umi": "^3.2.14"

  },

+ "devDependencies": {

+    "@umijs/test": "^3.2.14"

+ }

}


修改根组件

create-react-app 的入口是 src/index,在 umi 中并没有真实的暴露程序的主入口,但是我们可以在 layouts 中执行同样的操作。

将 src/index 中的逻辑转移到 src/layouts/index 中,操作完成你的代码应该看起来像:

import React from 'react';

import './index.css';

export default ({ children }) => (

    <React.StrictMode>

        {children}

    </React.StrictMode>

);

转移页面文件

将页面组件转移到 src/pages 目录下面。

这里我们期望通过路由 / 访问 App 文件,因此我们如下修改文件名,并修改内部引用。HTML 模版

将 public/index.html 中的内容,转移到 src/pages/document.ejs。

create-react-app 中通过 %PUBLIC_URL% 取得部署路径,而 umi 中需要通过 context 取值。

- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />

+ <link rel="icon" href="<%= context.config.publicPath +'favicon.ico'% />" />

修改 eslint 配置

将 package.json 中的 eslint 配置,转移到 .eslintrc.js。在 umi 项目中我们推荐你使用 @umijs/fabric。当然,你可以使用你熟悉的任意配置。

{

  "devDependencies": {

+    "@umijs/fabric": "^2.2.2",

  }

-  "eslintConfig": {

-    "extends": "react-app"

-  }

}

module.exports = {

  extends: [require.resolve('@umijs/fabric/dist/eslint')],

};

测试相关

增加测试配置引用

新建配置文件 jest.config.js,编写如下配置:

module.exports = {

    "setupFilesAfterEnv": [

        "<rootDir>/src/setupTests.js"

    ]

}

使用 umi-test 替代 react-scripts test

相关修改可以查看上文中提到的依赖处理,如果你刚才没有留意,你可以返回去查看。

执行 umi-test:

$ umi-test

PASS  src/pages/index.test.js (11.765s)

  ✓ renders learn react link (31ms)

Test Suites: 1 passed, 1 total

Tests:      1 passed, 1 total

Snapshots:  0 total

Time:        12.594s

Ran all test suites.

✨  Done in 13.83s.

启动项目

执行 umi dev,项目将会在 http://localhost:8000/ 上启动,如果你习惯使用 3000 端口,你可以通过环境变量来设置。现在项目看起来应该与迁移之前的效果一致。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容