最近升级Umi,踩了一些坑,总结记录了一下,发出来分享一下,大概四五千字,升级遇到问题的小伙伴可以来查阅一下。
按照官网更改依赖
项目的 package.json 需要升级 Umi,并替换掉对应的 Umi 插件。
如果 umi@3 中是使用 umi + @umijs/preset-react 的组合进行开发的,那可以直接使用新版的 max 直接升级。
diff
{
"devDependencies": {
+ "@umijs/max": "^4.0.0",
- "umi": "^3.0.0",
- "@umijs/preset-react": "^1.2.2"
}
}
删除 node_module,执行下 npm install 重装依赖。
报错了

这里报错 没有umi,把postinstall删掉试一下,install成功了。
把postinstall钩子删掉了
更改启动命令
diff
{
"scripts": {
- "build": "umi build",
+ "build": "max build",
- "postinstall": "umi g tmp",
+ "postinstall": "max setup",
- "start": "umi dev",
+ "start": "max dev",
}
}
恢复postinstall钩子,用max setup替换umi g tmp
让后npm run dev启动一下,又报错,runtimePublicPath配置的值无效,先不启动了,按照官网改.umirc.ts

css
fatal - AssertionError [ERR_ASSERTION]: Invalid config values: runtimePublicPath
Invalid value for runtimePublicPath:
[
{
"code": "invalid_type",
"expected": "object",
"received": "boolean",
"path": [],
"message": "Expected object, received boolean"
}
]
修改配置文件
- 更改
umi为@umijs/max
diff
- import { defineConfig } from 'umi';
+ import { defineConfig } from '@umijs/max';
mock属性
diff
- mock: isDev ? {} : false,
+ mock: {},
umi4默认开启webpack5,删除webpack配置
diff
- webpack5: {}
- 更改
runtimePublicPath
diff
- runtimePublicPath: true,
+ runtimePublicPath: {},
- 删除
title,默认为null,无需设置false
diff
- title: false,
- 删除
nodeModulesTransform
diff
- nodeModulesTransform: {
- type: 'none',
- exclude: [],
- },
- 删除
locale,不知道是干嘛的?
diff
- locale: { antd: true },
- 删除
dynamicImport,Umi 4 默认 按页分包 ,从而在页面切换时存在加载过程,通过该文件来配置加载动画。在目录结构下添加loading.tsx
diff
- dynamicImport: {
- loading: '@/components/Loading',
- },
- 在
.umirc.ts中添加historyWithQuery字段
diff
// .umirc.ts
{
+ historyWithQuery: {},
}
现在启动一下npm run dev,又报错了!!!!!

vbnet
error - [MFSU][eager] worker got Error Error: Cannot find module 'umi/dist/service/service'
Require stack:
代码层面更改
将页面中所有umi的导入改为@umijs/max
diff
- import { } from 'umi';
+ import { } from '@umijs/max';
在npm run dev 启动一下,依然保持,与上面保持相同,找不到模块
umi/dist/service/service然后升级了node到v20
删除node_modules和package-lock.json文件
重新
npm install再次
npm run dev它又报错了,啊啊啊!!!

vbnet
ValidationError: Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'localsConvention'. These properties are valid:
object { url?, import?, modules?, sourceMap?, importLoaders?, esModule?, exportType? }
删掉css-loader配置
diff
- cssLoader: {
- localsConvention: 'asIs',
- },
重新
npm run dev报错
index.html没有暴露window.publicPath

在index.html要暴露
window.publicPath,但是升级后的index.html中没有暴露

原来的

- 通过
headScripts向index.html注入全局变量脚本
diff
// .umirc.ts
{
+ headScripts: [
+ 'window.routerBase = "abc/"',
+ 'window.publicPath = window.resourceBaseUrl || "abc/";',
+ ]
}
注入后:

再次执行
npm run dev又报错,但是有预感快成功了
因为上面
window.publicPath配置的一个写死的字符串改为
bathPath变量再次启动
又又又报错

改成了这样

再次执行
npm run dev又报了其他错误
getInitialState注册失败

vbnet
Unhandled Rejection (Error): register failed, invalid key getInitialState from plugin /Users/mac/Desktop/xxxxx/src/app.ts.
提示我
getInitialState注册不成功,真坑
umi4需要,在.umirc.ts中添加配置
diff
// .umirc.ts
{
+ initialState: {},
+ model: {}, // 使用useModel需要这个配置
}
再次
npm run dev跑起来了!!
路由好像失败了!!!
只展示出来一个layout,antd的主题样式自定义也没了
先解决只展示layout的问题
按照umi/max新规范,需要使用<Outlet />替换children
diff
import React from 'react';
+ import { Outlet } from 'umi';
export default function Layout(props) {
return (
<div>
- { props.children }
+ <Outlet />
</div>
);
}
修改完后项目展示部分正常了
使用useHistory的部分又报错了!!!!

因为Umi4将
React-Router@5升级到了React-Router@6在
React-Router@6中,使用useNavigate和useLocation替换了useHistory将项目中使用
useHistory替换为useNavigate再次执行
npm run dev项目启动,报错没了
_layout.tsx文件失效了,气人 !!!
经查询,把原来的_layout.tsx文件放到与所在目录同级,并改名为与目录名相同,如下:
原来的:
lua
|--parent
| |--index.tsx
| |--_layout.tsx
更新后:
css
|--parent
| |--index.tsx
|--parent.tsx # 原来的_layout.tsx
重新
npm run dev正常了
动态路由出现错误
Umi4约定式路由使用
$id.tsx,不在支持[id].tsx
总结
在项目技术栈升级实操过程中一定要有文档记录自己每一步的操作,当遇到问题时及时回溯操作的可行性。避免因为自己的操作,解决了一个问题却引入了其他问题,自己还不自知的情况。