記錄一次舊項(xiàng)目升級(jí)umi3到4的過(guò)程,希望踩過(guò)的坑可以給大家?guī)?lái)一點(diǎn)幫助。
項(xiàng)目背景:(只說(shuō)一下重點(diǎn))
react@16
antd@4(初始是antd3,升級(jí)到4的)
antd-pro@2(萬(wàn)年老版,已經(jīng)不知道用在哪里)
umi@3.5(配套的 reatc-redux,dva)
react-router-dom@4(版本有點(diǎn)低)
項(xiàng)目本身是一套后臺(tái)管理,小型系統(tǒng),整體可控。
升級(jí)過(guò)程:
-
升級(jí) reace@17
package.json 直接處理: "react": "^17.0.2” "react-dom": "^17.0.2",好像沒有任何不適,完美兼容,贊一下。(主要是第二步需要react@17)
引入
jotai,用來(lái)代替dva
- 因?yàn)橹爸苯由?jí)umi4,好像遇到了dva的問(wèn)題
- 也因?yàn)榕f項(xiàng)目,dva的封裝, api.js --> model/project.js --> dispatch 的引用,還不能用 sync/await,讓我不爽
- stroage數(shù)據(jù)不刷新,發(fā)布代碼后,經(jīng)常需要手動(dòng)清空,原因不明
- 一個(gè)關(guān)鍵點(diǎn):需要引入
React.Suspense解決ajax請(qǐng)求白屏的問(wèn)題。但也會(huì)帶來(lái)過(guò)渡白屏的問(wèn)題(尷尬),自己取舍吧。 - 最后留下一個(gè)空殼文件。 (該內(nèi)容在升級(jí)完成后,移除了)
# modules/login.js
// 因?yàn)閡mi的問(wèn)題,如果不保留,會(huì)導(dǎo)致加載dvajs報(bào)錯(cuò),所以需要保留一下
export default {
namespace: 'login',
state: {},
effects: {
*tokenLogin({}, {}) {
return null;
},
},
};
- 最后才知道umi@4 max版也引入了
valtio,貌似功能類似,不管了
- 升級(jí) umi@4,參考的升級(jí)指南 https://umijs.org/docs/introduce/upgrade-to-umi-4
{
"devDependencies": {
+ "@umijs/max": "^4.0.0",
- "umi": "^3.0.0",
- "@umijs/preset-react": "^1.2.2"
}
}
- 修改 umi 的配置 config.js
import { defineConfig } from 'umi';
import routes from './router.config.js';
import defaultSettings from '../src/defaultSettings.js';
export default defineConfig({
plugins: [
'@umijs/plugins/dist/antd',
],
routes,
mfsu: {
strategy: 'normal',
},
antd: {},
hash: true,
history: { type: 'hash' },
outputPath: 'dist-build',
esbuildMinifyIIFE: true,
lessLoader: {
javascriptEnabled: true,
},
cssLoader: {
modules: {
getLocalIdent: (context, localIdentName, localName) => {
return localName;
},
},
},
});
- 升級(jí) nodejs@16至 nodejs@18 ,我比較保守,慢慢升
- 關(guān)鍵點(diǎn),需要安裝
yarn add @umijs/pluginsyarn add @umijs/plugin-antd,并在config中引入,否則antd相關(guān)的css貌似無(wú)法裝載。 - esbuildMinifyIIFE 必須打開
-
outputPath: 'dist-build', 之前是outputPath: '/dist-build', 貌似判別方法變了 - 兩個(gè) cssLoader,不太明白,但GPT如是說(shuō),放上
- 還遇到自定義的 less 混合宏代碼不生效,less代碼重寫后生效了。
- 在BasicLayout.menuList,渲染菜單樹時(shí)卡了比較久,之前props.route,有所有路由表?,F(xiàn)在沒有了,只能自己用route.config.js去處理轉(zhuǎn)換一下,因?yàn)楸容^深,遞歸也用上了。
- props中,不再包含 route / location {query} 需要自己往里填,所以自己包裝了一個(gè)高階函數(shù)(HOC),對(duì)所有組件包裝一下,真累,不過(guò)同時(shí)把需要的全局字節(jié)數(shù)據(jù)也做了進(jìn)去,確實(shí)也方便了許多。
// hoc.js
import { useAtom } from 'jotai';
import React from 'react';
import { useLocation, useSearchParams } from 'react-router-dom';
import allSampleTypesAtom, { allProductsAtom } from '@/models/atom.js';
import routesConfig from '../../config/router.config.js';
import { getRouter } from './utils.js';
// 因?yàn)樯?jí)umi4導(dǎo)致像 location.query不能直接獲取,需要包裝一下。順便把需要的字典數(shù)據(jù)加進(jìn)來(lái)
const withQueryParams = (WrappedComponent, dataLoads = {}) => {
return (props) => {
const location = useLocation();
const [searchParams] = useSearchParams();
// 將查詢參數(shù)解析為對(duì)象格式
location.query = Object.fromEntries([...searchParams]);
// 獲取路由
const route = getRouter(location.pathname, routesConfig);
// 附加數(shù)據(jù)
const appendData = {};
if (dataLoads.allProducts) {
const [allProducts] = useAtom(allProductsAtom);
appendData.allProducts = allProducts;
}
if (dataLoads.allSampleTypes) {
const [allSampleTypes] = useAtom(allSampleTypesAtom);
appendData.allSampleTypes = allSampleTypes;
}
return <WrappedComponent {...props} location={location} route={route} {...appendData} />;
};
};
export default withQueryParams;
使用時(shí)
import withQueryParams from '@/utils/hocs.js';
...
class SampleEdit extends PureComponent {
...
}
...
export default withQueryParams(SampleEdit); // SampleEdit;
- document.ejs 沒用了,有點(diǎn)意外。加載外部的cdn,需要在config.js中增加配置項(xiàng)(不開心)
headScripts: [
{ src: 'https://rescdn.qqmail.com/node/ww/wwopenmng/js/sso/wwLogin-1.0.0.js' }
],
最后,yarn add prettier@latest -D升級(jí)一下格式化工具
至此大面上的事情基本解決?;竞臅r(shí)一周多的人力。后續(xù)慢慢體會(huì) mako:{}, 倒底快沒快
祝大家都升級(jí)順利。