首页
/ Astro Integration 包实战:从官方 Starter 模板构建、联调并发布你的 Astro 集成

Astro Integration 包实战:从官方 Starter 模板构建、联调并发布你的 Astro 集成

2026-09-04 13:06:23作者:段琳惟

Astro 通过 Integration API 让第三方包能够在配置、开发服务器、构建等各个生命周期阶段扩展框架行为。本文基于 Astro 仓库中的官方集成模板 examples/integration/README.md 展开,结合模板源码与框架核心类型定义,系统讲解如何从零创建一个 Astro Integration 包:包括模板获取与项目结构、入口文件 index.ts 的工厂函数写法、package.json 的关键字段、astro:config:setup 等生命周期钩子的完整参数,以及 npm link 本地联调与 npm publish 发布的完整工作流。读完后你可以独立编写、调试并分发一个可复用、可发布的 Astro 集成包。

获取模板:一条命令创建 Integration 项目

官方模板的使用方式是在任意空目录中运行以下命令(引自 README):

npm create astro@latest -- --template integration

该模板的定位是"用于编写跨多个项目复用、或发布到 NPM 的 Astro 集成"的起点。模板本身刻意保持极简——没有 src/pages、没有 astro.config.mjs,因为 Integration 包本身不是一个网站,而是一个被网站项目以 integrations: [] 形式引入的第三方包。

项目结构:三个文件构成的最小 Integration 包

模板生成的目录结构如下(完整继承自 README):

/
├── index.ts
├── tsconfig.json
├── package.json

其中 index.ts 是 integration 的"入口点"(entry point):把集成在 index.ts 中导出,它就能被你的包所引用。下面逐文件解读这三个文件的真实内容。

入口 index.ts:导出工厂函数,返回 AstroIntegration

模板的 index.ts 全文如下:

import type { AstroIntegration } from 'astro';

export default function createIntegration(): AstroIntegration {
	// See the Integration API docs for full details
	// https://docs.astro.build/en/reference/integrations-reference/
	return {
		name: '@example/my-integration',
		hooks: {
			'astro:config:setup': () => {
				// See the @astrojs/react integration for an example
				// https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts
			},
			'astro:build:setup': () => {
				// See the @astrojs/react integration for an example
				// https://github.com/withastro/astro/blob/main/packages/integrations/react/src/index.ts
			},
			'astro:build:done': () => {
				// See the @astrojs/partytown integration for an example
				// https://github.com/withastro/astro/blob/main/packages/integrations/partytown/src/index.ts
			},
		},
	};
}

模板注释中指向的参考实现就存放在当前仓库中。以 @astrojs/react 的源码 为例,其默认导出同样是"接收选项、返回 AstroIntegration"的工厂函数,并在 astro:config:setup 中调用钩子参数完成三件典型工作:

'astro:config:setup': ({ command, addRenderer, updateConfig, injectScript }) => {
	// 1. 注册渲染器,让 Astro 知道用哪个框架渲染框架组件
	addRenderer(getRenderer(versionConfig));
	// 2. 把 Vite 插件(@vitejs/plugin-react)注入到 Astro 的 Vite 配置
	updateConfig({ vite: getViteConfiguration({...}, versionConfig) });
	// 3. 仅在 dev 命令下注入 fast-refresh 前导脚本
	if (command === 'dev') {
		const preamble = FAST_REFRESH_PREAMBLE.replace(`__BASE__`, '/');
		injectScript('before-hydration', preamble);
	}
},

它还在 astro:config:done 中通过 logger.warn 检测"同时启用了多个 JSX 渲染器且未设置 include/exclude"的冲突场景。这个真实例子直观展示了集成模板中三个空钩子各自能做什么:astro:config:setup 用于注册渲染器与注入 Vite 插件,构建类钩子则用于处理产物。

值得注意的细节是,模板中 name 字段写的是 '@example/my-integration',而 package.json 的包名是 @example/integrationname 主要用于 Astro 内部的日志与冲突检测,建议正式发布时统一为与包名一致,避免排查问题时产生歧义。

package.json:决定包"如何被消费"的关键字段

模板的 package.json 内容不长,但每个字段都直接影响集成包的安装与加载方式:

{
  "name": "@example/integration",
  "private": true,
  "engines": { "node": ">=22.12.0" },
  "version": "0.0.1",
  "type": "module",
  "exports": { ".": "./index.ts" },
  "files": ["src", "index.ts"],
  "keywords": ["withastro"],
  "devDependencies": { "astro": "^7.2.10" },
  "peerDependencies": { "astro": "^4.0.0" }
}

各字段的含义与约束:

  • exports: { ".": "./index.ts" }:把包的根导入指向 index.ts。用户项目中 import myIntegration from '@example/integration' 时解析到的就是这个默认导出的工厂函数。这也是 README 强调"在 index.ts 中导出集成"的原因。
  • files: ["src", "index.ts"]:限制 npm publish 时只把 src 目录与 index.ts 打进包体,控制发布体积;如果你的实现放在 src/ 下,发布前需要确认 files 与实际目录、exports 指向的文件保持一致。
  • private: true:防止模板原样被误发布到 NPM。真正发布前必须移除该字段。
  • peerDependencies:声明对 Astro 运行时的版本要求,由使用方的 Astro 项目提供实际版本,集成包自身不重复安装运行时。
  • devDependencies 中的 astro:仅用于开发期类型检查与本地运行,不进入依赖树。
  • keywords: ["withastro"]:便于在 NPM 生态中被检索到。

模板的 tsconfig.json 只有一行 "extends": "astro/tsconfigs/strict",即复用 Astro 官方发布的严格 TS 配置基线,保证类型推导与 Astro 的类型系统对齐。

生命周期钩子:从核心类型定义看集成能介入哪些阶段

模板中的三个钩子只是起点。Astro 的集成 API 在核心类型定义 packages/astro/src/types/public/integrations.ts 中给出了完整的 BaseIntegrationHooks 定义,覆盖开发、同步、构建的全生命周期。摘录各钩子及其核心参数如下:

钩子 触发时机 关键参数(节选)
astro:config:setup 配置解析完成后、最终配置确定前,dev/build/preview/sync 均会触发 configcommand('dev' | 'build' | 'preview' | 'sync')、isRestartupdateConfigaddRendereraddWatchFileinjectScriptinjectRouteaddClientDirectiveaddDevToolbarAppaddMiddlewarecreateCodegenDirlogger
astro:config:done 最终配置确定后 configsetAdapterinjectTypesloggerbuildOutput('static' | 'server')
astro:server:setup 开发服务器创建后 server(ViteDevServer)、toolbarrefreshContentlogger
astro:server:start 开发服务器开始监听后 address(监听地址信息)、logger
astro:server:done 开发服务器退出时 logger
astro:build:setup 每次 Vite 构建前(client/server 两轮各一次) vite(InlineConfig)、pages(路由构建数据)、target('client' | 'server')、updateConfiglogger
astro:build:generated 构建产物生成后 dir(输出目录)、routeToHeaderslogger
astro:build:done 构建全部完成后 pages(已构建页面列表)、dirassets(资源映射)、logger
astro:route:setup 每个路由解析时 route(component 与 prerender)、logger
astro:routes:resolved 全部路由解析完成后 routeslogger
astro:build:ssr SSR 构建完成后 manifest(序列化 SSR 清单)、middlewareEntryPointlogger
astro:build:start 构建开始前 loggersetPrerenderer

几点从类型定义中可以确认的实现细节:

  • astro:config:setupinjectScript 接受四种注入阶段,定义为 InjectedScriptStage = 'before-hydration' | 'head-inline' | 'page' | 'page-ssr'。前两者、以及 page 阶段会被 Vite 处理与解析(head-inline 除外,它直接内联进 <head> 的 script 标签),page-ssr 则注入到每个 Astro 页面的 frontmatter 中。@astrojs/react 在 dev 模式下注入的 fast-refresh preamble 用的就是 before-hydration 阶段。
  • astro:build:setup 会执行两次:一次针对 target: 'client',一次针对 target: 'server'。编写构建钩子时应根据 target 区分需要注入的 Vite 插件与产物处理逻辑。
  • 钩子函数可以是异步的:类型上所有钩子都允许返回 void | Promise<void>,可以安全地 await 文件系统或网络操作。
  • AstroIntegrationhooks 类型允许通过 & Partial<Record<string, unknown>> 携带任意自定义键,即框架对未知钩子键采取宽松处理,不会因拼写错误而直接抛错——这也是编写集成时需要对钩子名做字符串校验类测试的原因。

在 Astro 项目中引用你的集成

集成包编写完成后,消费方的接入方式与其他官方集成完全一致:

// astro.config.mjs
import myIntegration from '@example/integration';

export default defineConfig({
	integrations: [myIntegration()], // 工厂函数调用,可传参
});

框架在 packages/astro/src/core/create-vite.ts 等核心模块中按顺序调用用户集成与内置 Vite 插件管线,integrations 数组中的每一项都会在命令启动时被调用并合并其钩子。由于 astro:config:setup 钩子的 command 参数会区分当前命令,你的集成可以只在 dev 时注入刷新脚本、只在 build 时做产物处理。

开发与发布工作流

README 中的命令表完整继承如下,所有命令均从项目根目录的终端执行:

命令 作用
npm link 将本包在本地注册为全局链接包;随后在任意 Astro 项目中运行 npm link my-integration 即可安装你的集成
npm publish 将包发布到 NPM。发布前需确保已登录 NPM 账号

一个可落地的本地联调循环是:

  1. 在集成模板目录中运行 npm link,把 @example/integration 注册到本机 npm 全局链接;
  2. 在目标 Astro 项目根目录运行 npm link @example/integration(README 中写作 npm link my-integration,替换为你的包名);
  3. astro.config.mjsintegrations 中引入并调用该集成,npm run dev 验证行为;修改 index.ts 后无需重新构建,link 场景下源码即被直接解析(模板 exports 直接指向 ./index.ts,这一点对本地联调尤为友好);
  4. 验证通过后,移除 package.json 中的 private: true,修正 name 为正式包名,再运行 npm publish 发布。

小结

这个仅含三个文件的 模板 覆盖了编写 Astro 集成包的全部骨架:index.ts 以工厂函数导出 AstroIntegrationpackage.jsonexports/files/peerDependencies 决定包的分发形态,npm linknpm publish 分别支撑本地联调与正式发布。在此基础上,参考 integrations.ts 中的 BaseIntegrationHooks 完整定义和 @astrojs/react 等仓库内真实集成的实现,你可以把配置注入、渲染器注册、构建产物处理等能力逐步填充进自己的集成,形成一个可跨项目复用、可发布到 NPM 的 Astro 扩展包。

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

项目优选

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