通过 100+ 条技巧学习 Nuxt!

升级指南

了解如何升级到最新的 Nuxt 版本。

升级 Nuxt

最新版本

要将 Nuxt 升级到最新版本,请使用 nuxi upgrade 命令。

npx nuxi upgrade

Nightly Release Channel

要使用最新的 Nuxt 构建版本并在发布前测试功能,请阅读nightly release channel 指南。

nightly release channel latest 标签目前正在跟踪 Nuxt v4 分支,这意味着它现在特别容易出现重大更改 - 请务必小心!您可以使用 "nuxt": "npm:nuxt-nightly@3x" 选择加入 3.x 分支 nightly 版本。

测试 Nuxt 4

Nuxt 4 的发布日期待定。这取决于在 Nitro 主要版本发布后是否有足够的时间在社区中进行充分测试。您可以在此 PR 中关注 Nitro 版本发布的进度。

在发布之前,可以从 Nuxt 3.12+ 版本开始测试 Nuxt 4 的许多重大更改。

观看 Alexander Lichter 的视频,了解如何选择加入 Nuxt 4 的重大更改。

选择加入 Nuxt 4

首先,将 Nuxt 升级到最新版本

然后,您可以设置您的 compatibilityVersion 以匹配 Nuxt 4 的行为

目前,您需要在选择加入 Nuxt 4 行为的每个层中定义兼容性版本。Nuxt 4 发布后将不再需要这样做。
nuxt.config.ts
export default 
defineNuxtConfig
({
future
: {
compatibilityVersion
: 4,
}, // To re-enable _all_ Nuxt v3 behavior, set the following options: // srcDir: '.', // dir: { // app: 'app' // }, // experimental: { // scanPageMeta: 'after-resolve', // sharedPrerenderData: false, // compileTemplate: true, // resetAsyncDataToUndefined: true, // templateUtils: true, // relativeWatchPaths: true, // normalizeComponentNames: false, // spaLoadingTemplateLocation: 'within', // defaults: { // useAsyncData: { // deep: true // } // } // }, // features: { // inlineStyles: true // }, // unhead: { // renderSSRHeadOptions: { // omitLineBreaks: false // } // } })

当您将 compatibilityVersion 设置为 4 时,整个 Nuxt 配置的默认值将更改为选择加入 Nuxt v4 行为,但您可以在测试时细粒度地重新启用 Nuxt v3 行为,遵循上面注释掉的行。如果这样做,请提交 issue,以便我们可以在 Nuxt 或生态系统中解决这些问题。

迁移到 Nuxt 4

重大或重要更改将在此处注明,并附带向后/向前兼容的迁移步骤。

本节在最终发布之前可能会发生更改,因此如果您使用 compatibilityVersion: 4 测试 Nuxt 4,请定期查看此处。

使用 Codemod 进行迁移

为了方便升级过程,我们与 Codemod 团队合作,通过一些开源 codemod 自动化许多迁移步骤。

如果您遇到任何问题,请使用 npx codemod feedback 向 Codemod 团队报告 🙏

有关 Nuxt 4 codemod 的完整列表、每个 codemod 的详细信息、其来源以及运行它们的各种方法,请访问 Codemod Registry

您可以使用以下 codemod recipe 运行本指南中提到的所有 codemod

npx codemod@latest nuxt/4/migration-recipe

此命令将按顺序执行所有 codemod,您可以选择取消选择任何您不想运行的 codemod。每个 codemod 也列在下面,以及其各自的更改,并且可以独立执行。

新的目录结构

🚦 影响级别:重大

Nuxt 现在默认为新的目录结构,具有向后兼容性(因此,如果 Nuxt 检测到您正在使用旧结构,例如带有顶层 pages/ 目录,则此新结构将不适用)。

👉 查看完整 RFC

发生了什么变化
  • 新的 Nuxt 默认 srcDir 默认为 app/,并且大多数内容都从那里解析。
  • serverDir 现在默认为 <rootDir>/server 而不是 <srcDir>/server
  • layers/modules/public/ 默认相对于 <rootDir> 解析
  • 如果使用 Nuxt Content v2.13+content/ 相对于 <rootDir> 解析
  • 添加了一个新的 dir.app,它是我们查找 router.options.tsspa-loading-template.html 的目录 - 这默认为 <srcDir>/
v4 文件夹结构的示例。
.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/
server/
  api/
  middleware/
  plugins/
  routes/
  utils/
nuxt.config.ts

👉 有关更多详细信息,请参阅实现此更改的 PR

更改原因
  1. 性能 - 将所有代码放在 repo 的根目录会导致 .git/node_modules/ 文件夹被 FS 监视器扫描/包含,这会显着延迟非 Mac OS 上的启动。
  2. IDE 类型安全 - server/ 和应用程序的其余部分在两个完全不同的上下文中使用不同的全局导入运行,确保 server/ 不在与应用程序其余部分相同的文件夹中是确保您在 IDE 中获得良好自动完成功能的第一大步。
迁移步骤
  1. 创建一个名为 app/ 的新目录。
  2. 将您的 assets/components/composables/layouts/middleware/pages/plugins/utils/ 文件夹以及 app.vueerror.vueapp.config.ts 移动到它下面。如果您有 app/router-options.tsapp/spa-loading-template.html,则这些路径保持不变。
  3. 确保您的 nuxt.config.tscontent/layers/modules/public/server/ 文件夹保留在 app/ 文件夹之外,位于项目的根目录中。
  4. 记住更新任何第三方配置文件以使用新的目录结构,例如您的 tailwindcsseslint 配置(如果需要 - @nuxtjs/tailwindcss 应该自动正确配置 tailwindcss)。
您可以通过运行 npx codemod@latest nuxt/4/file-structure 来自动化此迁移

但是,迁移是非必需的。如果您希望保留当前的文件夹结构,Nuxt 应该会自动检测到它。(如果未检测到,请提出 issue。)一个例外是,如果您已经有一个自定义 srcDir。在这种情况下,您应该意识到您的 modules/public/server/ 文件夹将从您的 rootDir 而不是从您的自定义 srcDir 解析。如果需要,您可以配置 dir.modulesdir.publicserverDir 来覆盖此设置。

您还可以使用以下配置强制使用 v3 文件夹结构

nuxt.config.ts
export default defineNuxtConfig({
  // This reverts the new srcDir default from `app` back to your root directory
  srcDir: '.',
  // This specifies the directory prefix for `app/router.options.ts` and `app/spa-loading-template.html`
  dir: {
    app: 'app'
  }
})

路由元数据去重

🚦 影响级别:最小

发生了什么变化

可以使用 definePageMeta 设置一些路由元数据,例如 namepath 等。以前,这些在路由和路由元数据上都可用(例如,route.nameroute.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> 中使用更新后的名称。

或者,目前,您可以使用以下方式禁用此行为

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
normalizeComponentNames
: false
} })

Unhead v2

🚦 影响级别:最小

发生了什么变化

用于生成 <head> 标签的 Unhead 已更新到版本 2。虽然大部分兼容,但它包含一些针对较低级别 API 的重大更改。

  • 已删除的 props:vmidhidchildrenbody
  • 不再支持 Promise 输入。
  • 标签现在默认使用 Capo.js 排序。
迁移步骤

以上更改应该对您的应用程序影响最小。

如果您遇到问题,您应该验证

  • 您没有使用任何已删除的 props。
useHead({
  meta: [{ 
    name: 'description', 
    // meta tags don't need a vmid, or a key    
-   vmid: 'description' 
-   hid: 'description'
  }]
})
import { TemplateParamsPlugin, AliasSortingPlugin } from '@unhead/vue/plugins'

export default defineNuxtPlugin({
  setup() {
    const unhead = injectHead()
    unhead.use(TemplateParamsPlugin)
    unhead.use(AliasSortingPlugin)
  }
})

虽然不是必需的,但建议将任何从 @unhead/vue 的导入更新为 #importsnuxt/app

-import { useHead } from '@unhead/vue'
+import { useHead } from '#imports'

如果您仍然遇到问题,您可以通过启用 head.legacy 配置来恢复到 v1 行为。

export default defineNuxtConfig({
  unhead: {
    legacy: true,
  }
})

SPA 加载屏幕的新 DOM 位置

🚦 影响级别:最小

发生了什么变化

当渲染仅客户端页面(使用 ssr: false)时,我们可选地在 Nuxt 应用程序根目录中渲染加载屏幕(来自 app/spa-loading-template.html

<div id="__nuxt">
  <!-- spa loading template -->
</div>

现在,我们默认将模板与 Nuxt 应用程序根目录一起渲染

<div id="__nuxt"></div>
<!-- spa loading template -->
更改原因

这允许 spa 加载模板保留在 DOM 中,直到 Vue 应用程序 suspense 解析,从而防止出现白屏闪烁。

迁移步骤

如果您使用 CSS 或 document.queryElement 定位 spa 加载模板,您将需要更新您的选择器。为此,您可以使用新的 app.spaLoaderTagapp.spaLoaderAttrs 配置选项。

或者,您可以使用以下方式恢复到之前的行为

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
spaLoadingTemplateLocation
: 'within',
} })

更细粒度的内联样式

🚦 影响级别:中等

Nuxt 现在将仅内联 Vue 组件的样式,而不是全局 CSS。

发生了什么变化

以前,Nuxt 会内联所有 CSS,包括全局样式,并删除 <link> 元素以分离 CSS 文件。现在,Nuxt 将仅对 Vue 组件执行此操作(以前这会生成单独的 CSS 块)。我们认为这是减少单独网络请求(就像以前一样,初始加载时不会为每个页面或每个组件的单个 .css 文件发出单独的请求)以及允许缓存单个全局 CSS 文件并减小初始请求的文档下载大小之间的更好平衡。

迁移步骤

此功能是完全可配置的,您可以通过将 inlineStyles: true 设置为内联全局 CSS 以及每个组件的 CSS 来恢复到之前的行为。

nuxt.config.ts
export default 
defineNuxtConfig
({
features
: {
inlineStyles
: true
} })

解析后扫描页面元数据

🚦 影响级别:最小

发生了什么变化

我们现在调用 pages:extend 钩子之后而不是之前扫描页面元数据(在 definePageMeta 中定义)。

更改原因

这是为了允许扫描用户想要在 pages:extend 中添加的页面的元数据。我们仍然提供机会在新 pages:resolved 钩子中更改或覆盖页面元数据。

迁移步骤

如果您想覆盖页面元数据,请在 pages:resolved 而不是在 pages:extend 中执行此操作。

  export default defineNuxtConfig({
    hooks: {
-     'pages:extend'(pages) {
+     'pages:resolved'(pages) {
        const myPage = pages.find(page => page.path === '/')
        myPage.meta ||= {}
        myPage.meta.layout = 'overridden-layout'
      }
    }
  })

或者,您可以使用以下方式恢复到之前的行为

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
scanPageMeta
: true
} })

共享预渲染数据

🚦 影响级别:中等

发生了什么变化

我们启用了一个以前的实验性功能,以跨不同页面共享来自 useAsyncDatauseFetch 调用的数据。请参阅 原始 PR

更改原因

此功能会自动在预渲染的页面之间共享 payload 数据。当预渲染使用 useAsyncDatauseFetch 并在不同页面中获取相同数据的站点时,这可以显着提高性能。

例如,如果您的站点需要为每个页面进行 useFetch 调用(例如,获取菜单的导航数据或来自 CMS 的站点设置),则此数据仅在预渲染使用它的第一个页面时获取一次,然后缓存以供预渲染其他页面时使用。

迁移步骤

确保您的数据的任何唯一 key 始终可以解析为相同的数据。例如,如果您使用 useAsyncData 来获取与特定页面相关的数据,则应提供唯一匹配该数据的 key。(useFetch 应该为您自动执行此操作。)

app/pages/test/[slug].vue
// This would be unsafe in a dynamic page (e.g. `[slug].vue`) because the route slug makes a difference
// to the data fetched, but Nuxt can't know that because it's not reflected in the key.
const route = useRoute()
const { data } = await useAsyncData(async () => {
  return await $fetch(`/api/my-page/${route.params.slug}`)
})
// Instead, you should use a key that uniquely identifies the data fetched.
const { data } = await useAsyncData(route.params.slug, async () => {
  return await $fetch(`/api/my-page/${route.params.slug}`)
})

或者,您可以使用以下方式禁用此功能

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
sharedPrerenderData
: false
} })

useAsyncDatauseFetch 中的默认 dataerror

🚦 影响级别:最小

发生了什么变化

useAsyncData 返回的 dataerror 对象现在将默认为 undefined

更改原因

以前,data 初始化为 null,但在 clearNuxtData 中重置为 undefinederror 初始化为 null。此更改是为了提高一致性。

迁移步骤

如果您正在检查 data.valueerror.value 是否为 null,则可以更新这些检查以检查 undefined

您可以通过运行 npx codemod@latest nuxt/4/default-data-error-value 来自动化此步骤

如果您遇到任何问题,可以使用以下方式恢复到之前的行为

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
defaults
: {
useAsyncData
: {
value
: 'null',
errorValue
: 'null'
} } } })

如果您这样做,请报告 issue,因为我们不打算将其保留为可配置项。

删除调用 useAsyncDatauseFetch 中的 refresh 时已弃用的 dedupe 选项的 boolean

🚦 影响级别:最小

发生了什么变化

以前可以将 dedupe: boolean 传递给 refresh。这些是 cancel (true) 和 defer (false) 的别名。

app.vue
const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt 3!' }))

async function refreshData () {
  await refresh({ dedupe: true })
}
更改原因

为了更清晰,这些别名已被删除。

当将 dedupe 作为选项添加到 useAsyncData 时,问题出现了,并且我们删除了 boolean 值,因为它们最终是相反的

refresh({ dedupe: false }) 表示“不要取消现有请求而支持这个新请求”。但是在 useAsyncData 的选项中传递 dedupe: true 意味着“如果存在现有挂起的请求,则不要发出任何新请求。”(请参阅 PR。)

迁移步骤

迁移应该很简单

  const { refresh } = await useAsyncData(async () => ({ message: 'Hello, Nuxt 3!' }))
  
  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 来自动化此步骤

useAsyncDatauseFetch 中清除 data 时尊重默认值

🚦 影响级别:最小

发生了什么变化

如果您为 useAsyncData 提供了自定义 default 值,则在调用 clearclearNuxtData 时将使用此值,并且它将重置为其默认值,而不是简单地取消设置。

更改原因

通常,用户设置适当的空值,例如空数组,以避免在迭代时需要检查 null/undefined。在重置/清除数据时应尊重这一点。

迁移步骤

如果您遇到任何问题,目前可以使用以下方式恢复到之前的行为

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
resetAsyncDataToUndefined
: true,
} })

如果您这样做,请报告 issue,因为我们不打算将其保留为可配置项。

useAsyncDatauseFetch 中的浅层数据响应性

🚦 影响级别:最小

useAsyncDatauseFetchuseLazyAsyncDatauseLazyFetch 返回的 data 对象现在是 shallowRef 而不是 ref

发生了什么变化

当获取新数据时,依赖于 data 的任何内容仍然是响应式的,因为整个对象都被替换了。但是,如果您的代码更改了该数据结构内部的属性,则这不会触发应用程序中的任何响应性。

更改原因

这为深度嵌套的对象和数组带来了显着的性能提升,因为 Vue 不需要监视每个属性/数组的修改。在大多数情况下,data 也应该是不可变的。

迁移步骤

在大多数情况下,不需要迁移步骤,但如果您依赖于数据对象的响应性,那么您有两个选择

  1. 您可以基于每个 composable 细粒度地选择加入深度响应性
    - const { data } = useFetch('/api/test')
    + const { data } = useFetch('/api/test', { deep: true })
    
  2. 您可以更改项目范围内的默认行为(不建议)
    nuxt.config.ts
    export default 
    defineNuxtConfig
    ({
    experimental
    : {
    defaults
    : {
    useAsyncData
    : {
    deep
    : true
    } } } })
如果需要,您可以通过运行 npx codemod@latest nuxt/4/shallow-function-reactivity 来自动化此步骤

builder:watch 中的绝对监视路径

🚦 影响级别:最小

发生了什么变化

Nuxt 的 builder:watch 钩子现在发出的是绝对路径,而不是相对于项目 srcDir 的相对路径。

更改原因

这允许我们支持监听 srcDir 之外的路径,并为 layers 和其他更复杂的模式提供更好的支持。

迁移步骤

我们已经主动迁移了我们所知的、使用此钩子的公共 Nuxt 模块。请参阅 issue #25339

但是,如果您是模块作者,使用 builder:watch 钩子并希望保持向前/向后兼容,您可以使用以下代码来确保您的代码在 Nuxt v3 和 Nuxt v4 中都能正常工作

+ 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-path 来自动化此步骤

移除 window.__NUXT__ 对象

发生了什么变化

我们正在应用完成 hydration 后移除全局 window.__NUXT__ 对象。

更改原因

这为多应用模式打开了大门 (#21635),并使我们能够专注于访问 Nuxt 应用数据的单一方式 - useNuxtApp()

迁移步骤

数据仍然可用,但可以使用 useNuxtApp().payload 访问

- console.log(window.__NUXT__)
+ console.log(useNuxtApp().payload)

目录索引扫描

🚦 影响级别:中等

发生了什么变化

您的 middleware/ 文件夹中的子文件夹也会被扫描以查找 index 文件,并且这些文件现在也会在您的项目中注册为中间件。

更改原因

Nuxt 会自动扫描许多文件夹,包括 middleware/plugins/

您的 plugins/ 文件夹中的子文件夹也会被扫描以查找 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 已经出现了一系列安全问题。这些问题实际上并不适用于 Nuxt 项目,因为它是在构建时而不是运行时使用,并且由受信任的代码使用。但是,它们仍然出现在安全审计中。此外,lodash 是一个庞大的依赖项,并且大多数项目都不使用它。

最后,直接在 Nuxt 中提供代码序列化函数并不理想。相反,我们维护像 unjs/knitwork 这样的项目,这些项目可以作为您项目的依赖项,并且可以在其中直接报告/解决安全问题,而无需升级 Nuxt 本身。

迁移步骤

我们已经提出了 PR 来更新使用 EJS 语法的模块,但如果您需要自己执行此操作,您有三种向前/向后兼容的替代方案

  • 将您的字符串插值逻辑直接移动到 getContents() 中。
  • 使用自定义函数来处理替换,例如在 https://github.com/nuxt-modules/color-mode/pull/240 中。
  • 使用 es-toolkit/compat (lodash template 的直接替代品),作为项目的依赖项,而不是 Nuxt 的依赖项
+ 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 来自动化此步骤

移除实验性功能

🚦 影响级别:最小

发生了什么变化

在 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 可以在用户空间中使用 此插件 实现
  • respectNoSSRHeader 可以在用户空间中使用 服务器中间件 实现

Nuxt 2 vs Nuxt 3+

下表快速比较了 3 个版本的 Nuxt

功能 / 版本Nuxt 2Nuxt BridgeNuxt 3+
Vue223
稳定性😊 稳定😊 稳定😊 稳定
性能🏎 快速✈️ 更快🚀 最快
Nitro 引擎
ESM 支持🌙 部分👍 更好
TypeScript☑️ 可选🚧 部分
Composition API🚧 部分
Options API
组件自动导入
<script setup> 语法🚧 部分
自动导入
webpack445
Vite⚠️ 部分🚧 部分
Nuxi CLI❌ 旧版✅ nuxi✅ nuxi
静态站点

Nuxt 2 到 Nuxt 3+

迁移指南提供了 Nuxt 2 功能与 Nuxt 3+ 功能的逐步比较,以及调整当前应用程序的指导。

查看 从 Nuxt 2 迁移到 Nuxt 3 的指南

Nuxt 2 到 Nuxt Bridge

如果您希望逐步将 Nuxt 2 应用程序迁移到 Nuxt 3,可以使用 Nuxt Bridge。Nuxt Bridge 是一个兼容层,允许您在 Nuxt 2 中使用 Nuxt 3+ 功能,并具有可选机制。

从 Nuxt 2 迁移到 Nuxt Bridge