艰难升级Nuxt 3.15.4至Nuxt 4.2.0的问题记录

参考官网的升级指引:Upgrade Guide · Get Started with Nuxt v4,对项目进行升级和自动化迁移目录结构后,执行nuxt dev启动项目,然后就开始了一路的解决报错之旅。

1
2
3
4
5
6
7
8
9
# 升级新版本
npm install nuxt@^4.0.0

# 安装自动化迁移工具
npx codemod@0.18.7 nuxt/4/migration-recipe

# 执行自动化迁移
> y
> [按下Enter键,等待自动迁移...]

报错1:File is not defined

这个报错信息并不是我的代码造成的,而是node_modules目录下的NPM包报错,所以我第一反应是node环境有变化了,于是去官网查看了node版本要求。果然,Nuxt 4需要 Node 20.X 以上的版本。

1
2
3
4
5
6
7
8
9
10
11
12
ERROR  File is not defined                                                                                   09:50:46

at Object.<anonymous> (node_modules\undici\lib\web\webidl\index.js:531:48)
at Module._compile (node:internal/modules/cjs/loader:1364:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
at Module.load (node:internal/modules/cjs/loader:1203:32)
at Module._load (node:internal/modules/cjs/loader:1019:12)
at Module.require (node:internal/modules/cjs/loader:1231:19)
at require (node:internal/modules/helpers:177:18)
at Object.<anonymous> (node_modules\undici\lib\web\fetch\util.js:12:20)
at Module._compile (node:internal/modules/cjs/loader:1364:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)

官网文档有提到Node版本要求官网文档有提到Node版本要求

主包平时用nvm管理node多环境(参考这篇),这里切到了node 22.x版本就解决了。

报错2:Cannot start nuxt: Cannot find native binding.

没遇到过,问了豆包说可能是切换node版本之后,node_modules中的安装包需要重新安装导致的,于是按照豆包给的提示删除了项目下的node_modulespackage_locked.json,重新执行npm install

1
2
3
4
5
6
7
8
# 1. 删除 node_modules 和 package-lock.json
rm -rf node_modules package-lock.json

# 2. 清除 npm 缓存(避免缓存的损坏依赖影响安装)
npm cache clean --force

# 3. 重新安装依赖
npm install

因为windows上没有rm -rf指令,需要手动删一下。重装之后问题解决。

报错3:Error: Could not load d:/***/app/lib/prisma (imported by server/api/***/***/[id].delete.ts): ENOENT: no such file or directory, open ‘d:\***\app\lib\prisma’

Nuxt4中把srcDir调整到app目录Nuxt4中把srcDir调整到app目录

原因是之前引用其他文件时,~指向的是根目录,而在Nuxt 4中~调整为指向app/目录。你可以在nuxt.config.ts中修改srcDir的值为.来恢复到Nuxt 3的状态,但这操作不排除会对app目录下的文件路由产生影响。所以这里我用相对路径替换,手动修改了这些文件的引用关系。

另一个变动项是:我把Prisma实例从lib\prisma.ts移动至server\utils\prisma.ts

我最初打算将lib\prisma.ts文件移动至server\lib\prisma.ts,但依旧出现了找不到引用地址的问题。最后看Nuxt推荐的目录结构,将其放到了server\utils目录,就没出现报错了。

关于引用路径替换

最初我用相对路径替换prisma引用,后面发现使用~~也可以指向到根目录,即~~/server/就代表着根目录/server/目录,舒服了😁

调整1:工具类、类型定义文件迁移至shared目录

过去我把工具类放到了lib/utils.ts中,以导出方法的形式在服务端和客户端间调用。在Nuxt中则提供了/shared/目录,放置无状态的、不受运行环境限制的、服务端和客户端都可使用的代码(例如工具类和类型定义文件)。

由于/shared/utils/shared/types下的ts文件,支持方法自动导入(auto-imports),所以这一步我把过去的工具类拆成了单个方法放置在/shared/utils/[xxx].ts;而对于类型定义文件,则直接迁移到/shared/types目录下。

报错4:Cannot find module ‘~/app/assets/css/***.css’ imported from ‘virtual:nuxt: .nuxt/css.mjs’. - If you rely on tsconfig.json’s “paths” to resolve modules, please install “vite-tsconfig-paths” plugin to handle module resolution.

原因是nuxt.config.ts中的css属性配置错误,因为srcDir的指向变了,这里导入的css路径也需要修改。修改完成后,重启项目,问题解决!

1
2
3
4
5
6
7
8
9
10
export default defineNuxtConfig({
// ...
css: [
// 原来的配置
'~/app/assets/css/***.css',

// 修改为
'~/assets/css/***.css',
],
})

报错5:Uncaught (in promise) SyntaxError: The requested module ‘/_nuxt/@fs/xxx/node_modules/@prisma/client/index-browser.js’ does not provide an export named ‘PrismaClient’

这个问题非常奇怪,侧边菜单栏的接口我是在composables中通过useFetch调用后端nuxt接口操作的,它可以正常调用;而我页面中是封装的$fetch调用后端接口,就会出现这个错误。

我试图在Github的两个项目中(@prisma/nuxtprisma)查找解决方案,搜索了一些同样问题的issue,但是评论区的一些答案,对我并不起作用:

我又尝试了降级@prisma/client和新创建Nuxt 4项目测试,效果都不行。降级到@prisma/client@6.4.1,连客户端都无法生成了(提示:Failed to generate Prisma Client.);新创建的Nuxt 4项目在测试时也依旧存在该问题。

重新安装了一个nuxt 4,也仍然存在问题重新安装了一个nuxt 4,也仍然存在问题

我在这个问题上卡了两天,几乎试过了网上所有的解决方案,也和几个AI对话试图去寻找解决方案,最终都没有解决问题。直到有天我无意间点开了@prisma/nuxtPull Requests页面,看到了下图。

看到了一个兼容Nuxt4的合并请求,还被关闭了...看到了一个兼容Nuxt4的合并请求,还被关闭了...

整了半天,插件还不支持Nuxt 4!此时我有点骑虎难下了,其他问题都解决了,就剩下一个Prisma兼容问题。如果让我放弃回滚代码还有点不甘心了(沉没成本已经2天半了😡)。然后我就开始搜Nuxt 4 + Prisma的使用教程,还真搜到一个:在 Nuxt4 中让 Prisma 正常工作。最后我参考文章中的思路,放弃使用@prisma/nuxt,转而使用原生Prisma。

  1. 切换成原生Prisma包;
1
2
3
4
5
# 卸载@prisma/nuxt
npm uninstall @prisma/nuxt

# 安装Prisma
npm install prisma @prisma/client
  1. 调整prisma/schema.prisma
1
2
3
4
5
6
generator client {
provider = "prisma-client-js"

// 这里我和文章中不同,我测试使用非node_modules目录也不影响项目构建
output = "../prisma/generate"
}

测试过构建项目了,没报错!测试过构建项目了,没报错!

  1. 修改nuxt.config.ts,从modules中删除@prisma/nuxt
  2. package.json中增加Prisma的相关命令;
1
2
3
4
5
6
7
8
{
"scripts": {
"prisma:generate": "prisma generate",
"prisma:migrate": "npx prisma migrate dev",
"prisma:reset": "prisma migrate reset",
"prisma:seed": "npx prisma db seed"
}
}

以后schema.prisma结构更新,就要自己执行prisma:generate更新生成Prisma客户端了。

  1. 执行一次prisma:generate生成Prisma客户端;

这里有一点小差别:

  • Nuxt 3升级Nuxt 4不会遇到问题;
  • 新创建的Nuxt 4项目底下多了一个prisma.config.ts配置文件,如果直接运行大概率会报错(Failed to load config file “****” as a TypeScript/JavaScript module. Error: PrismaConfigEnvError: Missing required environment variable: DATABASE_URL)。如果遇到这个报错请参考下方代码修改prisma.config.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 改动1:引用dotenv和fs
import dotenv from 'dotenv';
import fs from 'fs';
// 改动1结束


import { defineConfig, env } from "prisma/config";

// 改动2:检查.env文件是否存在,存在则开始加载配置文件
if(fs.existsSync('.env')) {
dotenv.config({path: '.env'});
} else {
dotenv.config({path: '.env.example'});
}
// 改动2结束

export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
engine: "classic",
datasource: {
url: env("DATABASE_URL"),
},
});
  1. 创建Prisma单例文件;
1
2
3
4
5
6
7
8
9
10
11
12
import { PrismaClient } from "~~/prisma/generate";
export * from "~~/prisma/generate";

const prismaClientSingleton = () => new PrismaClient();

declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;

export const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();

if (process.env.NODE_ENV !== "production") globalThis.prismaGlobal = prisma;
  1. 替换server/api/**/*.ts接口文件的Prisma引用;
  2. 重启项目,问题解决🚀

调整2:删除Vue页面中使用的工具类方法、类型定义的导入代码

在Prisma恢复正常后,页面上开始报错。是由 调整1 里将工具类、类型定义文件迁到shared目录下,导致页面中无法按路径导入文件产生的报错。处理方式也很简单,直接从页面中删除这些导入代码即可(因为shared目录下的这些文件会在运行时自动导入,所以这里不用再处理引用关系了😂)

结尾

整个Nuxt 4升级工作花了我三天时间,两天半的时间卡在 报错5 上,最后终于升级完成了,真不容易😄

我也用上 Nuxt 4了我也用上 Nuxt 4了

艰难升级Nuxt 3.15.4至Nuxt 4.2.0的问题记录

作者:有点东西

链接: https://www.youdiandongxi.com/article/nuxt4-upgrade-log.html

协议:本文采用 CC BY-NC-SA 4.0 隐私协议,转载请注明出处!

评论区