首页
/ @astrojs/vue 集成完全指南:配置选项、渲染机制、Container API 与版本演进

@astrojs/vue 集成完全指南:配置选项、渲染机制、Container API 与版本演进

2026-09-07 22:38:08作者:尤峻淳Whitney

本文以 @astrojs/vue 变更日志 为主线,结合仓库源码(packages/integrations/vue/src)与测试夹具,系统梳理 Astro 官方 Vue 集成的全部可配置项、SSR/客户端水合渲染管线、Container API 使用方式以及各主要版本(0.x→7.x)的破坏性变更与迁移要点。阅读完本文,你将能在 Astro 项目中正确配置与调优 Vue 集成,并能在升级大版本或排查水合/DevTools/多框架共存问题时快速定位方向。

集成是什么:让 Vue 3 组件在 Astro 中 SSR 与水合

@astrojs/vue 是 Astro 官方维护的框架渲染器集成,其职责正如 包内 README 所描述:"enables server-side rendering and client-side hydration for your Vue 3 components"。它不是一个独立 UI 库,而是把 Vue SFC(单文件组件)接入 Astro 的 Islands 架构:服务端把组件渲染成静态 HTML,客户端按需加载并水合为可交互应用。

当前仓库中该包版本为 7.0.2(见 package.json),要求 peerDependenciesastro: ^7.0.0vue: ^3.5.24,运行时 Node 版本为 18.20.8 || ^20.3.0 || >=22.0.0。包内部依赖 @vitejs/plugin-vue(Vue SFC 编译)、@vitejs/plugin-vue-jsx(Vue JSX 支持)、@vue/compiler-sfcvite-plugin-vue-devtools(开发期 DevTools)。

安装与最小配置

在 Astro 项目中使用 Vue,只需在 astro.config.mjs 中引入该集成:

// astro.config.mjs
// @ts-check
import vue from '@astrojs/vue';
import { defineConfig } from 'astro/config';

export default defineConfig({
	// Enable Vue to support Vue components.
	integrations: [vue()],
});

之后即可在 .astro 页面中导入并渲染 .vue 组件,通过 client:loadclient:visible 等指令控制客户端水合时机。集成同时在 exports 中暴露了多个子路径入口(见 package.json):client.js(客户端水合入口)、server.js(SSR 服务端渲染入口)、container-renderer(Container API 渲染器)、editor(语言服务编辑器支持)。

集成配置项详解

vue() 接收一个 Options 对象。从 src/index.ts 的类型定义看,它扩展了 @vitejs/plugin-vueOptions,并追加了三个 Astro 特有选项:

interface Options extends VueOptions {
	jsx?: boolean | VueJsxOptions;
	appEntrypoint?: string;
	devtools?: boolean | Omit<VitePluginVueDevToolsOptions, 'appendTo'>;
}

appEntrypoint:给 Vue 应用注入全局逻辑

appEntrypoint 是 1.2.0 引入、随后在 4.0.x 系列被反复打磨的核心选项。它接受一个根路径相对(或以 . 开头的相对)路径,指向一个默认导出函数、接收 Vue App 实例的模块,使开发者能在应用挂载前统一注入自定义插件(如 i18n):

// astro.config.mjs
import { defineConfig } from 'astro/config';
import vue from '@astrojs/vue';

export default defineConfig({
	integrations: [
		vue({
			appEntrypoint: '/src/pages/_app',
		}),
	],
});
// src/pages/_app.ts
import type { App } from 'vue';
import i18nPlugin from '../plugins/i18n';

export default function setup(app: App) {
	app.use(i18nPlugin, {/* options */});
}

从源码看,该选项的实现机制是:virtualAppEntrypoint() 插件创建虚拟模块 virtual:astro:vue-appsrc/index.ts),在 load 钩子中生成一个 setup(app) 函数——它动态 import 入口文件并调用其 default 导出。client.tsserver.ts 都以 import { setup } from 'virtual:astro:vue-app' 引入并在 app 创建后调用 await setup(app),从而保证水合与 SSR 两侧都执行同一份应用级初始化逻辑

关于 appEntrypoint,变更日志记录了完整的能力演进,可直接据此判断各场景是否受支持:

版本 变更 说明
1.2.0 新增该选项 支持 Vue 自定义插件等全局扩展
4.0.1 无 default 导出不再崩溃 改为忽略入口并打印警告
4.0.2 修复 astro dev 下失效问题 开发模式行为与构建保持一致
4.0.4 简化 appEntrypoint 处理逻辑 代码清理与稳定性提升
4.0.7 支持 async appEntrypoint 默认导出函数可返回 Promise
4.0.8 修复入口引用样式被构建排除 保证入口内引入的全局样式正确注入

源码中的 virtualAppEntrypoint 插件还通过 transform 钩子(对 .vue 文件 prepend import appEntrypoint)确保"Vue 组件直接引用 appEntrypoint"——注释表明这样能让 Astro 把该文件中导入的全局样式关联到应注入的页面;4.0.8 修复的正是相关场景。appEntrypoint 相关的测试夹具位于 test/fixtures/app-entrypoint,另有针对入口 CSS 隔离(app-entrypoint-css)、异步入口(app-entrypoint-async)、无 default 导出(app-entrypoint-no-export-default)、相对/绝对路径(app-entrypoint-relativeapp-entrypoint-src-absolute)等多组夹具,可直接在 test 目录查看其断言。

devtools:开发期启用官方 Vue DevTools

4.2.0 引入 devtools 选项,在开发模式下集成官方 Vue DevTools Vite 插件:

export default defineConfig({
	integrations: [vue({ devtools: true })],
});

4.3.0 将其类型收窄为允许传入 VueDevToolsOptions,实现更多自定义(注意 appendTo 选项不受支持):

export default defineConfig({
	integrations: [
		vue({
			devtools: { launchEditor: 'webstorm' },
		}),
	],
});

源码实现位于 getViteConfiguration()src/index.ts):仅当 command === 'dev' 且开启 devtools 时才动态加载 vite-plugin-vue-devtools;且插件会被 applyToEnvironment 限制为只作用于 environment.name === 'client' 的客户端环境,避免污染 SSR 构建。该选项对 astro build 无效,仅在 astro dev 下生效。7.0.2 进一步修复了"启用 Vue DevTools 且使用 Vite 8 时 dev server 崩溃"的问题——若你正在 Vite 8 / Astro 7 开发期使用 DevTools,应升级到 7.0.2+。

jsx:在 Vue 中使用 JSX/TSX

1.1.0 起支持 Vue JSX。选项值可以是布尔或对象(对象形式会把配置透传给 @vitejs/plugin-vue-jsx):

export default defineConfig({
	integrations: [
		vue({ jsx: true }),
	],
});

源码中,当 options.jsx 为真时,集成会额外注册一个名为 @astrojs/vue (jsx) 的渲染器(getJsxRenderer()src/index.ts),使 .jsx/.tsx 文件按 Vue JSX 规则编译。

一个易踩的坑:当项目同时启用 Vue JSX 与其他 JSX 系框架(React、Preact、Solid)时,若不显式设置 include/exclude,扩展了 VueOptions 的这两个字段也随插件透传,代码会以 .jsx/.tsx 文件归属为依据;5.0.5 起集成会在 astro:config:done 钩子中检测该冲突并打印告警(src/index.ts),提示你通过 includeexclude 明确文件归属。4.0.11 则移除了无用的 jsxTransformOptionsjsxImportSource 渲染器配置项,说明现代实现已不再需要这两项。

Vue 编译器选项与其他透传能力

由于 Options 直接继承 @vitejs/plugin-vue 的 Options,0.1.2 就支持的"自定义 Vue 编译器选项"、template 相关配置等均可直接传入。集成内部强制设置了 template.transformAssetUrls: falsesrc/index.ts),把资源 URL 处理交给 Astro 资产管线而非 Vite 插件,这也与 4.0.9 修复的"Vue 组件内引用 public 图片不生效"问题相呼应——在该模式下,public 目录图片与经 Astro 处理的资源都能在 SFC 模板中正确解析。

此外,集成在 astro:config:setup 时通过 configEnvironmentPlugin()src/index.ts)对 client/ssr/prerender 环境做 optimizeDeps 与依赖外置调优:客户端环境预打包 vue@astrojs/vue/client.js,SSR 环境把 vuetifyvueperslidesprimevue 标记为 resolve.external。这三者分别对应 1.2.1(自动 vuetify noExternal)、1.0.1(vueperslides)、1.2.2(primevue 作为外部 Vue 包)三处历史修复。4.0.10 则从 ssr.external 配置中移除了已废弃的 @vue/server-renderer 包。

渲染机制源码解析:SSR、水合与插槽

服务端渲染(server.ts)

src/server.ts 是服务端渲染入口。核心流程:

  1. 通过 check() 判断组件是否具备 ssrRender__ssrInlineRender(即能否服务端渲染);
  2. renderToStaticMarkup() 中把 Astro 传来的 slot 字符串包装为 StaticHtml VNode,创建 createSSRApp({ render: () => h(Component, props, slots) })
  3. 关键细节:app.config.idPrefix = prefix,其中 prefix 来自 src/context.tsincrementId()——它以 SSRResult 为键维护自增索引,生成 s0s1……形式的唯一前缀,并通过返回的 attrs.prefix 写进最终 HTML 的宿主元素属性。

这个 id 前缀机制正是 4.5.2 修复"useId()(Vue 3.5 引入)生成的 ID 在多个 island 之间不唯一" 的实现基础:每个 island 拥有独立递增前缀,useId 派生的 DOM id 因而全局不冲突。

客户端水合(client.ts)

src/client.ts 是客户端入口。几个值得注意的设计:

  • ssr 属性守卫:宿主元素若缺少 ssr 属性则直接返回(0.1.5 起的行为),避免重复水合;
  • createSSRApp vs createAppclient !== 'only'(即 client:load 类指令)时用 createSSRApp 执行水合,client:only 时则用 createApp 全新挂载;
  • 视图过渡持久化:模块级 appMap(WeakMap)记录了每个元素上已初始化的 app 实例。当 client:only 组件在视图过渡中被重渲染时,若实例已存在则直接更新 props/slots 并调用 $forceUpdate(),而非重建应用——这正是 4.5.1 修复"view transition 持久化时 Vue island 丢失状态" 的实现;app.config.idPrefix 读取宿主元素上的 prefix 属性,与 SSR 侧保持一致;
  • 自动卸载:挂载后注册一次性 astro:unmount 监听并调用 app.unmount()(3.0.0 引入);
  • 异步组件:当 Component.setup 是 async 函数时(对应 issue #6549),渲染内容会被包进 <Suspense> 以支持异步 setup。

插槽与静态 HTML(static-html.ts)

Astro 传给框架组件的 children/插槽是 HTML 字符串,而 Vue 需要 VNode。因此 src/static-html.ts 定义了 StaticHtml 包装组件,等价于 <div v-html="value">:它按 hydrate 布尔值选择渲染 <astro-slot><astro-static-slot> 标签。

astro-static-slot 机制对应 2.2.0 引入的 supportsAstroStaticSlot 标志——服务端渲染器声明它、以 astro-static-slot 占位未被水合的静态插槽,供 Astro 随后移除,从而支持"SSR-only 组件嵌套 client:* 组件"的组合(<Component><div><Component client:load>...)。2.2.1 修复了该机制导致的 astro-static-slot 水合不匹配错误。另外 3.0.3 修复"Astro slot 名被当作属性传给组件"——现在具名插槽只通过 slot 通道传递,不再污染 props;0.2.0 起则已支持从 .astro 向 Vue 组件传具名插槽。

Vue 3.3 泛型与编辑器支持

编译与编辑器层面,3.0.4 为 Vue 非 setup script 块与 Vue 3.3 泛型增加了编辑器支持;包的 editor 子路径入口(src/editor.cts)与类型声明文件 vue-shims.d.tsenv.d.ts 服务于语言服务,仓库中也存在 check.test.tstoTsx.test.ts 等编辑器相关测试。

在测试中使用 Container API 渲染 Vue 组件

变更日志用相当篇幅记录了 Container API(实验性)对 Vue 组件的支持演进,这也是在 Vitest 等单元测试中渲染 .vue 组件的官方路径:

从包根导入 getContainerRenderer(4.4.0 → 7.0.0 弃用)

4.4.0 起集成暴露 getContainerRenderer,配合 loadRenderers 即可在测试中渲染含框架组件的页面:

import { experimental_AstroContainer as AstroContainer } from 'astro/container';
import ReactWrapper from '../src/components/ReactWrapper.astro';
import { loadRenderers } from 'astro:container';
import { getContainerRenderer } from '@astrojs/react';

test('ReactWrapper with react renderer', async () => {
	const renderers = await loadRenderers([getContainerRenderer()]);
	const container = await AstroContainer.create({ renderers });
	const result = await container.renderToString(ReactWrapper);

	expect(result).toContain('Counter');
	expect(result).toContain('Count: <!-- -->5');
});

5.1.3 增强:getContainerRenderer() 返回的渲染器对象加入了客户端水合入口,组件可以真正具备客户端交互能力——此前用户必须手动调用 container.addClientRenderer() 注册对应入口。仓库中的 examples/container-with-vitest 提供了完整可运行示例,其 test 目录下的测试正是该 API 的实际用法参考。

7.0.0 破坏性变更getContainerRenderer() 的导入入口被迁移到独立的 container-renderer 子路径。原因是此前从包根导入会令打包器在"仅使用 Container API"时仍尝试打包根模块的其他无关导出。迁移方式:

- import { getContainerRenderer } from '@astrojs/react';
+ import { getContainerRenderer } from '@astrojs/react/container-renderer';

从根路径导入仍然可用,但已弃用并打印警告日志。仓库源码同步验证了这一约定:根入口 src/index.ts 中的 getContainerRenderer() 被标注 @deprecatedconsole.warn 引导用户改从 container-renderer 导入,而新入口 src/container-renderer.ts 单纯返回 { name, clientEntrypoint: '@astrojs/vue/client.js', serverEntrypoint: '@astrojs/vue/server.js' }package.jsonexports 中新增了 "./container-renderer": "./dist/container-renderer.js"。React、Preact、Svelte、SolidJS、Vue、MDX 六种集成的迁移方式一致。

按需页面手动注册渲染器 addServerRenderer(4.5.0)

4.5.0 为 Container API 新增 addServerRenderer,适用于按需(on-demand)渲染场景,例如在 API 路由中按需拼接组件 HTML:

import type { APIRoute } from 'astro';
import { experimental_AstroContainer } from 'astro/container';
import reactRenderer from '@astrojs/react/server.js';
import vueRenderer from '@astrojs/vue/server.js';
import ReactComponent from '../components/button.jsx';
import VueComponent from '../components/button.vue';

// MDX runtime is contained inside the Astro core
import mdxRenderer from 'astro/jsx/server.js';

// In case you need to import a custom renderer
import customRenderer from '../renderers/customRenderer.js';

export const GET: APIRoute = async (ctx) => {
	const container = await experimental_AstroContainer.create();
	container.addServerRenderer({ renderer: reactRenderer });
	container.addServerRenderer({ renderer: vueRenderer });
	container.addServerRenderer({ renderer: customRenderer });
	// You can pass a custom name too
	container.addServerRenderer({
		name: 'customRenderer',
		renderer: customRenderer,
	});
	const vueComponent = await container.renderToString(VueComponent);
	return await container.renderToResponse(Component);
};

注意代码中的 server.js 即上述 SSR 渲染器入口(src/server.ts),renderToString/renderToResponse 是 Container 提供的高层 API。

版本兼容矩阵与升级路线

该集成从 v1.0.0 起就与 Astro 大版本严格绑定:2.0.0 起将 astro 设为 peerDependency,此后每个主版本都对齐 Astro 主版本并同步升级底层 Vite。下表依据变更日志整理:

集成版本 对应 Astro 底层 Vite 关键变更
0.x astro@1 beta/stable Vite 3(0.5.0) 初版、稳定化
1.0.0–1.2.x astro@1 稳定、appEntrypoint、Vue JSX
2.0.0–2.2.1 astro@2 Vite 4 astro 设为 peerDependency;移除 Node 14
3.0.0–3.0.4 astro@3 移除 Node 16;astro:unmount 自动卸载
4.0.0–4.5.3 astro@4 Vite 5 DevTools 选项、Container API、async 入口
5.0.0–5.1.4 astro@5 Vite 6 支持任意 HTML 属性;最低 Node 18.20.8
6.0.0–6.0.1 astro@6 Vite 7(含 plugin-vue 6) 修复 Cloudflare 运行时错误
7.0.0–7.0.2 astro@7 Vite 8 container-renderer 新入口;修复 DevTools 崩溃

大版本破坏性变更与行动清单

  • 升级到 7.0.0:① 若用 Container API,把 getContainerRenderer 导入改为 <集成包名>/container-renderer(见上文迁移 diff),根导入仅保留向后兼容并打警告;② 底层升级为 Vite 8,需同步检查项目内直接依赖 Vite 相关插件/配置的兼容性。
  • 升级到 6.0.0:Astro 6 将开发服务器/生产打包器升级到 Vite 7;集成侧同步把 @vitejs/plugin-vue 升级到 v6、@vitejs/plugin-vue-jsx 到 v5、vite-plugin-vue-devtools 到 v8,日志明确"用户无需任何改动"。另有两点行为增强:支持在 Vue 组件上透传任意 HTML 属性(5.1.4 与 6.0.0 均有提交),以及修复与 Cloudflare adapter 联用时的运行时错误(6.0.0)。
  • 升级到 5.0.0 / 5.1.0:peerDependency 放开到支持 Astro 5,Vite 升到 v6;Node 最低版本提升到 18.20.8(Node 18 已 EOL,日志建议尽快迁移到 Node 22)。特别提醒 Cloudflare Pages 用户:其默认构建镜像使用 Node 18.17.1,已不被支持,需要覆盖默认 Node 版本到 22;Cloudflare Workers 默认 Node 22,不受影响。5.0.0 还移除了 Node 21 支持。此外 5.1.2/5.1.1/5.0.13/5.0.10/5.0.9/5.0.8/5.0.6 等多次升级 Vite 均为修复 CVE 与稳定性,属于建议同步的低风险升级。
  • 升级到 4.0.0 / 4.1.0 / 3.0.0 / 2.0.0:分别引入 Vite 5、收紧 Node 支持策略(低于 18.17.1 的 18、低于 20.0.3 的 20 及整个 19 弃用)、移除 Node 16(最低 18.14.1)、移除 Node 14 并将 astro 改为 peerDependency(最低 16.12.0)。
  • peerDependencies 修正:7.0.1 修复了 peerDependencies 字段中使用了错误依赖项的问题;4.5.3 解决了 Yarn PnP 等严格包管理器的 Vite peer 依赖解析;5.0.2 同样修复了 vue 集成的 Vite peer 依赖。若使用 Yarn PnP,请确保集成版本在 4.5.3+。

需要留意的已知问题修复(Patch 速查)

变更日志中部分 Patch 对日常使用有直接价值:

  • 视图过渡/客户端交互:4.5.2 修复 useId()(Vue 3.5)生成的 ID 在 island 间不唯一;同时修复客户端过渡期间的 Reference Error。4.5.1 修复 view transition 持久化下 island 状态丢失。3.0.2 修复仅更新 <script> 标签时 Vue 组件 HMR 失效。
  • 水合与插槽:2.2.1 修复 astro-static-slot 水合不匹配;4.0.8 修复 Vue 组件的 class 属性水合报错。
  • 构建/类型:5.0.7 修复编译器无法被自动解析(会尝试从 vue/compiler-sfc 显式导入,见 src/index.ts);5.0.12/5.0.11 修复并强化了 SSR renderer 的类型安全;5.0.4 修复 server.mjs 的类型推断;4.0.9 修复组件内引用 public 图片。
  • 样式:4.0.8 顺带修复了 appEntrypoint 引用的样式被构建排除的问题。
  • 运行时:6.0.0(alpha.1 起)修复 Cloudflare adapter 下的运行时错误;1.0.2 修复 script setup 与其他 renderer 并用的问题;2.1.1 支持模板 setup 中顶层 await 语法糖。

仓库内可继续阅读的资料

若想深入验证本文结论,可在当前仓库按以下路径查阅:

结语

从 0.x 到 7.x,@astrojs/vue 的演进清晰地映射出 Astro 生态的几次结构性升级:Vite 版本跟随(3→8)、astro 转为 peerDependency、renderer 入口拆分(container-renderer)、Islands 插槽协议标准化(astroStaticSlot)以及应用级配置(appEntrypoint/devtools)的补齐。对开发者而言,掌握这张版本与功能对照表,并在升级前核对 Node/Vite/peerDependency 三项约束,即可在绝大多数场景中无痛跟随 Astro 的主版本迭代。

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

项目优选

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