记一次 React 老项目升级改造

关注公粽号『 前端我废了 』,查看更多文章!!!

项目背景

目的是需要改造优化一个 React 老项目本地开发启动、热更新及打包速度。背景是部门老大有天找我说有个 React 老项目本地开发启动太慢了,每次启动和热更新都要 6,7 分钟左右,叫我抽空看看能不能优化一下,我看了下代码仓库,该项目是 08 年写的,我把代码克隆下来跑了下试试,好家伙!将近 700 s,这也太慢了啦。

记一次 React 老项目升级改造_第1张图片

问题分析过程

问题很明确了,接下来先看下项目,项目基础架子是基于 ant-design-pro v1 ,本地启动打包都是基于 roadhog 这个工具,相关工具、框架及库版本如下:

  • roadhog^1.3.1 : cli 工具,可以认为是一个可配置的 create-react-app
  • react^16.0.0
  • dva^2.1.0
  • antd^3.26.19

roadhog 1.x 版本依赖了 webpack^3.0.0-rc.1 , roadhog 最新的版本为 2.5.0-beta.4,依赖关系为:roadhog@^2.5.0-beta.4af-webpack^0.23.0-beta.1webpack^3.5.6 ;roadhog 1.x 和 2.x 内部都是依赖了 webapck 3.x 版本。


分析构建过程

安装 webpack 插件 npm i simple-progress-webpack-plugin -D,将构建进度信息在终端打印出来

// webpack.config.js
const SimpleProgressWebpackPlugin = require("simple-progress-webpack-plugin");
module.exports = (webpackConfig, env) => {
  webpackConfig.plugins.push(
   new SimpleProgressWebpackPlugin()
  )
  return webpackConfig
}

可以看到在 Optimize modules 阶段就卡住了

记一次 React 老项目升级改造_第2张图片

google 一下,找找有没有类似问题,找到的相关 issues

  • [Build Performance] chunk graph very much slow
  • 请问为什么动态路由会影响热更新速度呢
  • Webpack 2 Dynamic Import degrades build performance (slow) compared to static imports.

其中的一个 issue

记一次 React 老项目升级改造_第3张图片

看了下回答,大概意思是说,使用动态导入越多,webpack 构建速度就会越慢;可以使用 babel 插件 babel-plugin-dynamic-import-node ,将 import() 转换为 require() ,这样就可以用这个插件将所有异步组件都用同步的方式引入,也就是在开发环境不用代码分割成单独的 chunk。

记一次 React 老项目升级改造_第4张图片

首先安装插件npm i babel-plugin-dynamic-import-node -D,然后添加到 .roadhogrc 配置文件的 extraBabelPlugins 选项中,重新启动项目,结果确实几秒就构建完成。

// .roadhogrc
{
  "env": {
    "development": {
      "extraBabelPlugins": ["dynamic-import-node"]
    }
  },
 // 其他配置...
}

到这里,开发环境的启动速度慢问题就解决了,但是打包依旧很慢 ,还是到 roadhog 的 github 仓库查看有没有相关 issue,发现有类似构建慢问题,解决办法大都是是迁移到 webpack 4,webpack 4 的构建速度提升了 60% ~ 98%,然后再将一些较大的第三方库 external 掉,解决方案大概有以下几个方向,最终采用方案二。

解决方案

方案一: 跟随 ant-design-pro 迁移文档升级

因为原项目是基于 ant-design-pro v1,构建工具为 roadhog,如果要升级到 ant-design-pro v2,构建工具需要迁移为 UmiJS(简称 umi),而 umi 不只是一个构建工具,它包含了路由以及一套插件机制用于构建一个完整的 React 应用。此种方案改动需要遵循 umi 的约定,会破坏原有代码的组织形式且改动较大,放弃!

方案二:替换为 create-react-app 脚手架(采用)

可以基于 cra,然后通过命令 npm run inject 将 cra 相关的配置(webpack, Babel, ESLint 等)暴露出来,方便我们自定义一些配置,采用该方案对原有组织形式不影响,只需要将我们业务代码搬过来即可,最终采用此方案!

方案三:自己从 0 配置 webpack

与基于 cra 的方案做法类似,只不过需要我们需要自己从零配置 webpack 来处理各种资源(样式,图片,字体等),区分开发、生产环境配置…


相关 issues:

  • 编译很慢
  • 支持 vendor 的配置
  • 打包优化

扩展了解

  1. roadhog 是啥?和 umi 有什么区别?

    roadhog 是基于 webpack 的封装工具,目的是简化 webpack 的配置,roadhog 是比较纯粹的 webpack 封装工具,作为一个工具,他能做的就比较有限(限于 webpack 层)。而 umi 则等于 roadhog + 路由 + HTML 生成 + 完善的插件机制,所以能在提升开发者效率方面发挥出更大的价值。

  2. umi.js 和 dva、roadhog 是什么关系?

    • roadhog 是基于 webpack 的封装工具,目的是简化 webpack 的配置。
    • umi 可以简单地理解为 roadhog + 路由,思路类似 next.js / nuxt.js,辅以一套插件机制,目的是通过框架的方式简化 React 开发。
    • dva 目前是纯粹的数据流,和 umi 以及 roadhog 之间并没有相互的依赖关系,可以分开使用也可以一起使用。

参考

  • DvaJS
  • UmiJS v2 、UmiJS v3 、UmiJS v4
  • ant-design-pro v1 、ant-design-pro v2
  • roadhug 配置 webpack 插件
  • Webpack-Modules-dynamic-expressions-in-import
  • MDN - Dynamic imports
  • Webpack Rebuild Improvement: How A One Line Change Yielded A 93% Increase
  • webpack 4: released today!!✨

你可能感兴趣的:(work,notes,笔记,react.js,前端,webpack)