要将 Nuxt 升级到最新版本,请使用 nuxt upgrade 命令。
npx nuxt upgrade
yarn nuxt upgrade
pnpm nuxt upgrade
bun x nuxt upgrade
要在新特性发布前使用最新的 Nuxt 构建并进行测试,请阅读 每日构建版本渠道 指南。
latest 标签目前跟踪 Nuxt v4 分支,这意味着现在特别可能存在破坏性更改 —— 请务必小心!你可以通过 "nuxt": "npm:nuxt-nightly@3x" 选择使用 3.x 分支的每日构建版本。Nuxt 4 计划于 2025 年第二季度发布。它将包含所有当前通过 compatibilityVersion: 4 可用的功能。
在正式发布之前,可以从 Nuxt 3.12 版本开始测试许多 Nuxt 4 的破坏性更改。
首先,将 Nuxt 升级到最新版本。
然后,你可以设置 compatibilityVersion 来匹配 Nuxt 4 的行为:
export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
// 若要重新启用 _全部_ Nuxt v3 的行为,请设置以下选项:
// srcDir: '.',
// dir: {
// app: 'app'
// },
// experimental: {
// scanPageMeta: 'after-resolve',
// sharedPrerenderData: false,
// compileTemplate: true,
// resetAsyncDataToUndefined: true,
// templateUtils: true,
// relativeWatchPaths: true,
// normalizeComponentNames: false,
// spaLoadingTemplateLocation: 'within',
// parseErrorData: false,
// pendingWhenIdle: true,
// alwaysRunFetchOnKeyChange: true,
// defaults: {
// useAsyncData: {
// deep: true
// }
// }
// },
// features: {
// inlineStyles: true
// },
// unhead: {
// renderSSRHeadOptions: {
// omitLineBreaks: false
// }
// }
})
compatibilityVersion。在 Nuxt 4 发布后,将不再需要这样做。当你将 compatibilityVersion 设置为 4 时,Nuxt 配置中的默认值将更改以适应 Nuxt v4 行为,但你可以根据上面注释的行内容,在测试中逐步重新启用 Nuxt v3 的行为。如果遇到问题,请提交 issue,方便我们在 Nuxt 或生态系统中修复。
重大或破坏性变更将会在这里进行说明,并提供向前/向后兼容的迁移步骤。
compatibilityVersion: 4 测试 Nuxt 4,请定期回来查看。为了简化升级流程,我们与 Codemod 团队合作,提供了一些开源的代码转换工具(codemods)来自动执行许多迁移步骤。
npx codemod feedback 向 Codemod 团队反馈 🙏有关完整的 Nuxt 4 codemods 列表、每个工具的详细信息、源码和多种运行方式,请访问 Codemod 注册表。
你可以使用以下 codemod 命令执行本指南中提到的所有 codemods:
# Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
npx codemod@0.18.7 nuxt/4/migration-recipe
# Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
yarn dlx codemod@0.18.7 nuxt/4/migration-recipe
# Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
pnpm dlx codemod@0.18.7 nuxt/4/migration-recipe
# Using pinned version due to https://github.com/codemod-com/codemod/issues/1710
bun x codemod@0.18.7 nuxt/4/migration-recipe
该命令将会按顺序运行所有 codemods,你还可以选择不执行某些不想运行的;每个 codemod 也在下文列出,并可单独运行。
🚦 影响等级:重大
Nuxt 默认采用新的目录结构,但保持向后兼容(如果 Nuxt 检测到你使用的是旧结构,比如顶级的 pages/ 目录,则不会应用这个新结构)。
srcDir 现在是 app/,大部分内容都从这里解析。serverDir 默认从 <rootDir>/server 而非 <srcDir>/serverlayers/、modules/ 和 public/ 目录默认相对于 <rootDir> 解析content/ 相对于 <rootDir> 解析dir.app,这是寻找 router.options.ts 和 spa-loading-template.html 的目录,默认是 <srcDir>/.output/
.nuxt/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.config.ts
app.vue
router.options.ts
content/
layers/
modules/
node_modules/
public/
shared/
server/
api/
middleware/
plugins/
routes/
utils/
nuxt.config.ts
👉 详情可见 实现此变更的 PR。
.git/ 和 node_modules/ 文件夹被文件系统监听器扫描/包含,这可能在非 macOS 系统上显著延长启动时间。server/ 目录与应用其余部分运行在两个完全不同的环境中,拥有不同的全局导入。确保 server/ 不在应用程序其余部分的相同目录中是实现 IDE 良好自动补全的第一大步。app/ 的新目录。assets/、components/、composables/、layouts/、middleware/、pages/、plugins/ 和 utils/ 文件夹移到其中,以及 app.vue、error.vue、app.config.ts。如果你已有 app/router-options.ts 或 app/spa-loading-template.html,路径保持不变。nuxt.config.ts、content/、layers/、modules/、public/ 和 server/ 文件夹留在项目根目录(app/ 外)。tailwindcss 或 eslint 配置(如果需要的话,@nuxtjs/tailwindcss 会自动配置正确的 tailwindcss)。npx codemod@latest nuxt/4/file-structure 来自动化此迁移。然而,迁移 非必需。如果想继续使用当前的文件夹结构,Nuxt 会自动检测。如果没有检测到,请提交 issue。唯一的例外是如果你已经自定义了 srcDir。此时,你需要知道 modules/、public/ 和 server/ 文件夹会从你的 rootDir 解析,而不是从自定义的 srcDir。如有需要,你可通过配置 dir.modules、dir.public 和 serverDir 来覆盖。
你也可以通过以下配置强制使用 v3 文件夹结构:
export default defineNuxtConfig({
// 将新的 srcDir 默认值从 `app` 改回根目录
srcDir: '.',
// 指定 `app/router.options.ts` 和 `app/spa-loading-template.html` 的目录前缀
dir: {
app: 'app',
},
})
🚦 影响等级:中等
Nuxt 的数据获取系统 (useAsyncData 和 useFetch) 已经被大幅重构,以提升性能和一致性:
useAsyncData 或 useFetch 并使用相同 key 的调用都会共享同一份 data、error 和 status refs。这意味着所有带显式 key 的调用的选项 deep、transform、pick、getCachedData 或 default 不能冲突。getCachedData 更多控制:现在无论数据是否来自 watcher 还是通过调用 refreshNuxtData,每次请求数据时都会调用 getCachedData。之前这些场景下会强制重新获取数据而不调用该函数。为了更灵活地控制何时使用缓存数据,函数接收的上下文参数中包含了请求来源。useAsyncData 获取数据的组件卸载时,Nuxt 会移除这条数据,避免内存持续增长。这些修改是为了改善内存使用效率和提升多个调用之间加载状态的一致性。
// 这将触发警告
const { data: users1 } = useAsyncData('users', () => $fetch('/api/users'), { deep: false })
const { data: users2 } = useAsyncData('users', () => $fetch('/api/users'), { deep: true })
export function useUserData (userId: string) {
return useAsyncData(
`user-${userId}`,
() => fetchUser(userId),
{
deep: true,
transform: user => ({ ...user, lastAccessed: new Date() }),
},
)
}
getCachedData 的实现:useAsyncData('key', fetchFunction, {
- getCachedData: (key, nuxtApp) => {
- return cachedData[key]
- }
+ getCachedData: (key, nuxtApp, ctx) => {
+ // ctx.cause - 可能是 'initial' | 'refresh:hook' | 'refresh:manual' | 'watch'
+
+ // 例子:手动刷新时不使用缓存
+ if (ctx.cause === 'refresh:manual') return undefined
+
+ return cachedData[key]
+ }
})
你也可以通过以下配置关闭该行为:
export default defineNuxtConfig({
experimental: {
granularCachedData: false,
purgeCachedData: false,
},
})
🚦 影响等级:最低
使用 Nuxt Layers 时,模块加载顺序被修正。之前项目根目录的模块会优先加载,导致顺序与预期相反。
现在模块加载顺序正确:
影响包括:
nuxt.config.ts 的 modules 数组中声明的模块modules/ 目录的自动发现模块此变化确保:
大多数项目无需更改,该修正使加载顺序与预期一致。
但如果你的项目依赖之前的错误顺序,可能需要:
正确顺序示例:
// Layer: my-layer/nuxt.config.ts
export default defineNuxtConfig({
modules: ['layer-module-1', 'layer-module-2'],
})
// Project: nuxt.config.ts
export default defineNuxtConfig({
extends: ['./my-layer'],
modules: ['project-module-1', 'project-module-2'],
})
// 加载顺序(已修正):
// 1. layer-module-1
// 2. layer-module-2
// 3. project-module-1(可以覆盖 layer 模块)
// 4. project-module-2(可以覆盖 layer 模块)
如果因需注册钩子而遇到模块加载顺序问题,可考虑使用 modules:done 钩子,该钩子在所有模块加载完成后调用,安全使用。
👉 详情见 PR #31507 及 issue #25719。
🚦 影响等级:最低
通过 definePageMeta 设置的某些路由元数据(如 name、path 等),之前既存在于 route 对象上,也存在于路由元数据中(例如 route.name 与 route.meta.name)。
现在它们仅存在于路由对象上。
该变化是开启默认 experimental.scanPageMeta 后的性能优化。
迁移很简单:
const route = useRoute()
- console.log(route.meta.name)
+ console.log(route.name)
🚦 影响等级:中等
Vue 现在会生成符合 Nuxt 组件命名规范的组件名称。
如果没有手动设置组件名称,Vue 默认将组件名称设为组件的文件名。
例如目录结构:
├─ components/
├─── SomeFolder/
├───── MyComponent.vue
Vue 中,该组件名称为 MyComponent。用于 <KeepAlive> 或 Vue DevTools 时即是此名称。
但自动导入时需要用 SomeFolderMyComponent。
现在这两个名称将统一,Vue 会生成匹配 Nuxt 组件命名规范的名称。
请确保所有依赖组件名称的测试(如使用 @vue/test-utils 的 findComponent)和 <KeepAlive> 标签使用更新后的名称。
你也可以暂时通过以下配置关闭该行为:
export default defineNuxtConfig({
experimental: {
normalizeComponentNames: false,
},
})
🚦 影响等级:最低
生成 <head> 标签的 Unhead 更新至版本 2。大多数兼容,但底层 API 有若干破坏性变更:
vmid、hid、children、body。上述变更对应用影响较小。
确保未使用已移除属性:
useHead({
meta: [{
name: 'description',
// meta 标签不再需要 vmid 或 key
- vmid: 'description'
- hid: 'description'
}]
})
import { AliasSortingPlugin, TemplateParamsPlugin } from '@unhead/vue/plugins'
export default defineNuxtPlugin({
setup () {
const unhead = injectHead()
unhead.use(TemplateParamsPlugin)
unhead.use(AliasSortingPlugin)
},
})
虽然不是必需的,但建议将任何从 @unhead/vue 的导入更新为 #imports 或 nuxt/app。
-import { useHead } from '@unhead/vue'
+import { useHead } from '#imports'
若仍有问题,可通过开启旧版模式恢复 v1 行为:
export default defineNuxtConfig({
unhead: {
legacy: true,
},
})
🚦 影响等级:最低
客户端渲染页面(ssr: false)时,Nuxt 加载屏幕(取自 app/spa-loading-template.html)默认渲染位置由:
<div id="__nuxt">
<!-- spa loading template -->
</div>
变更为:
<div id="__nuxt"></div>
<!-- spa loading template -->
加载模板不再包裹在 #_nuxt 内侧。
此举确保加载模板保留在 DOM 中直到 Vue Suspense 解析完成,防止白屏闪烁。
若有使用 CSS 或 document.querySelector 针对加载模板,需更新选择器。可用新配置 app.spaLoaderTag 和 app.spaLoaderAttrs 协助。
若需恢复旧行为:
export default defineNuxtConfig({
experimental: {
spaLoadingTemplateLocation: 'within',
},
})
error.data🚦 影响等级:最低
之前抛出的错误对象中的 data 未被解析。现在该字段被解析后可直接使用。虽然是修正,但对依赖旧行为自行解析数据的用户属于破坏性变更。
更新自定义的 error.vue,移除对 error.data 的额外解析:
<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>
你也可关闭该实验特性:
export default defineNuxtConfig({
experimental: {
parseErrorData: false,
},
})
🚦 影响等级:中等
Nuxt 仅对 Vue 组件内联样式,而非所有全局 CSS。
之前 Nuxt 会将所有 CSS(含全局样式)内联并移除 <link> 标签;现在只内联 Vue 组件的 CSS(这些组件之前会拆分成独立 CSS chunk)。这避免首屏请求独立 .css 文件,支持缓存单一全局 CSS,减少初始文档大小。
你可以通过启用旧行为:
export default defineNuxtConfig({
features: {
inlineStyles: true,
},
})
🚦 影响等级:最低
扫描页面元数据(definePageMeta)的时机改为在 pages:extend 钩子之后,而非之前。
能扫描 pages:extend 中新增的页面元数据。新增钩子 pages:resolved 用于修改或覆盖元数据。
如需覆盖页面元数据,应在 pages:resolved 钩子中进行:
export default defineNuxtConfig({
hooks: {
- 'pages:extend'(pages) {
+ 'pages:resolved'(pages) {
const myPage = pages.find(page => page.path === '/')
myPage.meta ||= {}
myPage.meta.layout = 'overridden-layout'
}
}
})
你也可通过配置恢复旧行为:
export default defineNuxtConfig({
experimental: {
scanPageMeta: true,
},
})
🚦 影响等级:中等
启用了之前的实验特性,支持在不同页面间共享 useAsyncData 和 useFetch 调用的数据。详情见 相关 PR。
该功能允许预渲染时在页面间共享数据载荷,显著提升多页面请求同一数据(如导航栏数据)的性能。
确保所有数据 key 唯一映射对应数据。例如动态页面中,useAsyncData 的 key 应唯一标识请求资源:
// 这是不安全的,因为 slug 影响数据但 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}`)
})
你可通过配置关闭该功能:
export default defineNuxtConfig({
experimental: {
sharedPrerenderData: false,
},
})
useAsyncData 和 useFetch 中默认的 data 和 error 值🚦 影响等级:最低
useAsyncData 返回的 data 和 error 默认值现在为 undefined(此前分别为 null 和 null/undefined)。
保证初始化一致性。
如果代码中检查 null,请改为检查 undefined,例如:
if (data.value === undefined) { ... }
npx codemod@latest nuxt/4/default-data-error-value。若遇问题可关闭此变更:
export default defineNuxtConfig({
experimental: {
defaults: {
useAsyncData: {
value: 'null',
errorValue: 'null',
},
},
},
})
如果您正在这样做,请报告问题,因为我们不打算将其保持为可配置项。
useAsyncData 和 useFetch 中调用 refresh 时,dedupe 选项已弃用的 boolean 值🚦 影响级别:最低
之前可以传递 dedupe: boolean 给 refresh。这些是 cancel(true)和 defer(false)的别名。
const { refresh } = await useAsyncData(() => Promise.resolve({ message: 'Hello, Nuxt!' }))
async function refreshData () {
await refresh({ dedupe: true })
}
为了更清晰,这些别名已被移除。
在为 useAsyncData 添加 dedupe 选项时出现了这个问题,我们移除了布尔值,因为它们最终变成了_相反_的意思。
refresh({ dedupe: false }) 的意思是不要为了这个新请求而取消已有的请求。但在 useAsyncData 的选项中传递 dedupe: true 则表示如果已有挂起的请求,则不再发起新的请求。(参见 PR。)
迁移应该很简单:
const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt!' }))
async function refreshData () {
- await refresh({ dedupe: true })
+ await refresh({ dedupe: 'cancel' })
- await refresh({ dedupe: false })
+ await refresh({ dedupe: 'defer' })
}
npx codemod@latest nuxt/4/deprecated-dedupe-value。useAsyncData 和 useFetch 清理数据时遵守默认值🚦 影响等级:最低
调用 clear 或 clearNuxtData 时,若设置了 default 值,则用默认值重置数据,而非直接清空。
尊重用户自定义默认空值,避免频繁检查 null 或 undefined。
遇问题可暂用配置关闭该行为:
export default defineNuxtConfig({
experimental: {
resetAsyncDataToUndefined: true,
},
})
未来该配置可能移除。
useAsyncData 和 useFetch 中 pending 值对齐🚦 影响等级:中等
useAsyncData、useFetch、useLazyAsyncData 和 useLazyFetch 返回的 pending 现在为计算属性,且仅在 status 为 pending 时返回 true。
当设置 immediate: false 时,pending 在首次请求发起前保持 false(之前始终为 true)。
保证 pending 和 status 一致,均表示请求中状态。
依赖 pending 的逻辑需遵循新语义,示例:
<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>
可用配置临时恢复旧行为:
export default defineNuxtConfig({
experimental: {
pendingWhenIdle: true,
},
})
useAsyncData 和 useFetch 中 key 变更行为🚦 影响等级:中等
响应式 key 变化时,useAsyncData 仅在已有数据时重新请求数据,符合 immediate: false 语义。useFetch 行为现在与之保持一致,均不会无条件请求。
统一行为防止意外请求。关闭自动请求时,需手动调用 refresh 或 execute。
如依赖旧行为自动请求,可手动注册监听:
const id = ref('123')
const { data, execute } = await useFetch('/api/test', {
query: { id },
immediate: false
})
+ watch(id, () => execute(), { once: true })
可全局禁用该行为:
// 或于 Nuxt 配置
export default defineNuxtConfig({
experimental: {
alwaysRunFetchOnKeyChange: true,
},
})
useAsyncData 和 useFetch 中的数据浅层响应性🚦 影响等级:最低
useAsyncData、useFetch、useLazyAsyncData 及 useLazyFetch 返回的 data 由 ref 变为 shallowRef。
新数据到达时替换 data 对象触发响应;修改内部属性不再触发响应。
极大提升深层嵌套对象性能,避免监听每个属性。多数场景数据应保持不变。
一般无需变更。若依赖深层响应性:
- const { data } = useFetch('/api/test')
+ const { data } = useFetch('/api/test', { deep: true })
export default defineNuxtConfig({
experimental: {
defaults: {
useAsyncData: {
deep: true,
},
},
},
})
npx codemod@latest nuxt/4/shallow-function-reactivitybuilder:watch 中的绝对路径监听🚦 影响等级:最低
builder:watch 钩子回调的路径现为绝对路径(非相对于 srcDir 的相对路径)。
支持监听 srcDir 以外路径,更好支持多层和复杂场景。
我们已自动迁移公共 Nuxt 模块,详情见 issue #25339。
作为模块作者,兼容写法示例:
+ import { relative, resolve } from 'node:fs'
// ...
nuxt.hook('builder:watch', async (event, path) => {
+ path = relative(nuxt.options.srcDir, resolve(nuxt.options.srcDir, path))
// ...
})
npx codemod@latest nuxt/4/absolute-watch-pathwindow.__NUXT__ 对象应用完成 hydration 后全局对象 window.__NUXT__ 被移除。
为多应用模式铺路(#21635),并统一通过 useNuxtApp() 访问 Nuxt 数据。
数据仍可访问,改为:
- console.log(window.__NUXT__)
+ console.log(useNuxtApp().payload)
🚦 影响等级:中等
middleware/ 目录下子文件夹中的 index 文件同样会被扫描并注册为中间件。
与 plugins/ 目录一致,支持子文件夹中的 index 文件。
通常无须迁移。如想恢复旧行为,可在钩子中过滤掉 index 中间件:
export default defineNuxtConfig({
hooks: {
'app:resolve' (app) {
app.middleware = app.middleware.filter(mw => !/\/index\.[^/]+$/.test(mw.path))
},
},
})
🚦 影响等级:最低
以前 Nuxt 用 lodash/template 编译文件系统模板(.ejs 语法),并提供了一些模板工具函数(如 serialize、importName、importSources),现在移除这些。
Nuxt v3 引入了支持 getContents() 的虚拟语法,更灵活高效。lodash/template 存在安全问题,且依赖较大。内置使用代码序列化不理想,推荐使用 unjs/knitwork。
我们已提交 PR 修正使用 EJS 语法的模块,也提供以下方案:
getContents()。es-toolkit/compat(lodash template 替代)作为项目依赖:+ import { readFileSync } from 'node:fs'
+ import { template } from 'es-toolkit/compat'
// ...
addTemplate({
fileName: 'appinsights-vue.js'
options: { /* some options */ },
- src: resolver.resolve('./runtime/plugin.ejs'),
+ getContents({ options }) {
+ const contents = readFileSync(resolver.resolve('./runtime/plugin.ejs'), 'utf-8')
+ return template(contents)({ options })
+ },
})
如使用 serialize、importName、importSources 函数,可改用 knitwork:
import { genDynamicImport, genImport, genSafeVariableName } from 'knitwork'
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"\{(.+)\}"(?=,?$)/gm, r => JSON.parse(r).replace(/^\{(.*)\}$/, '$1'))
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')
}
const importName = genSafeVariableName
npx codemod@latest nuxt/4/template-compilation-changes🚦 影响级别:最小
compilerOptions.noUncheckedIndexedAccess 现在默认为 true,而不是 false。
此更改是对之前 3.12 配置更新 的后续改进,我们优化了默认值,主要遵循了 TotalTypeScript 的建议。
有两种方法:
nuxt.config.ts 中覆盖新的默认值:export default defineNuxtConfig({
typescript: {
tsConfig: {
compilerOptions: {
noUncheckedIndexedAccess: false,
},
},
},
})
🚦 影响级别:最小
Nuxt 现在为不同的上下文生成单独的 TypeScript 配置,以提供更好的类型检查体验:
.nuxt/tsconfig.app.json - 对于您的应用代码(Vue 组件、可组合项等).nuxt/tsconfig.server.json - 对于您的服务器端代码(Nitro/server 目录).nuxt/tsconfig.node.json - 对于您的构建时代码(模块,nuxt.config.ts 等).nuxt/tsconfig.shared.json - 对于应用和服务器上下文之间共享的代码(如类型和非环境特定的实用程序).nuxt/tsconfig.json - 旧版配置,保持向后兼容.nuxt/tsconfig.json 的项目将继续像以前一样工作。typescript.nodeTsConfig 选项:你现在可以自定义 Node.js 构建时代码的 TypeScript 配置。此更改带来了以下几个好处:
例如,自动导入在你的 nuxt.config.ts 中不可用(但之前 TypeScript 并不会对此进行标记)。而且虽然 IDE 能识别你 server/ 目录下 tsconfig.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" }
]
}
tsconfig.json 文件(例如 server/tsconfig.json),这些文件如果扩展了 .nuxt/tsconfig.server.json,请删除。- "typecheck": "nuxt prepare && vue-tsc --noEmit"
+ "typecheck": "nuxt prepare && vue-tsc -b --noEmit"
app/ 目录。server/ 目录。shared/ 目录。app/、server/ 或 shared/ 目录之外增强类型将无法与新的项目引用设置一起使用。export default defineNuxtConfig({
typescript: {
// Customize app/server TypeScript config
tsConfig: {
compilerOptions: {
strict: true,
},
},
// Customize build-time TypeScript config
nodeTsConfig: {
compilerOptions: {
strict: true,
},
},
},
})
新配置为选择加入的项目提供了更好的类型安全性和智能感知,同时对现有设置保持完全的向后兼容性。
🚦 影响级别:最小
在 Nuxt 4 中,四个实验性功能不再可配置:
experimental.treeshakeClientOnly 将为 true(自 v3.0 起为默认值)experimental.configSchema 将为 true(自 v3.3 起为默认值)experimental.polyfillVueUseHead 将为 false(自 v3.4 起为默认值)experimental.respectNoSSRHeader 将为 false(自 v3.4 起为默认值)vite.devBundler 不再可配置——默认将使用 vite-node这些选项已经被设置为当前的值有一段时间了,我们没有理由认为它们需要保持可配置。
polyfillVueUseHead is implementable in user-land with this pluginrespectNoSSRHeaderis implementable in user-land with server middlewaregenerate 配置🚦 影响程度:最小
Nuxt 4 不再提供顶层的 generate 配置选项。这包括其所有属性:
generate.exclude - 用于从预渲染中排除路由generate.routes - 用于指定需要预渲染的路由顶层的 generate 配置是 Nuxt 2 的遗留设置。我们已经支持 nitro.prerender 一段时间了,并且它是 Nuxt 3+ 中配置预渲染的首选方式。
将 generate 配置替换为相应的 nitro.prerender 选项:
export default defineNuxtConfig({
- generate: {
- exclude: ['/admin', '/private'],
- routes: ['/sitemap.xml', '/robots.txt']
- }
+ nitro: {
+ prerender: {
+ ignore: ['/admin', '/private'],
+ routes: ['/sitemap.xml', '/robots.txt']
+ }
+ }
})
在下表中,对 Nuxt 的三个版本进行了快速比较:
| Feature / Version | Nuxt 2 | Nuxt Bridge | Nuxt 3+ |
|---|---|---|---|
| Vue | 2 | 2 | 3 |
| Stability | 😊 Stable | 😊 Stable | 😊 Stable |
| Performance | 🏎 Fast | ✈️ Faster | 🚀 Fastest |
| Nitro Engine | ❌ | ✅ | ✅ |
| ESM support | 🌙 Partial | 👍 Better | ✅ |
| TypeScript | ☑️ Opt-in | 🚧 Partial | ✅ |
| Composition API | ❌ | 🚧 Partial | ✅ |
| Options API | ✅ | ✅ | ✅ |
| Components Auto Import | ✅ | ✅ | ✅ |
<script setup> syntax | ❌ | 🚧 Partial | ✅ |
| Auto Imports | ❌ | ✅ | ✅ |
| webpack | 4 | 4 | 5 |
| Vite | ⚠️ Partial | 🚧 Partial | ✅ |
| Nuxt CLI | ❌ Old | ✅ nuxt | ✅ nuxt |
| Static sites | ✅ | ✅ | ✅ |
迁移指南提供了 Nuxt 2 特性与 Nuxt 3+ 特性的逐步对比,以及如何适配现有应用的指导。
如果你希望渐进迁移 Nuxt 2 应用到 Nuxt 3,可以使用 Nuxt Bridge。Nuxt Bridge 是一个兼容层,允许你在 Nuxt 2 中按需启用 Nuxt 3+ 的特性。