项目升级nextjs15, antd5和node20 踩坑记录

2,427 阅读3分钟

image.png

背景

因为项目目前统一用的node 16.15.0 已经逐渐废弃,并且一些新的包依赖node 18甚至20以上,所以需要升级系统依赖

image.png

  • react 18.2.0 → 18.3.1
  • antd v4.23.5 → v5.22.1
  • nextjs 12.3.4 →  15.0.3
  • node 16.15.0 → 20.17.0

node版本升级

node 版本维护链接:nodejs.org/zh-cn/about…

node版本升级 16.15.0 → 20.17.0

一步到位升级到最新的稳定版本呢20.17.0,这个版本维护的周期也很长适合升级

nextjs版本升级

随着node升级,基础框架nextjs也需要相应的更新到最新的版本以适应node的更新迭代

next.js版本 12.3.1 → 14.2.15 → 15.0.3 (改动过程中又升级了,那就正好用最新版吧)

yarn add next``@latest react``@latest react-dom``@latest eslint-config-next``@latest

升级文档参考:

nextjs.org/docs/pages/…

nextjs.org/docs/app/bu…

nextjs.org/docs/app/bu…

pages文件夹迁移成app文件夹(这个斟酌一下要不要做)

需要注意middleware文件中,cookie的格式有改变

参考文档nextjs.org/docs/app/bu…

// 新cookie格式

let cookie = request.cookies.get('nextjs')

console.log(cookie) 
// { name: 'nextjs', value: 'fast', Path: '/' }

// 之前是直接给值的,并不是一个对象

另一个问题是

github.com/vercel/next…

Next.js 15 fails to build when using antd due to "SyntaxError: Cannot use import statement outside a module"

transpilePackages: [
  // https://github.com/vercel/next.js/issues/58817
  "@ant-design",
  "@rc-component",
  "antd",
  "rc-cascader",
  "rc-checkbox",
  "rc-collapse",
  "rc-dialog",
  "rc-drawer",
  "rc-dropdown",
  "rc-field-form",
  "rc-image",
  "rc-input",
  "rc-input-number",
  "rc-mentions",
  "rc-menu",
  "rc-notification",
  "rc-pagination",
  "re-motion",
  "rc-picker",
  "rc-progress",
  "rc-rate",
  "rc-resize-observer",
  "rc-segmented",
  "rc-select",
  "rc-slider",
  "rc-steps",
  "rc-switch",
  "rc-table",
  "rc-tabs",
  "rc-textarea",
  "rc-tooltip",
  "rc-tree",
  "rc-tree-select",
  "rc-upload",
  "rc-util",
],

next13以后babel只翻译src中的资源

node_modules中翻译需要配置,

nextjs.org/docs/archit…

stackoverflow.com/questions/6…

因为nextjs 14没有好的兼容 less的解决方案,之前用的next-plugin-antd-less,但是这个插件已经不支持最新的nextjs14了,找了另一个next-with-less插件也只支持到13. 鉴于nextjs对于less的支持越来越差,决定放弃less使用cssinjs,即升级antd4 → antd5

next14中node_env = development 会导致奇怪报错,目前没找到原因,可以使用其他env环境

github.com/vercel/next…

Antd v4 to v5

ant.design/docs/react/…

需要修改的地方

## 安装
卸载antd4,安装antd5
yarn remove antd
yarn add antd
## 移除依赖
// 不再支持 babel-plugin-import,CSS-in-JS 本身具有按需加载的能力,不再需要插件支持。
yarn remove babel-plugin-import
// 并且更改 bable.config.js
module.exports = function (api) {
  api.cache(true);

  return {
    presets: [['next/babel']],
  };
};
## 更改配置文件 next.config.js
// 去掉withAntdLess嵌套
## 更改入口文件 _app.tsx, 全局主题也可以在这里设置
import { MainLayout as Layout } from '@/page-components/layout/MainLayout';
import { ConfigProvider } from 'antd';
import { useEffect } from 'react';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';

import zhCN from 'antd/locale/zh_CN';
import 'antd/dist/reset.css';
import '@/styles/global.css';

dayjs.locale('zh-cn');

const themeToken = {
  token: {
    colorPrimary: '#ff472e',
    colorTextBase: '#232426',
    colorLink: '#ff472e',
  },
};

SentryLogger.init();

function CustomApp({ Component, pageProps }: any) {

  return (
    <ConfigProvider locale={zhCN} theme={themeToken}>
      <div id="root">
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </div>
    </ConfigProvider>
  );
}

export default CustomApp;

所有index.module.less 改为 index.module.css

要用css的格式写,不能大括号嵌套了

里面的全局变量用 @main-color 改为 var(--main-color)

嫌麻烦可以用在线转换 在线less转css地址

## 更换moment依赖

import moment, { Moment } from 'moment';

// 替换为

import dayjs, { Dayjs } from 'dayjs';`
## 另外还有一些类型地址变了,这个还没找到目标地址

import { RuleObject } from 'rc-field-form/lib/interface'; 
## 一些组件visiable改成open传参,这个具体看文档和报错即可
### antd5还有一些样式区别与antd4, 比如圆角什么的,这个细节就要具体看一下了

特别注意,不要用antd v5.22.0

这个版本的select选择框maxTagCount="responsive"的时候有bug(坑了我一下午...), 用v5.22.1

github.com/ant-design/…