Loading... ## 前言 Nuxt 4 计划于 2025 年第二季度正式发布,带来了大量的性能优化和架构改进。本文将详细介绍 Nuxt 3.x 到 4.0 的所有重大变更,并提供完整的迁移步骤指南。 ## 快速开始:如何测试 Nuxt 4 在正式版发布前,你可以通过以下方式提前体验 Nuxt 4 的特性: ### 1. 升级到最新版本 ```bash # npm npx nuxt upgrade # yarn yarn nuxt upgrade # pnpm pnpm nuxt upgrade # bun bun x nuxt upgrade ``` ### 2. 启用 Nuxt 4 兼容模式 在 `nuxt.config.ts` 中添加: ```typescript export default defineNuxtConfig({ future: { compatibilityVersion: 4, }, }) ``` ### 3. 使用自动化迁移工具 Nuxt 团队与 Codemod 合作提供了自动化迁移工具: ```bash npx codemod@latest nuxt/4/migration-recipe ``` 这个命令会依次执行所有迁移脚本,你可以选择性地运行需要的部分。 --- ## 主要变更详解 ### 🔥 1. 新的目录结构(影响级别:重大) #### 变更内容 Nuxt 4 采用了全新的默认目录结构,具有向后兼容性: **旧结构(Nuxt 3):** ``` . ├── components/ ├── pages/ ├── plugins/ ├── server/ ├── public/ └── nuxt.config.ts ``` **新结构(Nuxt 4):** ``` . ├── app/ # 新增:应用代码目录 │ ├── assets/ │ ├── components/ │ ├── composables/ │ ├── layouts/ │ ├── middleware/ │ ├── pages/ │ ├── plugins/ │ ├── utils/ │ ├── app.vue │ ├── error.vue │ ├── app.config.ts │ └── router.options.ts ├── content/ # 保持在根目录 ├── layers/ # 保持在根目录 ├── modules/ # 保持在根目录 ├── public/ # 保持在根目录 ├── server/ # 保持在根目录 └── nuxt.config.ts # 保持在根目录 ``` #### 关键变更 - **默认 `srcDir` 为 `app/`**:大部分应用代码都放在 `app/` 目录下 - **`serverDir` 默认为 `<rootDir>/server`**:而不是 `<srcDir>/server` - **`~` 别名指向 `app/`**:例如 `~/components` 解析为 `app/components/` - **根目录保留**:`layers/`、`modules/`、`public/`、`server/` 仍在项目根目录 #### 迁移理由 1. **性能优化**:避免 `.git/` 和 `node_modules/` 被文件监视器扫描 2. **IDE 类型安全**:`server/` 和应用代码运行在不同上下文,分离有助于更好的自动补全 #### 迁移步骤 **自动迁移:** ```bash npx codemod@latest nuxt/4/file-structure ``` **手动迁移:** 1. 创建 `app/` 目录 2. 移动以下文件夹到 `app/` 下: - `assets/` - `components/` - `composables/` - `layouts/` - `middleware/` - `pages/` - `plugins/` - `utils/` - `app.vue` - `error.vue` - `app.config.ts` 3. 保持以下文件夹在根目录: - `nuxt.config.ts` - `content/` - `layers/` - `modules/` - `public/` - `server/` 4. 更新第三方配置文件(如 `tailwind.config.js`、`.eslintrc` 等) **如需保持旧结构:** ```typescript export default defineNuxtConfig({ srcDir: '.', dir: { app: 'app' } }) ``` --- ### 🔄 2. 单例数据获取层(影响级别:中等) #### 变更内容 Nuxt 4 重新设计了 `useAsyncData` 和 `useFetch` 的数据获取系统: 1. **共享引用**:相同 key 的所有调用共享 `data`、`error` 和 `status` 引用 2. **响应式 key 支持**:可以使用 computed、ref 或 getter 函数作为 key 3. **数据清理**:组件卸载时自动清理数据,避免内存泄漏 4. **改进的 `getCachedData` 控制**:每次获取数据时都会调用该函数 #### 迁移步骤 **检查冲突选项:** ```typescript // ❌ 错误:相同 key,不同选项 const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false }) const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true }) // ✅ 正确:提取为独立的 composable // composables/useUserData.ts export function useUserData(userId: string) { return useAsyncData( `user-${userId}`, () => fetchUser(userId), { deep: true, transform: (user) => ({ ...user, lastAccessed: new Date() }) } ) } ``` **更新 `getCachedData` 实现:** ```typescript useAsyncData('key', fetchFunction, { getCachedData: (key, nuxtApp, ctx) => { // ctx.cause 可以是:'initial' | 'refresh:hook' | 'refresh:manual' | 'watch' // 例如:手动刷新时不使用缓存 if (ctx.cause === 'refresh:manual') return undefined return cachedData[key] } }) ``` **临时禁用新行为:** ```typescript export default defineNuxtConfig({ experimental: { granularCachedData: false, purgeCachedData: false } }) ``` --- ### 📄 3. 路由元数据去重(影响级别:最小) #### 变更内容 通过 `definePageMeta` 设置的路由元数据(如 `name`、`path`)现在只能从 `route` 对象访问,而不再从 `route.meta` 访问。 #### 迁移步骤 ```typescript const route = useRoute() // ❌ 旧写法 console.log(route.meta.name) // ✅ 新写法 console.log(route.name) ``` --- ### 🏷️ 4. 标准化组件命名(影响级别:中等) #### 变更内容 Vue 生成的组件名称现在匹配 Nuxt 的组件命名模式。 **示例:** ``` components/ └── SomeFolder/ └── MyComponent.vue ``` - **旧命名**:Vue 组件名为 `MyComponent`,Nuxt 自动导入名为 `SomeFolderMyComponent` - **新命名**:两者都为 `SomeFolderMyComponent` #### 迁移步骤 更新测试和 `<KeepAlive>` 中的组件名称: ```vue <!-- ❌ 旧写法 --> <KeepAlive :include="['MyComponent']"> <SomeFolderMyComponent /> </KeepAlive> <!-- ✅ 新写法 --> <KeepAlive :include="['SomeFolderMyComponent']"> <SomeFolderMyComponent /> </KeepAlive> ``` **临时禁用:** ```typescript export default defineNuxtConfig({ experimental: { normalizeComponentNames: false } }) ``` --- ### 🎯 5. Unhead v2 升级(影响级别:最小) #### 变更内容 用于生成 `<head>` 标签的 Unhead 库升级到 v2 版本: - 移除的属性:`vmid`、`hid`、`children`、`body` - 不再支持 Promise 输入 - 默认使用 Capo.js 进行标签排序 #### 迁移步骤 **移除废弃属性:** ```typescript useHead({ meta: [{ name: 'description', content: '描述内容', // ❌ 移除这些 // vmid: 'description', // hid: 'description' }] }) ``` **更新导入路径:** ```typescript // ❌ 旧写法 import { useHead } from '@unhead/vue' // ✅ 新写法 import { useHead } from '#imports' // 或 import { useHead } from 'nuxt/app' ``` **如需使用模板参数或别名排序插件:** ```typescript import { TemplateParamsPlugin, AliasSortingPlugin } from '@unhead/vue/plugins' export default defineNuxtPlugin({ setup() { const unhead = injectHead() unhead.use(TemplateParamsPlugin) unhead.use(AliasSortingPlugin) } }) ``` --- ### 🎨 6. SPA 加载屏幕位置变更(影响级别:最小) #### 变更内容 SPA 加载模板的 DOM 位置改变: ```html <!-- 旧位置 --> <div id="__nuxt"> <!-- spa loading template --> </div> <!-- 新位置 --> <div id="__nuxt"></div> <!-- spa loading template --> ``` #### 迁移理由 允许 SPA 加载模板保持在 DOM 中直到 Vue 应用 suspense 解析完成,防止白屏闪烁。 #### 迁移步骤 更新 CSS 选择器或使用新的配置选项: ```typescript export default defineNuxtConfig({ app: { spaLoaderTag: 'div', spaLoaderAttrs: { id: 'custom-loader' } } }) ``` --- ### 📊 7. error.data 自动解析(影响级别:最小) #### 变更内容 抛出错误时的 `data` 属性现在会自动解析。 #### 迁移步骤 移除手动解析代码: ```vue <script setup lang="ts"> import type { NuxtError } from '#app' const props = defineProps({ error: Object as () => NuxtError }) // ❌ 移除手动解析 // const data = JSON.parse(error.data) // ✅ 直接使用 const data = error.data </script> ``` --- ### 🎨 8. 更细粒度的内联样式(影响级别:中等) #### 变更内容 Nuxt 现在只为 Vue 组件内联样式,不再内联全局 CSS。 #### 迁移理由 - 减少单独的网络请求 - 允许缓存单个全局 CSS 文件 - 减少初始请求的文档下载大小 #### 迁移步骤 如需恢复旧行为: ```typescript export default defineNuxtConfig({ features: { inlineStyles: true } }) ``` --- ### 🔍 9. 页面元数据扫描时机调整(影响级别:最小) #### 变更内容 现在在调用 `pages:extend` 钩子之后扫描页面元数据,而不是之前。 #### 迁移步骤 在 `pages:resolved` 钩子中覆盖页面元数据: ```typescript export default defineNuxtConfig({ hooks: { // ❌ 旧写法 // 'pages:extend'(pages) { // ✅ 新写法 'pages:resolved'(pages) { const myPage = pages.find(page => page.path === '/') myPage.meta ||= {} myPage.meta.layout = 'overridden-layout' } } }) ``` --- ### 🚀 10. 共享预渲染数据(影响级别:中等) #### 变更内容 启用了实验性功能,在不同页面间共享 `useAsyncData` 和 `useFetch` 的数据。 #### 迁移理由 自动在预渲染页面之间共享 payload 数据,显著提升预渲染性能。 #### 迁移步骤 确保每个数据的唯一 key 始终解析为相同的数据: ```typescript // ❌ 不安全:key 不反映实际获取的数据 const route = useRoute() const { data } = await useAsyncData(async () => { return await $fetch(`/api/my-page/${route.params.slug}`) }) // ✅ 安全:key 唯一标识获取的数据 const { data } = await useAsyncData(route.params.slug, async () => { return await $fetch(`/api/my-page/${route.params.slug}`) }) ``` --- ### 📦 11. useAsyncData 和 useFetch 的默认值变更(影响级别:最小) #### 变更内容 - `data` 默认值从 `null` 改为 `undefined` - `error` 默认值从 `null` 改为 `undefined` #### 自动迁移 ```bash npx codemod@latest nuxt/4/default-data-error-value ``` #### 手动迁移 ```typescript // ❌ 旧写法 if (data.value === null) { } if (error.value === null) { } // ✅ 新写法 if (data.value === undefined) { } if (error.value === undefined) { } ``` --- ### 🔄 12. 移除 dedupe 的布尔值(影响级别:最小) #### 变更内容 `refresh` 函数的 `dedupe` 选项不再接受布尔值,必须使用明确的字符串值。 #### 自动迁移 ```bash npx codemod@latest nuxt/4/deprecated-dedupe-value ``` #### 手动迁移 ```typescript const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt!' })) // ❌ 旧写法 await refresh({ dedupe: true }) await refresh({ dedupe: false }) // ✅ 新写法 await refresh({ dedupe: 'cancel' }) await refresh({ dedupe: 'defer' }) ``` --- ### 🎯 13. 清除数据时尊重默认值(影响级别:最小) #### 变更内容 调用 `clear` 或 `clearNuxtData` 时,`data` 会重置为其默认值而不是 `undefined`。 #### 示例 ```typescript const { data, clear } = useAsyncData('key', fetchData, { default: () => [] }) // 调用 clear() 后,data.value 将是 [],而不是 undefined ``` --- ### ⏳ 14. pending 值对齐(影响级别:中等) #### 变更内容 `pending` 现在是一个计算属性,只有当 `status` 为 `'pending'` 时才为 `true`。 #### 迁移步骤 ```vue <template> <!-- ❌ 旧写法 --> <!-- <div v-if="!pending"> --> <!-- ✅ 新写法 --> <div v-if="status === 'success'"> <p>Data: {{ data }}</p> </div> <div v-else> <p>Loading...</p> </div> </template> <script setup lang="ts"> const { data, pending, execute, status } = await useAsyncData( () => fetch('/api/data'), { immediate: false } ) onMounted(() => execute()) </script> ``` --- ### 🔑 15. Key 变更行为调整(影响级别:中等) #### 变更内容 当 `immediate: false` 时,`useAsyncData` 和 `useFetch` 只有在数据已经获取过一次后,才会在 key 变更时重新获取数据。 #### 迁移步骤 ```typescript const id = ref('123') const { data, execute } = await useFetch('/api/test', { query: { id }, immediate: false }) // ✅ 需要手动触发第一次 watch(id, execute, { once: true }) ``` --- ### 📉 16. 浅层数据响应性(影响级别:最小) #### 变更内容 `data` 对象现在是 `shallowRef` 而不是 `ref`。 #### 迁移理由 对深层嵌套对象和数组带来显著的性能提升。 #### 自动迁移 ```bash npx codemod@latest nuxt/4/shallow-function-reactivity ``` #### 手动迁移 **按需启用深度响应性:** ```typescript // ✅ 单个组件启用 const { data } = useFetch('/api/test', { deep: true }) ``` **全局配置(不推荐):** ```typescript export default defineNuxtConfig({ experimental: { defaults: { useAsyncData: { deep: true } } } }) ``` --- ### 📁 17. builder:watch 绝对路径(影响级别:最小) #### 变更内容 `builder:watch` 钩子现在发出绝对路径而不是相对于 `srcDir` 的路径。 #### 自动迁移 ```bash npx codemod@latest nuxt/4/absolute-watch-path ``` #### 手动迁移(模块作者) ```typescript import { relative, resolve } from 'node:fs' nuxt.hook('builder:watch', async (event, path) => { // 使其兼容 Nuxt 3 和 4 path = relative(nuxt.options.srcDir, resolve(nuxt.options.srcDir, path)) // ... }) ``` --- ### 🌐 18. 移除 window.__NUXT__ 对象(影响级别:最小) #### 变更内容 应用完成水合后,全局 `window.__NUXT__` 对象将被移除。 #### 迁移步骤 ```typescript // ❌ 旧写法 console.log(window.__NUXT__) // ✅ 新写法 console.log(useNuxtApp().payload) ``` --- ### 📂 19. 目录索引文件扫描(影响级别:中等) #### 变更内容 `middleware/` 文件夹中的子文件夹的 `index` 文件现在也会被注册为 middleware。 #### 迁移步骤 如需恢复旧行为: ```typescript export default defineNuxtConfig({ hooks: { 'app:resolve'(app) { app.middleware = app.middleware.filter( mw => !/\/index\.[^/]+$/.test(mw.path) ) } } }) ``` --- ### 📝 20. 模板编译变更(影响级别:最小) #### 变更内容 Nuxt 不再使用 `lodash/template` 编译 `.ejs` 模板文件。 #### 迁移理由 - 移除安全漏洞 - 减少依赖体积 - 更灵活的虚拟语法 #### 迁移步骤 **自动迁移:** ```bash npx codemod@latest nuxt/4/template-compilation-changes ``` **手动迁移方案:** **方案 1:使用 `getContents()` 直接处理** ```typescript addTemplate({ fileName: 'my-template.js', getContents({ options }) { return `export default ${JSON.stringify(options)}` } }) ``` **方案 2:使用 `es-toolkit/compat`** ```typescript import { readFileSync } from 'node:fs' import { template } from 'es-toolkit/compat' addTemplate({ fileName: 'appinsights-vue.js', options: { /* some options */ }, getContents({ options }) { const contents = readFileSync( resolver.resolve('./runtime/plugin.ejs'), 'utf-8' ) return template(contents)({ options }) } }) ``` **替换模板工具:** ```typescript import { genDynamicImport, genImport, genSafeVariableName } from 'knitwork' // 替换 serialize const serialize = (data: any) => JSON.stringify(data, null, 2) .replace(/"{(.+)}"(?=,?$)/gm, r => JSON.parse(r).replace(/^{(.*)}$/, '$1')) // 替换 importName const importName = genSafeVariableName // 替换 importSources const importSources = (sources: string | string[], { lazy = false } = {}) => { return toArray(sources).map((src) => { if (lazy) { return `const ${genSafeVariableName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}` } return genImport(src, genSafeVariableName(src)) }).join('\n') } ``` --- ### 🔧 21. TypeScript 配置变更(影响级别:最小) #### 变更内容 Nuxt 现在为不同上下文生成独立的 TypeScript 配置: - `.nuxt/tsconfig.app.json` - 应用代码 - `.nuxt/tsconfig.server.json` - 服务器代码 - `.nuxt/tsconfig.node.json` - 构建时代码 - `.nuxt/tsconfig.shared.json` - 共享代码 - `.nuxt/tsconfig.json` - 向后兼容 #### 迁移理由 - 更好的类型安全 - 改进的 IDE 体验 - 更清晰的分离 - 性能优化 #### 迁移步骤(可选) **启用项目引用:** 更新根 `tsconfig.json`: ```json { "files": [], "references": [ { "path": "./.nuxt/tsconfig.app.json" }, { "path": "./.nuxt/tsconfig.server.json" }, { "path": "./.nuxt/tsconfig.shared.json" }, { "path": "./.nuxt/tsconfig.node.json" } ] } ``` **更新类型检查脚本:** ```json { "scripts": { "typecheck": "nuxt prepare && vue-tsc -b --noEmit" } } ``` **配置 Node.js TypeScript 选项:** ```typescript export default defineNuxtConfig({ typescript: { // 自定义 app/server TypeScript 配置 tsConfig: { compilerOptions: { strict: true } }, // 自定义构建时 TypeScript 配置 nodeTsConfig: { compilerOptions: { strict: true } } } }) ``` --- ### 🗑️ 22. 移除实验性特性(影响级别:最小) #### 变更内容 以下实验性特性不再可配置: - `experimental.treeshakeClientOnly` - 将为 `true` - `experimental.configSchema` - 将为 `true` - `experimental.polyfillVueUseHead` - 将为 `false` - `experimental.respectNoSSRHeader` - 将为 `false` - `vite.devBundler` - 将默认使用 `vite-node` --- ### 📋 23. 移除顶层 generate 配置(影响级别:最小) #### 变更内容 顶层 `generate` 配置选项不再可用。 #### 迁移步骤 ```typescript export default defineNuxtConfig({ // ❌ 旧写法 // generate: { // exclude: ['/admin', '/private'], // routes: ['/sitemap.xml', '/robots.txt'] // } // ✅ 新写法 nitro: { prerender: { ignore: ['/admin', '/private'], routes: ['/sitemap.xml', '/robots.txt'] } } }) ``` --- ## 完整迁移清单 ### 准备阶段 - [ ] 升级到最新的 Nuxt 3.x 版本 - [ ] 备份项目代码 - [ ] 运行现有测试确保一切正常 ### 自动化迁移 - [ ] 运行完整迁移工具: ```bash npx codemod@latest nuxt/4/migration-recipe ``` ### 手动检查项 - [ ] 检查并调整新的目录结构 - [ ] 更新 `useAsyncData` 和 `useFetch` 调用 - [ ] 检查共享 key 的数据获取是否有冲突选项 - [ ] 更新路由元数据访问方式 - [ ] 更新组件名称引用 - [ ] 移除 `useHead` 中的废弃属性 - [ ] 检查 SPA 加载模板相关的 CSS - [ ] 移除 `error.data` 的手动解析 - [ ] 更新 `dedupe` 选项的布尔值为字符串 - [ ] 检查 `pending` 状态的使用 - [ ] 为需要深度响应性的数据添加 `deep: true` - [ ] 更新 `builder:watch` 钩子(如果是模块作者) - [ ] 替换 `window.__NUXT__` 为 `useNuxtApp().payload` - [ ] 迁移 `.ejs` 模板文件 - [ ] 更新 `generate` 配置为 `nitro.prerender` - [ ] (可选)启用新的 TypeScript 项目引用 ### 测试阶段 - [ ] 运行类型检查:`npm run typecheck` - [ ] 运行单元测试 - [ ] 运行 E2E 测试 - [ ] 本地开发环境测试 - [ ] 预渲染测试(如果使用) - [ ] 生产构建测试 ### 配置文件更新 - [ ] 更新 `tailwind.config.js`(如果使用) - [ ] 更新 `.eslintrc`(如果使用) - [ ] 更新其他第三方配置文件 --- ## 性能优化建议 迁移到 Nuxt 4 后,你可以享受以下性能提升: 1. **更快的启动时间**:新的目录结构减少了文件监视器的扫描范围 2. **更好的内存管理**:自动清理未使用的数据 3. **优化的 CSS 处理**:更细粒度的样式内联策略 4. **改进的预渲染**:共享数据减少重复请求 5. **浅层响应性**:深层嵌套数据的性能提升 --- ## 常见问题 ### Q: 必须立即迁移到 Nuxt 4 吗? **A:** 不必须。Nuxt 4 预计在 2025 年 Q2 发布,你可以继续使用 Nuxt 3.x。但建议提前测试兼容性,并逐步迁移。 ### Q: 如何在不破坏现有功能的情况下测试 Nuxt 4? **A:** 使用 `compatibilityVersion: 4` 配置可以选择性地启用 Nuxt 4 特性,同时可以通过配置项恢复 Nuxt 3 的行为。建议在开发分支上测试。 ### Q: 自动迁移工具安全吗? **A:** Codemod 工具是官方推荐的,但建议: 1. 先备份代码 2. 使用版本控制 3. 仔细审查自动生成的变更 4. 运行完整的测试套件 ### Q: 旧的目录结构还能用吗? **A:** 可以。Nuxt 会自动检测旧结构。如果检测到顶层的 `pages/` 目录,新的目录结构不会生效。你也可以通过配置强制使用旧结构。 ### Q: 如何处理第三方模块的兼容性? **A:** 1. 检查模块的官方文档是否有 Nuxt 4 更新 2. 在 GitHub 上查看模块的 issues 和 PR 3. 如有问题,向模块作者报告 4. Nuxt 团队已经主动迁移了许多流行模块 ### Q: TypeScript 项目引用是必须的吗? **A:** 不是必须的。现有项目继续使用 `.nuxt/tsconfig.json` 即可。项目引用是可选的优化,提供更好的类型检查体验。 ### Q: 迁移后性能会提升多少? **A:** 取决于项目规模和使用的特性: - 小型项目可能感受不明显 - 大型项目在启动时间、内存使用和预渲染方面会有显著提升 - 使用大量 `useAsyncData` 的项目会从新的数据获取系统中受益 ### Q: 如何回退到 Nuxt 3? **A:** 1. 移除 `compatibilityVersion: 4` 配置 2. 恢复相关的实验性选项配置 3. 如果调整了目录结构,可以通过配置恢复或手动移回 --- ## 版本对比 ### Nuxt 2 vs Nuxt 3 vs Nuxt 4 | 特性/版本 | Nuxt 2 | Nuxt 3 | Nuxt 4 | | ------------------ | ------------- | ---------------- | ---------------------- | | Vue 版本 | 2 | 3 | 3 | | 稳定性 | 😊 稳定 | 😊 稳定 | 😊 稳定 | | 性能 | 🏎 快速 | ✈️ 更快 | 🚀 最快 | | Nitro 引擎 | ❌ | ✅ | ✅ | | ESM 支持 | 🌙 部分 | 👍 更好 | ✅ 完整 | | TypeScript | ☑️ 可选 | ✅ 完整 | ✅ 完整 | | Composition API | ❌ | ✅ | ✅ | | `<script setup>` | ❌ | ✅ | ✅ | | 自动导入 | ❌ | ✅ | ✅ | | webpack | 4 | 5 | 5 | | Vite | ⚠️ 部分 | ✅ | ✅ | | 目录结构 | 扁平 | 扁平 | `app/` 目录 | | 数据获取 | `asyncData` | `useAsyncData` | 增强的`useAsyncData` | --- ## 推荐迁移时间线 ### 阶段 1:准备期(1-2 周) - 升级到最新的 Nuxt 3.x - 阅读官方迁移文档 - 在开发分支启用 `compatibilityVersion: 4` - 运行自动迁移工具 ### 阶段 2:测试期(2-4 周) - 修复自动迁移后的问题 - 运行完整测试套件 - 进行性能基准测试 - 处理第三方模块兼容性问题 ### 阶段 3:逐步部署(2-4 周) - 先在开发/测试环境部署 - 收集反馈和监控性能 - 修复发现的问题 - 准备回滚方案 ### 阶段 4:生产部署 - 选择低流量时段部署 - 密切监控错误和性能指标 - 准备快速回滚 --- ## 迁移资源 ### 官方资源 - **Nuxt 4 文档**: https://nuxt.com/docs/4.x - **升级指南**: https://nuxt.com/docs/4.x/getting-started/upgrade - **GitHub 仓库**: https://github.com/nuxt/nuxt - **发布说明**: https://github.com/nuxt/nuxt/releases ### 自动化工具 - **Codemod 注册表**: https://go.codemod.com/codemod-registry - **Nuxt 4 迁移配方**: ```bash npx codemod@latest nuxt/4/migration-recipe ``` ### 社区支持 - **Discord**: https://discord.com/invite/nuxt - **GitHub Discussions**: https://github.com/nuxt/nuxt/discussions - **Twitter/X**: @nuxt_js ### 相关库更新 - **Unhead v2**: https://unhead.unjs.io/ - **Nitro**: https://nitro.unjs.io/ - **Knitwork**: https://github.com/unjs/knitwork - **es-toolkit**: https://es-toolkit.slash.page/ --- ## 总结 Nuxt 4 带来了大量的性能优化和开发体验改进,主要变更包括: ### 🎯 核心变更 1. **新的 `app/` 目录结构** - 更好的性能和类型安全 2. **增强的数据获取系统** - 更好的内存管理和状态共享 3. **改进的类型系统** - 独立的上下文配置 ### 🚀 性能提升 - 更快的启动时间 - 更低的内存占用 - 优化的 CSS 处理 - 改进的预渲染性能 ### 🛠️ 开发体验 - 更好的 IDE 支持 - 更清晰的错误信息 - 自动化迁移工具 - 向后兼容性支持 ### ✅ 推荐做法 1. 使用自动迁移工具快速开始 2. 在开发分支先测试 3. 逐步启用新特性 4. 保持依赖更新 5. 关注官方发布说明 虽然 Nuxt 4 引入了一些破坏性变更,但大部分都可以通过自动化工具完成迁移,并且 Nuxt 提供了充分的配置选项来保持向后兼容。建议尽早开始测试,以便在正式版发布时能够顺利升级。 --- ## 附录:完整配置示例 ### Nuxt 4 完整配置示例 ```typescript // nuxt.config.ts export default defineNuxtConfig({ // 启用 Nuxt 4 兼容模式 future: { compatibilityVersion: 4, }, // TypeScript 配置 typescript: { strict: true, typeCheck: true, tsConfig: { compilerOptions: { strict: true, } }, nodeTsConfig: { compilerOptions: { strict: true, } } }, // Nitro 配置(替代旧的 generate 配置) nitro: { prerender: { routes: ['/sitemap.xml', '/robots.txt'], ignore: ['/admin', '/api'], } }, // 应用配置 app: { head: { charset: 'utf-8', viewport: 'width=device-width, initial-scale=1', }, // SPA 加载器配置 spaLoaderTag: 'div', spaLoaderAttrs: { id: 'spa-loader' } }, // 特性配置 features: { // 内联样式策略 inlineStyles: false, }, // Unhead 配置 unhead: { renderSSRHeadOptions: { omitLineBreaks: true } }, // 实验性特性(如需临时恢复 Nuxt 3 行为) experimental: { // 这些是示例,通常不需要配置 // scanPageMeta: 'after-resolve', // sharedPrerenderData: true, // defaults: { // useAsyncData: { // deep: false // } // } }, // 钩子示例 hooks: { 'pages:resolved'(pages) { // 在这里修改页面配置 }, 'builder:watch'(event, path) { // 处理文件变更 } } }) ``` ### Package.json 脚本示例 ```json { "name": "my-nuxt4-app", "version": "1.0.0", "scripts": { "dev": "nuxt dev", "build": "nuxt build", "generate": "nuxt generate", "preview": "nuxt preview", "postinstall": "nuxt prepare", "typecheck": "nuxt prepare && vue-tsc -b --noEmit", "lint": "eslint .", "migrate": "npx codemod@latest nuxt/4/migration-recipe" }, "dependencies": { "nuxt": "^3.12.0", "vue": "^3.4.0" }, "devDependencies": { "@nuxt/eslint": "latest", "typescript": "^5.3.0", "vue-tsc": "^2.0.0" } } ``` ### TypeScript 配置示例(使用项目引用) ```json // tsconfig.json { "files": [], "references": [ { "path": "./.nuxt/tsconfig.app.json" }, { "path": "./.nuxt/tsconfig.server.json" }, { "path": "./.nuxt/tsconfig.shared.json" }, { "path": "./.nuxt/tsconfig.node.json" } ] } ``` --- *本文翻译整理自Nuxt官方文档,由IvanHanloth主写,使用Claude进行翻译、代码修正和文风调整,请注意检查潜在的错误。请以Nuxt官方文档为准。* Last modification:September 30, 2025 © Allow specification reprint Support Appreciate the author AliPayWeChat Like 如果觉得我的文章对你有用,请随意赞赏