umi3.5升4.0,react17升18踩坑之路

1、背景2、开启umi升级踩坑之路2.1、修改配置2.2 layout层修改2.3 wrappers层修改2.4 修改从wrappers里传过来的属性获取方式2.5 修改history2.6 修改location取值方式2.7 useActivate, useUnactivate导入方式由umi改成react-activation2.8 使用了useModel的页面,再使用KeepAlive,都会报错:`Uncaught TypeError: Cannot read properties of null (reading 'dispatcher')`2.9 react报错ReactDOM.render is no longer supported in React 182.10 pnpm build 报错 export 'IFormilySchema' (reexported as 'IFormilySchema') was not found in '@designable/formily-transformer' (possible exports: transformToSchema, transformToTreeNode)

1、背景

由于部分页面有性能问题,前端同学也在研究提升性能方面的方法,除了一些常用方法之外,还了解到react18有部分API可以提升性能,所以想把项目中用到的React版本由17升到18。

经过调研,如果直接把项目React17改成18版本,项目编译时会报错,报错信息如下

原因是umi3.5.x版本的render-react包依赖的react不支持18,如图 所以如果要升react18的话必须把umi升到4.x版本。

2、开启umi升级踩坑之路

2.1、修改配置

1) 首先删除 package-lock.json, pnpm-lock.yaml,node_modules,.umi文件夹

2)package.json 需要移除umijs等相关插件,如@umijs/plugin-esbuild @umijs/route-utils @umijs/preset-react umi umi-plugin-keep-alive

3)package.json需要添加 “react”: “^18.2.0”,“react-dom”: “^18.2.0”,“@types/react”: “^18.2.0”,“@types/react-dom”: “^18.2.0”, “@umijs/max”: “4.0.40”

4)tsconfig.json配置 “compilerOptions”:{ “types”: [“node”,“react”] }

5)修改package.json中script的启动命令,因为@umijs/max将一些项目前置操作放到了 setup 命令中,如 umi@3 中的 umi g tmp 等命令,需要使用 max setup 替换 6)修改.umirc.ts 将mfsu 和webpack5配置去掉,因为umi max默认开启了mfsu和webpack5

去掉nodeModulesTransform 和 dynamicImport,增加 initialState: {}, model: {}, hash: true, historyWithQuery:{}, fastRefresh: true,antd: {},如果用到了keepalive插件需要添加 plugins: [‘umi-plugin-keep-alive’], 当然不要忘记安装这个插件了哦,执行pnpm add umi-plugin-keep-alive --save-dev

hash 官方竟然默认是false, 开启后会让build之后的产物包含hash后缀,如umi.df723s.js, umi.8sd8fw.css,通常用于增量发布和避免浏览器加载缓存,所以别忘了设置为trueantd: {} 必须设置,不然打包生成样式会缺少antd样式historyWithQuery 官方竟然默认是false, 导致history.push({ pathname: '/', query: { id } }) 跳转页面不会携带id,所以我们一定要设置上去

2.2 layout层修改

Umi 4 中将 react-router@5 升级到 react-router@6,所以路由相关的一些 api 存在着使用上的差异。 props 默认为空对象,以下属性都不能直接从 props 中取出 导致layouts 中的文件,取props.children获取为空,需要用umi的Outlet组件替换, 如图

2.3 wrappers层修改

同理,wrappers层用props.children取值渲染的地方也要改成umi max的Outlet

view-error.tsx view-auth.tsx (顺便替换了props.location) system-auth.tsx 使用了 React.cloneElement 方式渲染的路由组件改造 keepalive.tsx auth.tsx auth-button.tsx

2.4 修改从wrappers里传过来的属性获取方式

由于把wrappers层的props.children改成了Outlet,那么从props里取systemConfig,dictConfig,productionModalConfig等属性,需改成如下图方式获取

这里代码涉及处挺多的,别改漏了

2.5 修改history

1)由于从props里获取不到history了,需要改成从umi里直接引用,import { history } from 'umi'

2)history.push的Api也有改变,如果传了state,需修改传参,如下图 3)history.goBack() 需改成 history.back() 或 history.go(-1)

history.listen的获取值方式改变, 如下图

2.6 修改location取值方式

1)从props.location 需改成 import { useLocation } from 'umi'; let location = useLocation();

2)从props.location.query里取值的方式需要改成从history.location.query 或者 useLocation().search里获取,再用query-string解析获取

2.7 useActivate, useUnactivate导入方式由umi改成react-activation

2.8 使用了useModel的页面,再使用KeepAlive,都会报错:Uncaught TypeError: Cannot read properties of null (reading 'dispatcher')

在.umirc.ts里配置了model: {}; initialState:{} 就可以使用useModel了,但是与keepalive同时使用会报错,解决步骤如下:

1)需要安装插件 pnpm add umi-plugin-keep-alive --save;

2)需要在.umirc.ts文件中手动配置开启插件,plugins: [‘umi-plugin-keep-alive’]

3)src/app.ts中添加如下配置

2.9 react报错ReactDOM.render is no longer supported in React 18

在18.0版本中,React 18 不再支持 ReactDOM.render,需使用createRoot代替

2.10 pnpm build 报错 export ‘IFormilySchema’ (reexported as ‘IFormilySchema’) was not found in ‘@designable/formily-transformer’ (possible exports: transformToSchema, transformToTreeNode)

意思是重复导出的变量没有找到,写法如下 可是在 @designable/formily-transformer这个包里明明有导出这个类型定义呀,如图 后来经过研究,需要在导出的非变量前面加上type才可以,写法如下 这样再重新build就不会报错了

tips: 本次改动量比较多,涉及到的文件量比较大,不确定还有没有地方遗漏,要上线的话还需要做个上线的方案

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。