首页
/ Nuxt Bridge 的 Legacy Composition API 迁移指南:从 @nuxtjs/composition-api 平滑对齐 Nuxt 3

Nuxt Bridge 的 Legacy Composition API 迁移指南:从 @nuxtjs/composition-api 平滑对齐 Nuxt 3

2026-09-07 23:56:11作者:何将鹤

Nuxt Bridge 是运行在 Nuxt 2 项目上的"前向兼容层"模块,它让你不必一次性重写整个应用,就能逐步体验并迁移到 Nuxt 3 的 API 体系。本文聚焦 Bridge 中最关键的一环——如何从 Nuxt 2 时代的 @vue/composition-api / @nuxtjs/composition-api 迁移到与 Nuxt 3 完全对齐的 Composition API 语法,读完你将掌握依赖清理、bridge.capi 配置、各 legacy composable 的等价替换方案以及自动导入机制,为最终升级到 Nuxt 3/4 扫清最大障碍。

背景:Bridge 与 Composition API 的位置关系

在开始迁移之前,先明确 Nuxt Bridge 的定位。根据 Bridge Overview,Bridge 是一个"前向兼容层",通过安装并启用一个 Nuxt 模块,即可在 Nuxt 2 项目中体验大量 Nuxt 3 特性,从而让项目"几乎准备好"迁移到 Nuxt 3,并允许你分步骤渐进式过渡。

Bridge 文档将升级拆解为多个可独立执行的步骤,其中与本主题直接相关的两步是:

Nuxt Bridge 提供的 Composition API 是专门与 Nuxt 3 对齐的。这意味着:即使你此前已经在用 Composition API,启用 Bridge 时仍有少量额外步骤——因为 Bridge 的实现与旧的 @nuxtjs/composition-api 存在差异,且提供的 composable 集合以 Nuxt 3 为准。有些旧 composable 被移除且暂无替代品,因此迁移过程需要逐一处理。

第一步:移除旧依赖

无论你之前用的是哪种 Composition API 方案,首先都应从 package.jsonnuxt.config 中移除两个旧包:

  • 从依赖中移除 @vue/composition-api
  • 从依赖中移除 @nuxtjs/composition-api(同时从 nuxt.configmodules / buildModules 中移除对应的模块声明)。

移除之后,Composition API 的支持完全交由 Nuxt Bridge 提供,不需要再手动注册任何东西(详见下文)。

仅使用过 @vue/composition-api 的场景:几乎零成本

如果你的代码只依赖 @vue/composition-api(例如手动执行过 Vue.use(VueCompositionApi)),而没有使用 @nuxtjs/composition-api,迁移会非常直接:

1. 删除手动注册 Composition API 的插件。 这个注册工作现在由 Nuxt Bridge 自动完成,你需要把形如下面的代码从插件中删掉:

- import Vue from 'vue'
- import VueCompositionApi from '@vue/composition-api'
-
- Vue.use(VueCompositionApi)

2. 除此之外无需做任何事。 可选操作是:删除代码中 @vue/composition-api 的显式 import,改为依赖 Nuxt Bridge 的自动导入(auto-import)机制——refcomputed 等 Vue API 都会被自动注入。关于自动导入的完整约定可参考 Auto-imports 概念文档

这一"无缝兼容"的设计在当前仓库的核心实现中也能找到佐证:现代 Nuxt 在初始化时会把 vue-demi@vue/composition-api 两个模块名直接别名(alias)到应用内置的 compat 目录(见 packages/nuxt/src/core/nuxt.ts 中的 options.alias['vue-demi']options.alias['@vue/composition-api'])。别名指向的 shim 文件 packages/nuxt/src/app/compat/capi.tsexport * from 'vue',并额外提供 installsetdel 等空实现/兼容函数;packages/nuxt/src/app/compat/vue-demi.ts 则直接声明 isVue3 = true。也就是说,只要代码中保留了 import { ref } from '@vue/composition-api' 这样的写法,shim 也能保证其继续可用——这为从 Bridge 平滑过渡到 Nuxt 3/4 提供了一致的底层保障。

@nuxtjs/composition-api 迁移:差异与例外

与直接使用 @vue/composition-api 不同,@nuxtjs/composition-api 的用户会面临更多改动,因为:

  • Nuxt Bridge 对 Composition API 的实现与 @nuxtjs/composition-api 略有不同
  • Bridge 提供的 composable 以 Nuxt 3 的 composable 集合为基准,部分旧 composable 被移除且暂未提供替代品。

从 buildModules 移除 @nuxtjs/composition-api/module

你不必立即修改全部 import——在移除模块之后,Nuxt Bridge 会自动为目前代码中的大多数 import 提供 "shim"(垫片),从而给你留出迁移到新 composable 的时间。但有以下几个例外,它们已经被彻底移除,必须手动处理:

  • withContext 已移除。 需要迁移到 useNuxtApp / useState 等新 API,参见 Migrate New Composition API 中关于 useContextwithContext 的说明。
  • useStatic 已移除。 目前没有替代品;如果你确实需要它,可以在社区发起 discussion 说明你的使用场景。
  • reqRefreqSsrRef(此前已被标记为 deprecated)已彻底移除。 请按照下文中 ssrRef / shallowSsrRef 的替换指引(见 Migrate New Composition API 的对应小节)进行迁移。

设置 bridge.capi

为了让 Bridge 提供 Nuxt 3 风格的 Composition API(并兼容上述 legacy shim),需要在 nuxt.config 中显式启用 capi 特性(该特性默认开启,此处为显式声明):

import { defineNuxtConfig } from '@nuxt/bridge'

export default defineNuxtConfig({
  bridge: {
    capi: true,
    nitro: false, // 如果已完成向 Nitro 的迁移,请改为 true
  },
})

结合 Bridge Configuration 中的特性开关说明,capi 还支持更细粒度的控制:

// Disable Composition API support entirely
// capi: false,

// ... or just disable legacy Composition API support
// capi: {
//   legacy: false
// },

也就是说,bridge.capi: false 会整体关闭 Composition API 支持;而 bridge.capi: { legacy: false } 只关闭旧版(@nuxtjs/composition-api 风格)的兼容支持,Nuxt 3 风格的新 API 仍然可用。此外 nitro: false 意味着暂用 legacy server;若已完成 Nitro 迁移则设为 true。其余在用的每个 @nuxtjs/composition-api composable,按下面的步骤逐一替换。

逐个 composable 的迁移对照

useFetch$fetchState$fetch 被移除

Bridge 版本不再返回 $fetch$fetchState,需要改用 fetchfetchState

const {
- $fetch,
- $fetchState,
+ fetch,
+ fetchState,
} = useFetch(() => { posts.value = await $fetch('/api/posts') })

注意其中的 useFetch(() => ...) 内部回调依然是旧式写法(在回调内通过副作用给 posts 赋值),这仅用于展示属性名变化;后续若迁移到 Nuxt 3 风格的 useLazyFetch / useLazyAsyncData,应改为由它们返回响应式 data,详见 Migrate New Composition APIuseAsync / useFetch 小节,以及 Data Fetching 中对 useAsyncData / useFetch 的完整讲解。

defineNuxtMiddleware:类型辅助桩函数已移除

defineNuxtMiddleware 只是一个类型辅助的桩函数,现已移除。直接去掉这一层包装:

- import { defineNuxtMiddleware } from '@nuxtjs/composition-api`
- export default defineNuxtMiddleware((ctx) => {})
+ export default (ctx) => {}

如果需要 TypeScript 类型支持,可以改用 @nuxt/types 提供的 Middleware 类型:

import type { Middleware } from '@nuxt/types'

export default <Middleware> function (ctx) { }

defineNuxtPlugin:类型辅助桩函数已移除

defineNuxtMiddleware 同理,defineNuxtPlugin 也是一个被移除的类型辅助桩函数。如果你希望继续使用 Nuxt 2 风格的插件,去掉函数包装即可:

- import { defineNuxtPlugin } from '@nuxtjs/composition-api'
- export default defineNuxtPlugin((ctx, inject) => {})
+ export default (ctx, inject) => {}

需要 TypeScript 支持时,可用 @nuxt/typesPlugin 类型:

import type { Plugin } from '@nuxt/types'

export default <Plugin> function (ctx, inject) {}

::warning 上例虽然有效,但请注意:Nuxt 3 引入了签名略有不同的新 defineNuxtPlugin 函数。若希望一步到位迁移到 Nuxt 3 插件格式(插件只接收单个 nuxtApp 参数),请参考 Creating Plugins 文档 以及 Plugins and Middleware 迁移文档 中的新插件写法(示例中使用 nuxtApp.provide('injected', ...) 提供可在模板/实例中以 $injected 访问的能力)。 ::

useRouteruseRoute:直接替换,但 route 不再是 computed

Bridge 为这两个 composable 提供了直接替代品:useRouteruseRoute(分别对应 useRouteruseRoute)。

二者之间唯一关键差异是:Bridge(及 Nuxt 3)的 useRoute() 不再返回 computed 属性,因此访问路径不再需要 .value

- import { useRouter, useRoute } from '@nuxtjs/composition-api'

  const router = useRouter()
  const route = useRoute()

- console.log(route.value.path)
+ console.log(route.path)

也就是说,如果旧代码中存在大量 route.value.xxx 的访问,需要全局移除 .valueuseRoute() 返回的 route 对象本身已具备响应式属性(例如动态参数、查询参数等都会随导航更新),详情可阅读 useRoute API 文档

向 Nuxt 3 风格 API 迈进:ssrRefuseContext 等的归宿

原文档中明确指出 withContextuseStaticreqRef / reqSsrRef 的替代品需要参考 Migrate New Composition API。这里给出其中几项的关键迁移方向,帮助你一次性规划到位:

  • ssrRef / shallowSsrRefuseState 新 composable 在底层工作方式上非常接近,但你必须显式提供 key(旧实现会自动生成),而且 useState 只能在组件实例或 Nuxt 3 插件(defineNuxtPlugin)上下文中调用,不能在全局/环境上下文中使用,以避免跨请求共享状态:
- import { ssrRef } from '@nuxtjs/composition-api'
- const ref1 = ssrRef('initialData')
+ const ref1 = useState('ref1-key', () => 'initialData')
  // 访问方式保持不变
  console.log(ref1.value)

keyed 状态意味着只要使用相同 key,就能在多个位置访问同一份状态。详见 useState API 文档

  • useContext / useStoreuseNuxtApp 通过 useNuxtApp() 可以访问注入的 helper(如 $axios)与 Vuex store:
- import { useContext } from '@nuxtjs/composition-api'
+ const { $axios } = useNuxtApp()

- import { useStore } from '@nuxtjs/composition-api'
+ const { $store } = useNuxtApp()

另需注意:useNuxtApp() 还暴露一个 nuxt2Context key,包含 Nuxt 2 context 的全部属性,但官方不建议直接使用它(它在 Nuxt 3 中不存在),应尽量寻找其他访问途径。详见 useNuxtApp API 文档

  • onGlobalSetup → 插件 + hook。 可在 defineNuxtPlugin 内通过 nuxtApp.hook('vue:setup', ...) 实现等价逻辑,也可以在 layout 的 setup() 中运行自定义代码。

  • useAsync / useFetchuseLazyAsyncData / useLazyFetch 这些"lazy"版本与旧 composable 一样不会在客户端阻塞路由导航,但 API 完全不同(不要试图在 composable 外部修改其他变量)。且 useLazyFetch 需要先启用 Nitro

  • useMetauseNuxt2MetauseHead 在 Bridge 中可继续用 useNuxt2Meta(以 vue-meta 兼容方式操作 meta,支持响应式更新,但 Nuxt 3 不支持);也可以显式启用 bridge.meta: true 后使用 Nuxt 3 兼容的 useHead(底层基于 @unhead/vue)。注意不要在同一组件内混用 useNuxt2Meta() 与 Options API 的 head(),也不要混用原生 Nuxt 2 的 head() 属性与 useHead

关于自动导入:#imports 与显式禁用

完成上述替换后,若代码中仍保留旧包的显式 import(例如 import { ref } from '@nuxtjs/composition-api'),建议逐步移除,转而依赖 Bridge 的自动导入。与 Nuxt 3/4 一致,Nuxt 也通过 #imports 别名暴露所有自动导入项,供需要时显式引用:

<script setup lang="ts">
import { computed, ref } from '#imports'

const count = ref(1)
const double = computed(() => count.value * 2)
</script>

如果你想彻底关闭 composable 与工具函数的自动导入,可在 nuxt.config 中设置 imports.autoImport: false(此时仍可从 #imports 显式导入):

export default defineNuxtConfig({
  imports: {
    autoImport: false,
  },
})

更完整的自动导入行为说明(包含 imports.scan 等进阶选项)可参考 Auto-imports 概念文档

迁移后的验证与后续升级路径

完成上述改造后,建议按 Bridge Overview 的指引回归验证:确保 dev server 未运行,将 package.json 中的脚本由 nuxt 切换为 nuxt2(例如 dev: "nuxt2"build: "nuxt2 build"start: "nuxt2 start"),先运行一次确认应用行为与之前一致,再继续下一步。

Nuxt Bridge 的整套迁移不需要一次性完成,你可以按需逐项推进。与本主题衔接紧密的后续步骤包括:

需要提醒的是:Bridge 本质上仍运行在 Nuxt 2 之上,它追求与 Nuxt 3 的特性对齐,但也存在若干已知边界(例如 Bridge 文档在 overview 中提示 useAsyncData / useFetch 等 composable 存在使用限制,请以 Bridge OverviewBridge Configuration 中列出的特性开关为准)。因此在动手改造存量代码前,先对照特性开关梳理项目中实际用到的 composable 清单,能显著降低迁移过程中的返工成本。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391