升级next@13 react@18 chakra-ui@2

一、升级步骤

1、本地node建议升级到v20(next@13要求node@18,react@18、react-dom@18、chakra-ui@2)

2、支持渐进式升级next13,升级的项目需按 next 官方添加环境变量NEXT_PUBLIC_NEXT13,请devops帮忙Dockerfile构建时添加.env 文件到 pod中

 

3、由于升级 next13,公共组件客户端需要区分nginx与next,nginx项目需要按 create-react-app 官方添加环境变量REACT_APP_IS_NGINX=true,不用改Dockerfile

 

4、由于历史原因,@chakra-ui/theme-tools会升级失败,需要在resolutions指定为新版本"@chakra-ui/theme-tools": "2.1.

 

5、yarn add next@13.5.6 react@18.2.0 react-dom@18.2.0 @chakra-ui/react@2.8.2 @emotion/css@11.11.2 @emotion/react@11.11.3 @emotion/server@11.11.0 @emotion/styled@11.11.0 framer-motion@10.17.9

6、升级eslint插件 yarn add -D eslint-config-next@13.5.6

7、mik-ssr-web、mik-ssr-dc、mik-ssr-auth已上 prod环境,需要全量测试,升级后包增加100kb后期解决

8、next官方升级文档Upgrading: App Router Migration

 

二、调试方法

yarn start启动本地调试,通过组件栈与调试面板有助于查找报错原因

 

三、常见业务报错

1、next@13对react-router-dom兼容性不好,可能产生白屏。建议删除react-router-dom,使用next/router、next/link等。如需兼容nginx项目,统一使用useMikRouterMikLink,智能判断next/link、react-router-dom的Link、chakra-ui的Link

 
import { useMikRouter, MikLink } from 'michaels-ssr/hooks/nextOrNginx'; export default function Component() { const router = useMikRouter(); // 内部判断next或者nginx,添加react-router-dom的useLocation属性 router.push('/'); console.log('pathname', router.pathname) return <MikLink href='/home' p="30px" bg='tomato'>Home</MikLink> //支持chakra-ui样式 }

2、当useEffect的回调函数是异步函数时,可能产生白屏。async函数隐式返回一个Promise对象,React18框架错误地将其解释为返回的清理函数,这会在组件因导航而卸载时导致错误。

应该用函数包裹一层,需保留{},useEffect(() => { getIpFn() }, [])

 
错误写法: useEffect(async () => { const ipText = await fetch(`${env.COMMERCE_API}/shipping/getRequestIp`); }, []);
 
正确写法: const getIpFn = async () => { const ipText = await fetch(`${env.COMMERCE_API}/shipping/getRequestIp`); } useEffect(() => { getIpFn() }, []); //应该用函数包裹一层,需保留{}

2、next13的next/link的href属性,仅支持 string 与 object,undefined会报如下错误

 

4、水合一致性报错,react18水合检验更严格,会报418、423、425错误

函数组件的typeof window !== 'undefined' 应改为自定义 hook

 
import useIsClient from 'michaels-ssr/hooks/useIsClient'; export default function Component() { const isClient = useIsClient(); return isClient ? 'Is Client' : 'Is Server' }

5、useMediaQuery当客户端屏幕宽度与服务端渲染不一致报418、423,建议服务端渲染默认1440

 
const [is1440] = useMediaQuery(`(max-width: 1439px)`); const [is1024] = useMediaQuery(`(max-width: 1023px)`);

6、a 标签不能嵌套 a标签

 

7、其他水合一致性报错详见:

next官方文档Text content does not match server-rendered HTML

或 react官方文档hydrateRoot – React

8、ping接口使用正确es6写法

 
const ping = require('michaels-ssr/pages/api/ping'); module.exports = ping;

改为

 
import ping from 'michaels-ssr/pages/api/ping' export default ping

9、Toast 不弹出
过渡解决方案 在当前页使用standalone toast 参考,同时要保证theme color 值正确可用 Upgrading to v2
_app.jsx example:

 
import { createStandaloneToast } from '@chakra-ui/toast' import { withCustomer } from 'michaels-ssr/pages/_appWithOutHeaderFooter'; import CommonLayout from 'michaels-ssr/components/Layout'; const { ToastContainer } = createStandaloneToast() function CustomeLayout(props) { return ( <> <ToastContainer /> <CommonLayout {...props} />; </> ); } export default withCustomer({ newApp: true, Layout: CustomeLayout, });
posted @ 2024-04-29 09:48  jerry-mengjie  阅读(128)  评论(0)    收藏  举报