Astro 多框架集成实战:一个项目同时使用 React、Preact、Solid、Svelte 与 Vue
本篇基于 Astro 官方示例 examples/framework-multiple("Kitchen Sink: Microfrontends with Astro")展开,演示如何在一个 Astro 项目中同时接入五种前端框架的组件。读完后你将掌握:如何通过 integrations 配置让多框架共存、include/exclude 过滤器如何避免 Vite 插件之间的文件处理冲突,以及各框架组件在 Astro 页面中导入与客户端加载的完整写法。
一、示例定位:Astro 的多框架原生支持
该示例的核心主张只有一句话:Astro 内置了对多个前端框架的支持,可以在同一个项目中同时使用 React、Preact、Svelte 和 Vue(v3.x),甚至还能加上 Solid。README 中的关键说明是:
No configuration is needed to enable these frameworks—just start writing components in
src/components.
也就是说,框架集成能力来自 Astro 生态的官方集成包(@astrojs/react、@astrojs/preact 等),只需在 astro.config.mjs 中注册即可,不需要额外脚手架或构建工具改造。
用一条命令创建项目
官方提供了 framework-multiple 模板,可以直接创建此示例项目:
npm create astro@latest -- --template framework-multiple
项目目录结构如下(摘自本仓库 examples/framework-multiple 实际文件):
examples/framework-multiple/
├── astro.config.mjs # 注册五个框架集成
├── package.json # 依赖:五个框架 + 五个官方集成包
├── tsconfig.json # 继承 astro/tsconfigs/strict
└── src/
├── components/
│ ├── preact/PreactCounter.tsx
│ ├── react/ReactCounter.tsx
│ ├── solid/SolidCounter.tsx
│ ├── svelte/SvelteCounter.svelte
│ └── vue/VueCounter.vue
├── pages/index.astro # 同页混用五种框架组件
└── styles/global.css
每个框架组件都是一个结构相同的计数器:一个 -/+ 按钮、一个 <pre> 显示计数,外加一个接收插槽内容的消息区。五个组件在同一个首页上并排渲染,直观验证"多框架共存"的可行性。
二、核心配置:integrations 与 include 过滤器
多框架项目最关键的配置文件是 examples/framework-multiple/astro.config.mjs:
// @ts-check
import preact from '@astrojs/preact';
import react from '@astrojs/react';
import solid from '@astrojs/solid-js';
import svelte from '@astrojs/svelte';
import vue from '@astrojs/vue';
import { defineConfig } from 'astro/config';
// https://astro.build/config
export default defineConfig({
// Enable many frameworks to support all different kinds of components.
integrations: [
preact({ include: ['**/preact/*'] }),
solid({ include: ['**/solid/*'] }),
react({ include: ['**/react/*'] }),
svelte(),
vue(),
],
});
这里有几个值得注意的要点:
- 每个框架对应一个官方集成包,通过
integrations数组注册。从 examples/framework-multiple/package.json 可以看到当前示例使用的版本组合:@astrojs/preact@^6.0.5、@astrojs/react@^6.0.5、@astrojs/solid-js@^7.0.2、@astrojs/svelte@^9.0.1、@astrojs/vue@^7.0.2,同时安装了框架本体(preact、react/react-dom、solid-js、svelte、vue),Node 要求为>=22.12.0。 - 用
include把各 JSX 类框架的文件隔离到独立目录。示例中react({ include: ['**/react/*'] })、preact({ include: ['**/preact/*'] })、solid({ include: ['**/solid/*'] })各管各的目录。这一设计的原因在于:React、Preact、Solid 三者都使用.tsx扩展名且 JSX 语义相近(如onClick),若不限制文件范围,Vite 插件可能把 Preact 文件交给 React 编译器处理,导致运行时错误。 - Svelte 和 Vue 不需要 include。Svelte 组件是独立的
.svelte文件、Vue 是.vue文件,扩展名天然不冲突,因此直接svelte()、vue()即可。
从源码结构看,include 参数确实会透传给底层的 Vite 框架插件:在 packages/integrations/react/src/index.ts 中,集成接收 include/exclude 选项后分别传给 Vite 的 React 插件(编译范围控制)与 Astro 的客户端岛处理链路;该文件还会自动将 .astro 文件加入 exclude(注释说明在 Vite 8 中 @vitejs/plugin-react 需要显式排除 .astro 文件),保证 Astro 模板本身不会被 React 编译器误处理。
三、页面层:一个页面同时渲染五个框架的组件
examples/framework-multiple/src/pages/index.astro 展示了五种框架组件在同一个 Astro 页面中的完整用法:
---
// Style Imports
import '../styles/global.css';
import { PreactCounter } from '../components/preact/PreactCounter';
// Component Imports
// For JSX components, all the common ways of exporting (under a namespace,
// specific export, default export etc) are supported!
import * as react from '../components/react/ReactCounter';
import SolidCounter from '../components/solid/SolidCounter';
import SvelteCounter from '../components/svelte/SvelteCounter.svelte';
import VueCounter from '../components/vue/VueCounter.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" />
</head>
<body>
<main>
<react.Counter client:visible>
<h1>Hello from React!</h1>
</react.Counter>
<PreactCounter client:visible>
<h1>Hello from Preact!</h1>
</PreactCounter>
<SolidCounter client:visible>
<h1>Hello from Solid!</h1>
</SolidCounter>
<VueCounter client:visible>
<h1>Hello from Vue!</h1>
</VueCounter>
<SvelteCounter client:visible>
<h1>Hello from Svelte!</h1>
</SvelteCounter>
</main>
</body>
</html>
其中体现的两类要点:
- JSX 组件的导入方式非常灵活。源码注释明确写道:"For JSX components, all the common ways of exporting (under a namespace, specific export, default export etc) are supported!"。示例中 React 组件用了命名空间导入(
import * as react,页面上写作<react.Counter>),Preact/Solid 用常规命名/默认导入,Svelte/Vue 直接按扩展名导入。 client:visible客户端指令。五个计数器都需要交互,统一使用client:visible:当组件滚动进入视口时才加载对应的框架运行时并水合,比无条件加载更省首屏成本。各框架的运行时(React、Preact 等)会被打包成独立的客户端岛,只有在需要时才下载执行。
页面样式由 examples/framework-multiple/src/styles/global.css 提供,.counter 用 CSS Grid 三列布局排列 -、计数、+。
四、五个框架组件的实现对照
每个组件都是一个"计数器 + 插槽",实现方式恰好覆盖各自框架的惯用语法,适合作为跨框架速查对照。
React:显式指定 JSX 来源
examples/framework-multiple/src/components/react/ReactCounter.tsx 第一行是 /** @jsxImportSource react */——在多框架项目中这一行至关重要:TypeScript 需要知道该 .tsx 文件的 JSX 应编译为 React.createElement 而非其他框架的运行时。
/** @jsxImportSource react */
import { type ReactNode, useState } from 'react';
export function Counter({ children }: { children?: ReactNode }) {
const [count, setCount] = useState(0);
const add = () => setCount((i) => i + 1);
const subtract = () => setCount((i) => i - 1);
return (
<>
<div className="counter">
<button onClick={subtract}>-</button>
<pre>{count}</pre>
<button onClick={add}>+</button>
</div>
<div className="counter-message">{children}</div>
</>
);
}
Preact 的写法几乎一致(PreactCounter.tsx),只是 @jsxImportSource preact、hooks 从 preact/hooks 导入;Solid(SolidCounter.tsx)则换成 @jsxImportSource solid-js 和 createSignal 响应式原语。
Svelte 5:runes 语法
SvelteCounter.svelte 使用 Svelte 5 的 runes:$props() 接收插槽(类型 Snippet),$state(0) 声明响应式计数,模板中 {@render children?.()} 渲染插槽。
Vue 3:setup() + 一个已知的类型提示噪音
VueCounter.vue 使用组合式 API 的 Options 风格 setup(),ref(0) 声明计数。该文件里还保留了一条很有价值的注释:如果 Vue 模板中的 class 出现类型错误,原因是 @types/react 的 JSX 定义是全局声明、会泄漏到项目所有文件,在 React 与 Vue 共用 TypeScript 的项目中目前没有完全规避的办法。这提示在混合项目中若遇到此类编辑器误报,属于已知现象而非配置错误。
五、TypeScript 配置:让 Vue 模板获得智能提示
examples/framework-multiple/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 官方的 strict 预设,jsx: "preserve" 则是为了让 Vue 单文件组件的 <template> 部分(内含 JSX 风格的模板语法)获得 TypeScript 智能提示。
六、运行验证:官方 e2e 测试如何覆盖多框架场景
Astro 仓库自带一套 Playwright e2e 测试来验证多框架场景,即 packages/astro/e2e/multiple-frameworks.test.ts,它对每个框架的计数器做了一致的断言:
- 页面加载后对应
#react-counter、#preact-counter、#solid-counter、#vue-counter、#svelte-counter均可见且初始计数为0; - 点击
.increment按钮后计数变为1,证明各框架组件的客户端事件绑定真正生效; - 还包含一组 HMR 用例:分别修改各框架组件源码(如 React 的
useState(0)改为useState(5)、Vue 的ref(0)改为ref(5)、Svelte 的let count = 0改为let count = 5),断言开发服务器热更新后计数器初始值变化——说明多框架集成下各框架的热替换能力同样可用。
该测试基于独立的 fixture(packages/astro/e2e/fixtures/multiple-frameworks/)运行,验证的是 Astro 核心与集成层的组合行为,与本文示例目录互为印证。
小结
把这篇示例的要点浓缩成可复用的实践清单:
- 注册集成:在
astro.config.mjs的integrations中加入需要的@astrojs/*集成包,无需其他配置; - 目录隔离:JSX 类框架(React/Preact/Solid)建议通过
{ include: ['**/框架名/*'] }限定处理范围,.svelte/.vue组件可免配置; - 显式 JSX 来源:每个
.tsx组件文件首行用@jsxImportSource注释指明所属框架; - 按需水合:交互组件配合
client:visible等指令,只在需要时加载对应框架运行时; - TS 兼容:使用
astro/tsconfigs/strict预设,并视 Vue 提示需求开启jsx: "preserve"。
这套机制使"微前端"式的多技术栈共存成为可能——团队可以按组件维度选择最合适的框架,而整个站点仍由 Astro 的构建、路由与渲染管线统一托管。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00