首页
/ Astro + Vue 集成实战:framework-vue 示例项目全流程解析

Astro + Vue 集成实战:framework-vue 示例项目全流程解析

2026-09-04 09:32:08作者:温艾琴Wonderful

本篇以 Astro 官方示例项目 framework-vue 为主体,完整拆解"在 Astro 中渲染并水合 Vue 组件"的标准做法:从项目初始化命令、@astrojs/vue 集成配置,到 Vue 单文件组件(SFC)编写、client:visible 客户端指令挂载,再到 @astrojs/vue 集成包的 Vite 层实现原理。读完后你能独立搭建一个 Astro + Vue 混合渲染站点,并理解指令水合背后的调用链。

项目定位与快速启动

示例项目的 README 明确说明了它的用途:"This example showcases Astro working with Vue"——即演示 Astro 与 Vue 3 协同工作的最小可用形态。官方提供的一键初始化命令为:

npm create astro@latest -- --template framework-vue

示例目录结构非常精简,只包含一个页面和一个 Vue 组件:

examples/framework-vue/
├── public/                  # 静态资源(favicon.svg / favicon.ico)
├── src/
│   ├── components/
│   │   └── Counter.vue      # Vue 单文件组件
│   └── pages/
│       └── index.astro      # 首页,负责挂载 Counter
├── astro.config.mjs          # 集成配置
├── package.json
└── tsconfig.json

其中 package.json 声明了三类关键依赖与运行前提(以 examples/framework-vue/package.json 为准):

  • astro: ^7.2.10:Astro 框架本体;
  • @astrojs/vue: ^7.0.2:Vue 渲染集成包;
  • vue: ^3.5.29:Vue 3 运行时;
  • engines.node: >=22.12.0:Node.js 版本下限。

本地启动使用标准 Astro 脚本:npm run dev(对应 astro dev)、npm run buildnpm run preview

astro.config.mjs:一行集成启用 Vue 渲染器

示例的全部配置就四行核心代码(见 examples/framework-vue/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()],
});

vue() 返回一个 AstroIntegration,注册后 Astro 就获得了解析、SSR 渲染与水合 .vue 文件的能力。这个"一行配置"背后实际发生了什么,可以从集成包源码 packages/integrations/vue/src/index.ts 得到印证:

  1. 注册渲染器:在 astro:config:setup 钩子中调用 addRenderer(getContainerRendererImpl()),把 Vue 的容器渲染器(服务端入口 @astrojs/vue/server.js、客户端入口 @astrojs/vue/client.js)挂到 Astro 的渲染管线中;
  2. 注入 Vite 插件:通过 updateConfig 向 Vite 插件栈注入 @vitejs/plugin-vue(并显式关闭 transformAssetUrls,交由 Astro 自行处理模板资源 URL)、自定义虚拟模块插件与环境优化插件。

vue() 接受可选参数对象,从 Options 接口定义(同上文件第 14–18 行)可以看到完整参数面:

参数 类型 作用
jsx boolean | VueJsxOptions 启用 Vue 的 JSX 支持,额外注册 @vitejs/plugin-vue-jsx 与名为 @astrojs/vue (jsx) 的 JSX 渲染器
appEntrypoint string 指定 Vue 应用入口(如 src/vue.ts),Astro 会通过虚拟模块 virtual:astro:vue-app 动态 import 它并在每个 app 上执行其默认导出函数,用于在渲染前初始化 Vue 应用(安装插件、配置全局状态等)
devtools boolean | VitePluginVueDevToolsOptions 仅在 dev 命令下加载 vite-plugin-vue-devtools,注入 Vue DevTools 面板
其余透传项 @vitejs/plugin-vueOptions 直接透传给 Vue Vite 插件,例如 templatecompiler

此外源码中还有一个值得注意的细节:astro:config:done 钩子会检测是否同时启用了多个 JSX 渲染器(@astrojs/react@astrojs/preact@astrojs/solid-js 与 Vue JSX)。若多于一个且未设置 include/exclude,会打印警告提示开发者显式限定组件归属,避免渲染器歧义。另外从源码结构看,旧的从包根导入 getContainerRenderer() 的方式已被标记 @deprecated,官方建议改从 @astrojs/vue/container-renderer 导入。

Counter.vue:Vue 组件的完整写法

示例的核心组件 examples/framework-vue/src/components/Counter.vue 是一个典型的 Vue 3 组合式 API 单文件组件,共三个块:

<script setup lang="ts">
import { ref } from 'vue';

const count = ref(0);
const add = () => count.value++;
const subtract = () => count.value--;
</script>

<template>
	<div class="counter">
		<button @click="subtract">-</button>
		<pre>{{ count }}</pre>
		<button @click="add">+</button>
	</div>
	<div class="counter-message">
		<slot />
	</div>
</template>

<style>
.counter {
	display: grid;
	font-size: 2em;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	margin-top: 2em;
	place-items: center;
}

.counter-message {
	text-align: center;
}
</style>

要点逐条拆解:

  • <script setup lang="ts">:编译式组合式 API,count 是一个响应式 ref;组件通过 add / subtract 两个方法驱动计数增减,这是演示"客户端交互状态"的最小闭环;
  • <slot />:组件预留了默认插槽。这一点与下一页的关键——Astro 页面向 Vue 组件透传子内容的机制直接对应;
  • 非 scoped 的 <style>:普通 CSS 块会被集成包收集并按 Astro 的样式管线注入页面。集成包源码中对 appEntrypoint 的处理注释提到"让 Vue 组件直接引用 appEntrypoint,以便 Astro 把该文件里 import 的全局样式关联到应注入的页面",即 SFC 中的样式同样参与 Astro 的 CSS 分块与去重。

index.astro:挂载 Vue 组件与 client:visible 指令

页面文件 examples/framework-vue/src/pages/index.astro 展示了 Astro 与 Vue 协作的两个核心动作——导入 .vue 组件客户端指令水合

---
// Component Imports
import Counter from '../components/Counter.vue';
---

<html lang="en">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<link rel="icon" href="/favicon.ico" />
		<style>
			html, body { font-family: system-ui; margin: 0; }
			body { padding: 2rem; }
		</style>
	</head>
	<body>
		<main>
			<Counter client:visible>
				<h1>Hello, Vue!</h1>
			</Counter>
		</main>
	</body>
</html>

逐点说明:

  1. 直接 import Counter from '../components/Counter.vue':因为 astro.config.mjs 中已注册 @astrojs/vue.vue 扩展名在构建管线中被 Vite 的 Vue 插件接管,页面层无需任何额外配置。Astro.generator 是 Astro 内置的元信息对象,用于生成 <meta name="generator">
  2. client:visible 指令:这是示例的关键交互点。它表示该 Vue 组件在服务端先被 SSR 出初始 HTML(首屏可见计数器 UI 与 Hello, Vue!),但当组件滚动进入视口时才下载并执行对应 JS、完成水合。Astro 提供了一族客户端指令:client:only(仅客户端渲染,服务端不产出 HTML)、client:load(立即加载水合)、client:idle(浏览器空闲时水合)、client:visible(进入视口时水合)、client:media(满足媒体查询时水合)——这些指令在类型定义中集中声明于 packages/astro/src/types/public/elements.ts。对首屏之外的交互组件选择 client:visible 的意义在于按需加载 JS,减少首屏体积。
  3. 插槽透传<Counter client:visible> 内部写入的 <h1>Hello, Vue!</h1> 会作为默认插槽内容传入 Vue 组件的 <slot /> 位置。水合后,这部分内容同样由 Vue 接管,与纯 Astro 组件的 slot 语义保持一致。

tsconfig 与依赖配置细节

示例的 tsconfig.json 只有三处关键设置:

{
  "extends": "astro/tsconfigs/strict",
  "include": [".astro/types.d.ts", "**/*"],
  "exclude": ["dist"],
  "compilerOptions": {
    // Needed for TypeScript intellisense in the template inside Vue files
    "jsx": "preserve"
  }
}
  • astro/tsconfigs/strict:继承 Astro 官方严格版 TS 基线;
  • "jsx": "preserve":这是示例注释明确指出的必需项,用于保证 Vue SFC <template> 内 JSX 语法的 TypeScript 智能提示;
  • .astro/types.d.ts 为 Astro 构建时生成的类型文件,纳入编译范围可获得路由、内容集合等类型。

底层实现补充:SSR 预渲染与依赖优化

除渲染器注册与 Vite 插件注入外,packages/integrations/vue/src/index.ts 中的 configEnvironmentPlugin 还处理了多环境(client / ssr / prerender)下的依赖优化细节,从源码结构看可以归纳为:

  • client 环境optimizeDeps.include 显式加入 vue@astrojs/vue/client.js,保证水合运行时被预构建、按需加载命中缓存;同时排除服务端专用入口 @astrojs/vue/server.jsvue/server-renderer 与虚拟模块,防止客户端 bundle 混入 SSR 代码;
  • ssr / prerender 环境:若未关闭 noExternal,将 vuetifyvueperslidesprimevue 标记为外部依赖,避免这些大型 UI 库被 Vite 预构建拖慢构建;
  • virtual:astro:vue-app 虚拟模块:当配置了 appEntrypoint 时,load 钩子动态生成一段 setup(app) 代码去调用用户入口的默认导出;transform 钩子还会在每个 .vue 文件头部注入对该入口的 import,使入口中引入的全局样式能正确关联到页面。

集成包的测试套件位于 packages/integrations/vue/test/,其中 basicsapp-entrypoint 等 fixture 覆盖了基础 SFC 渲染、入口函数、CSS 注入等路径,可作为验证行为正确性的参照。

小结与扩展路径

这个示例用最小代价展示了 Astro 的"框架无关容器"理念:Astro 负责页面骨架与静态内容,Vue 组件以指令为开关按需接管交互。基于本示例可以继续扩展的方向包括:

  • vue() 中传入 { jsx: true } 使用 Vue 的 JSX 语法;
  • 配置 appEntrypoint 以初始化 Vue Router、Pinia 等应用级能力;
  • 开发期开启 devtools 获得 Vue DevTools 面板;
  • 参考 packages/integrations/vue/README.md 了解集成包的维护方与支持渠道,以及示例集 examples/framework-multiple 查看多框架(Vue、React、Svelte、Solid 等)混合使用的形态。

需要注意的适用前提:示例面向 astro ^7.2.10@astrojs/vue ^7.0.2,要求 Node.js >=22.12.0;文中关于集成内部行为的描述均以当前仓库源码为准。

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

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341