react 项目的 react17 升级经验


一、前端框架(或者库)升级的原因:

a、前端技术更新比较快,需要不断更新保持技术和依赖都和社区同步。当前项目基于CRA于2919年年中开发的脚手架搭建,插件和工具类版本已经过时,大部分外部依赖库都有很大升级而且我们无法控制,如果不升级,一年后项目会没法启动本地开发环境,也没法打包部署上线;
b、新版脚手架对性能和开发体验都进行了很多优化,新版脚手架基于社区2021年的相对最优解决方案和依赖。如vite2.0、react17(相比react16版本有了核心实现的重构)等;

二、详细描述要升级的框架以及类库。从哪个版本到哪个版本。有什么要注意的等等

a、antd 不做大版本升级;
b、react-script 3.0.1 → 4.0.3 脚手架的版本,无法向后兼容;(antd不做升级,对应的webpack5用不了,只能用webpack4.x的版本,所以对应的react-script只能升级到4.0.3,webpeck版本为4.44.2)

c、copy-webpack-plugin 调用方法有更改,无法向后兼容;
d、node less-loader less node-sass 的版本需要特别处理,需要在升级过程中调整相应的兼用版本;

三、升级的具体步骤
在项目目录下运行:

安装ncu

npm i -g npm-check-updates
ncu -u
rm -rf node_modules
npm i

有以下一些包要更新:

注意:

antd,less,less-loader不能升级到最新的版本,因为项目对antd做了很多定制化开发,andt升级改动较大,antd对less-loader的版本有依赖;

"less": "^3.10.3",
"less-loader": "^5.0.0",
"antd": "^3.26.19",

根据各依赖包版本升级之间的log,分析受影响的代码模块,开发自测;

使用 webpack-bundle-analyzer 插件分析build后的各个文件的大小,及时优化太大的js文件;

四、升级后的验证步骤有几步(保证升级后不破坏现有功能)

a、页面部署好之后能否正常打开;
b、页面有无报错信息,以及报错信息的类型;
c、冒烟测试是否能通过;
d、各功能模块流程是否能正常走通;
e、切记不要漏掉 WPA(web performance audit);

五、接下来分享升级过程的具体报错及解决方案。

1. copy-webpack-plugin  调用方法有更改,无法向后兼容;具体写法也可以在项目中node_modules-->copy-webpack-plugin-->README.md中看到。

new CopyWebpackPlugin({
        patterns: [
          { from: "source", to: "dest" },
          { from: "other", to: "public" },
        ],
})

2. Failed to load config "react-app" to extend from.

多数问题在于eslint缺失导致加载失败

yarn add eslint-config-react-app

3.Error: Duplicate plugin/preset detected.If you'd like to use two separate instances of a plugin,they need separate names, e.g.

 plugins: [

    ['some-plugin', {}],

    ['some-plugin', {}, 'some unique name'],

  ]

这个问题是:插件重复,先在面板中看有没有重复的依赖或者插件,找到项目文件中的babel.cofig.js/config-overrides.js ,发现重复的项 。

4. Attempted import error: 'Prompt' is not exported from 'react-router-dom'

react-router-dom结合项目,只能升级到5.3.0。

"react-router-dom": "^5.3.0",

5. Attempted import error: 'array-move' does not contain a default export (imported as 'arrayMove').

arrayMove写法发生改变,

错误写法:

import arrayMove from 'array-move';

正确写法:

import { arrayMoveImmutable } from 'array-move';

6. ./src/index.sass (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-6-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--5-oneOf-6-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-6-4!./src/index.sass)

Node Sass version 7.0.1 is incompatible with ^4.0.0 || ^5.0.0 || ^6.0.0.

此错误来自sass-loader。server不匹配。
解决方案:降低node-sass版本。
卸载node-sass :

npm uninstall node-sass

注意:

如果这边卸载报错的话,建议直接在package.json 中把 node-sass 改成4.14.1, 再从文件夹中删除node_module文件夹, 删除后再npm install

package.json:

"node-sass": "^4.14.1",

删除node_modules

rm -rf node_modules

重新安装

yarn

注意:

node-sass6以上版本,node版本必须升级为16以上。目前我的node版本是: v14.17.6, node-sass版本:v4.14.1

https://github.com/sass/node-sass

7. ./node_modules/antd/es/icon/style/index.less (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-8-1!./node_modules/postcss-loader/src??postcss!./node_modules/resolve-url-loader??ref--5-oneOf-8-3!./node_modules/less-loader/dist/cjs.js??ref--5-oneOf-8-4!./node_modules/antd/es/icon/style/index.less)

TypeError: this.getOptions is not a function

原因: less-loader安装的版本过高

解决方案: 

npm uninstall less-loader
"less": "^3.10.3",
"less-loader": "^5.0.0",
yarn

8.  Module not found: Can't resolve 'react-pdf/dist/Page/AnnotationLayer.css' in '/Users/ito-user/Desktop/upgrade/drs-web-pos/src/kits/porPdf'

导入出错:

以前版本:

import 'react-pdf/dist/Page/AnnotationLayer.css';

现在版本:

import 'react-pdf/dist/esm/Page/AnnotationLayer.css';

9. Parsing error: This experimental syntax requires enabling one of the following parser plugin(s): "decorators-legacy", "decorators". 

解决方案:

npm i --save-dev customize-cra react-app-rewired

config-overrides.js:

const {
  override,
  addDecoratorsLegacy,
  disableEsLint
} = require("customize-cra");

module.exports = override(
  addDecoratorsLegacy(),
  disableEsLint()
);

package.json:

"scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-app-rewired eject"
  },