跳转到内容

Astro 集成 API

Astro 集成只需几行代码即可为你的项目添加新功能和行为。

本参考页面适用于任何想要编写自己集成的开发者。要了解如何在你的项目中使用集成,请查阅我们的使用集成指南。

官方的 Astro 集成可以作为你构建自己集成时的参考。

interface AstroIntegration {
name: string;
hooks: {
'astro:config:setup'?: (options: {
config: AstroConfig;
command: 'dev' | 'build' | 'preview' | 'sync';
isRestart: boolean;
updateConfig: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;
addRenderer: (renderer: AstroRenderer) => void;
addWatchFile: (path: URL | string) => void;
addClientDirective: (directive: ClientDirectiveConfig) => void;
addMiddleware: (middleware: AstroIntegrationMiddleware) => void;
addDevToolbarApp: (entrypoint: DevToolbarAppEntry) => void;
injectScript: (stage: InjectedScriptStage, content: string) => void;
injectRoute: (injectedRoute: InjectedRoute) => void;
createCodegenDir: () => URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:route:setup'?: (options: {
route: RouteOptions;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:routes:resolved'?: (options: {
routes: IntegrationResolvedRoute[];
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:config:done'?: (options: {
config: AstroConfig;
setAdapter: (adapter: AstroAdapter) => void;
injectTypes: (injectedType: InjectedType) => URL;
logger: AstroIntegrationLogger;
buildOutput: 'static' | 'server';
}) => void | Promise<void>;
'astro:server:setup'?: (options: {
server: vite.ViteDevServer;
logger: AstroIntegrationLogger;
toolbar: ReturnType<typeof getToolbarServerCommunicationHelpers>;
refreshContent?: (options: RefreshContentOptions) => Promise<void>;
}) => void | Promise<void>;
'astro:server:start'?: (options: {
address: AddressInfo;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:server:done'?: (options: {
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:start'?: (options: {
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:setup'?: (options: {
vite: vite.InlineConfig;
pages: Map<string, PageBuildData>;
target: 'client' | 'server';
updateConfig: (newConfig: vite.InlineConfig) => void;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:ssr'?: (options: {
manifest: SerializedSSRManifest;
entryPoints: Map<IntegrationRouteData, URL>;
middlewareEntryPoint: URL | undefined;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:generated'?: (options: {
dir: URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
'astro:build:done'?: (options: {
pages: { pathname: string }[];
dir: URL;
assets: Map<string, URL[]>;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;
// ... any custom hooks from integrations
};
}

Astro 提供了钩子(hooks),集成可以实现这些钩子以在 Astro生命周期的特定部分执行代码。Astro 钩子在 IntegrationHooks 接口中定义,该接口是全局 Astro 命名空间的一部分。每个钩子都有一个logger 选项,允许你使用 Astro 的日志记录器来写入日志。

以下是 Astro 内置的钩子

下一个钩子: astro:route:setup

何时: 初始化时,在 ViteAstro 配置解析之前。

为何: 扩展项目配置。这包括更新 Astro 配置、应用 Vite 插件、添加组件渲染器以及向页面注入脚本。

'astro:config:setup'?: (options: {
config: AstroConfig;
command: 'dev' | 'build' | 'preview' | 'sync';
isRestart: boolean;
updateConfig: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;
addRenderer: (renderer: AstroRenderer) => void;
addClientDirective: (directive: ClientDirectiveConfig) => void;
addMiddleware: (middleware: AstroIntegrationMiddleware) => void;
addDevToolbarApp: (entrypoint: DevToolbarAppEntry) => void;
addWatchFile: (path: URL | string) => void;
injectScript: (stage: InjectedScriptStage, content: string) => void;
injectRoute: (injectedRoute: InjectedRoute) => void;
createCodegenDir: () => URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: AstroConfig

用户提供的 Astro 配置的只读副本。它在任何其他集成运行之前被解析。如果你需要所有集成完成其配置更新后的配置副本,请查看 astro:config:done 钩子

类型: 'dev' | 'build' | 'preview' | 'sync'

  • dev - 项目通过 astro dev 执行
  • build - 项目通过 astro build 执行
  • preview - 项目通过 astro preview 执行
  • sync - 项目通过 astro sync 执行

类型: boolean

添加于: astro@1.5.0

开发服务器启动时为 false,触发重新加载时为 true。用于检测此函数是否被多次调用。

类型: (newConfig: DeepPartial<AstroConfig>) => AstroConfig;

一个用于更新用户提供的 Astro 配置的回调函数。你提供的任何配置都将与用户配置和其他集成的配置更新合并,所以你可以自由地省略一些键!

例如,假设你需要为用户的项目提供一个 Vite 插件

import bananaCSS from '@vitejs/official-banana-css-plugin';
export default {
name: 'banana-css-integration',
hooks: {
'astro:config:setup': ({ updateConfig }) => {
updateConfig({
vite: {
plugins: [bananaCSS()],
}
})
}
}
}

类型: (renderer: AstroRenderer ) => void;
示例: sveltereactpreactvuesolid

一个用于添加组件框架渲染器(如 React、Vue、Svelte 等)的回调函数。你可以浏览上面的示例和类型定义以获取更高级的选项,但这里有两个主要选项需要注意

  • clientEntrypoint - 每当使用你的组件时,在客户端执行的文件的路径。这主要用于通过 JS 渲染或注水(hydrate)你的组件。
  • serverEntrypoint - 每当使用你的组件时,在服务器端请求或静态构建期间执行的文件的路径。这应该将组件渲染为静态标记,并在适用时带有用于注水(hydration)的钩子。 React 的 renderToString 回调是一个经典的例子。

添加于: astro@5.0.0

函数 clientEntrypointserverEntrypoint 接受一个 URL

类型: (path: URL | string) => void

添加于: astro@1.5.0

如果你的集成依赖于某些 Vite 不会监视的配置文件,和/或需要完全重启开发服务器才能生效,请使用 addWatchFile 添加它。每当该文件更改时,Astro 开发服务器将重新加载(你可以使用 isRestart 检查何时发生重新加载)。

用法示例

// Must be an absolute path!
addWatchFile('/home/user/.../my-config.json');
addWatchFile(new URL('./ec.config.mjs', config.root));

类型: (directive: ClientDirectiveConfig ) => void;

添加于: astro@2.6.0

添加一个自定义客户端指令,用于 .astro 文件中。

请注意,指令的入口点仅通过 esbuild 进行打包,应保持较小体积,以免减慢组件的注水(hydration)速度。

用法示例

astro.config.mjs
import { defineConfig } from 'astro/config';
import clickDirective from './astro-click-directive/register.js'
// https://astro.js.cn/config
export default defineConfig({
integrations: [
clickDirective()
],
});
astro-click-directive/register.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "client:click",
hooks: {
"astro:config:setup": ({ addClientDirective }) => {
addClientDirective({
name: "click",
entrypoint: "./astro-click-directive/click.js",
});
},
},
});
astro-click-directive/click.js
/**
* Hydrate on first click on the window
* @type {import('astro').ClientDirective}
*/
export default (load, opts, el) => {
window.addEventListener('click', async () => {
const hydrate = await load()
await hydrate()
}, { once: true })
}

你也可以在库的类型定义文件中为指令添加类型

astro-click-directive/index.d.ts
import 'astro'
declare module 'astro' {
interface AstroClientDirectives {
'client:click'?: boolean
}
}

类型: (entrypoint: DevToolbarAppEntry) => void;

新增于: astro@3.4.0

添加一个自定义的开发工具栏应用

用法示例

astro.config.mjs
import { defineConfig } from 'astro/config';
import devToolbarIntegration from './astro-dev-toolbar-app/integration.js'
// https://astro.js.cn/config
export default defineConfig({
integrations: [
devToolbarIntegration()
],
});
astro-dev-toolbar-app/integration.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "dev-toolbar-app",
hooks: {
"astro:config:setup": ({ addDevToolbarApp }) => {
addDevToolbarApp({
entrypoint: "./astro-dev-toolbar-app/plugin.js",
id: "my-plugin",
name: "My Plugin"
});
},
},
});
astro-dev-toolbar-app/plugin.js
/**
* @type {import('astro').DevToolbarApp}
*/
export default {
id: "my-plugin",
name: "My Plugin",
icon: "<svg>...</svg>",
init() {
console.log("I'm a dev toolbar app!")
},
};

类型: (middleware: AstroIntegrationMiddleware ) => void;

新增于: astro@3.5.0

添加在每个请求上运行的中间件。它接受包含中间件的 entrypoint 模块,以及一个 order 来指定它应该在其他中间件之前(pre)还是之后(post)运行。

@my-package/integration.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "my-middleware-package",
hooks: {
"astro:config:setup": ({ addMiddleware }) => {
addMiddleware({
entrypoint: '@my-package/middleware',
order: 'pre'
});
},
},
});

中间件在一个包中定义,带有一个 onRequest 函数,就像用户定义的中间件一样。

@my-package/middleware.js
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware(async (context, next) => {
if(context.url.pathname === '/some-test-path') {
return Response.json({
ok: true
});
}
return next();
});

添加于: astro@5.0.0

该函数也接受一个 URL 作为 entrypoint

@my-package/integration.js
/**
* @type {() => import('astro').AstroIntegration}
*/
export default () => ({
name: "my-middleware-package",
hooks: {
"astro:config:setup": ({ addMiddleware }) => {
addMiddleware({
entrypoint: new URL('./middleware.js', import.meta.url),
order: 'pre'
});
},
},
});

类型: ({ pattern: string; entrypoint: string | URL; prerender?: boolean }) => void;

一个用于向 Astro 项目中注入路由的回调函数。注入的路由可以是 .astro 页面.js.ts 路由处理程序

injectRoute 接受一个带有 patternentrypoint 的对象。

  • pattern - 路由在浏览器中输出的位置,例如 /foo/bar。`pattern` 可以使用 Astro 的文件路径语法来表示动态路由,例如 /foo/[bar]/foo/[...bar]。请注意,在 pattern需要文件扩展名。
  • entrypoint - 一个裸模块说明符,指向处理 pattern 中所表示路由的 .astro 页面或 .js/.ts 路由处理程序。
  • prerender - 一个布尔值,用于在 Astro 无法检测到你的 prerender 导出时进行设置。
injectRoute({
// Use Astro’s pattern syntax for dynamic routes.
pattern: '/subfolder/[dynamic]',
// Use relative path syntax for a local route.
entrypoint: './src/dynamic-page.astro',
// Use only if Astro can't detect your prerender export
prerender: false
});

对于设计用于安装在其他项目中的集成,请使用其包名来引用路由入口点。以下示例展示了一个发布到 npm 上的名为 @fancy/dashboard 的包注入了一个仪表盘路由

injectRoute({
pattern: '/fancy-dashboard',
entrypoint: '@fancy/dashboard/dashboard.astro'
});

当将你的包(在本例中为 @fancy/dashboard)发布到 npm 时,你必须在 package.json 中导出 dashboard.astro

package.json
{
"name": "@fancy/dashboard",
// ...
"exports": { "./dashboard.astro": "./dashboard.astro" }
}

添加于: astro@5.0.0

该函数也接受一个 URL 作为 entrypoint

injectRoute({
pattern: '/fancy-dashboard',
entrypoint: new URL('./dashboard.astro', import.meta.url)
});

类型: (stage: InjectedScriptStage, content: string) => void;

一个用于在每个页面上注入一段 JavaScript 内容字符串的回调函数。

stage 表示该脚本(content)应如何插入。一些阶段允许不经修改地插入脚本,而另一些阶段则允许在 Vite 的打包步骤中进行优化

  • "head-inline":注入到每个页面的 <head> 中的一个 script 标签内。不会被 Vite 优化或解析。

  • "before-hydration":在注水脚本运行之前,在客户端导入。会被 Vite 优化和解析。

  • "page":类似于 head-inline,但注入的代码段由 Vite 处理,并与页面上 Astro 组件内定义的任何其他 <script> 标签一起打包。该脚本将在最终页面输出中通过 <script type="module"> 加载,并由 Vite 进行优化和解析。

  • "page-ssr":在每个 Astro 页面组件的 frontmatter 中作为单独的模块导入。因为这个阶段会导入你的脚本,所以 Astro 全局变量不可用,你的脚本只会在 import 首次被求值时运行一次。

    page-ssr 阶段的主要用途是向每个页面注入一个 CSS import,以便由 Vite 进行优化和解析

    injectScript('page-ssr', 'import "global-styles.css";');

类型: () => URL;

添加于: astro@5.0.0

一个创建 <root>/.astro/integrations/<normalized_integration_name> 文件夹并返回其路径的函数。

它允许你拥有一个专用文件夹,从而避免与另一个集成或 Astro 本身发生冲突。这个目录是通过调用此函数创建的,因此可以直接向其中写入文件

my-integration.ts
import { writeFileSync } from 'node:fs'
const integration = {
name: 'my-integration',
hooks: {
'astro:config:setup': ({ createCodegenDir }) => {
const codegenDir = createCodegenDir()
writeFileSync(new URL('cache.json', codegenDir), '{}', 'utf-8')
}
}
}

添加于: astro@4.14.0

上一个钩子: astro:config:setup

下一个钩子: astro:routes:resolved

何时:astro build 中,打包开始之前。在 astro dev 中,在构建模块图时以及每当基于文件的路由发生变化(添加/删除/更新)时。

为何: 在构建时或请求时为路由设置选项,例如启用按需服务器渲染

'astro:route:setup'?: (options: {
route: RouteOptions;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: RouteOptions

一个包含 component 属性来识别路由的对象,以及以下附加值,允许你配置生成的路由:prerender

类型: string

添加于: astro@4.14.0

component 属性指示将在该路由上渲染的入口点。你可以在路由构建之前访问此值,以便为该页面配置按需服务器渲染。

类型: boolean
默认值: undefined

添加于: astro@4.14.0

prerender 属性用于为一个路由配置按需服务器渲染。如果路由文件包含一个明确的 export const prerender 值,该值将被用作默认值,而不是 undefined

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
integrations: [setPrerender()],
});
function setPrerender() {
return {
name: 'set-prerender',
hooks: {
'astro:route:setup': ({ route }) => {
if (route.component.endsWith('/blog/[slug].astro')) {
route.prerender = true;
}
},
},
};
}

如果在运行所有钩子后的最终值为 undefined,路由将根据 output 选项回退到预渲染默认值:static 模式下为预渲染,server 模式下为按需渲染。

添加于: astro@5.0.0

上一个钩子: astro:route:setup

下一个钩子: astro:config:done (仅在设置期间)

何时:astro dev 中,它也会在每次基于文件的路由发生更改(添加/删除/更新)时运行。

为何: 访问路由及其元数据

'astro:routes:resolved'?: (options: {
routes: IntegrationResolvedRoute[];
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: IntegrationResolvedRoute[]

所有路由及其关联元数据的列表。

用法示例

my-integration.mjs
const integration = () => {
return {
name: 'my-integration',
hooks: {
'astro:routes:resolved': ({ routes }) => {
const projectRoutes = routes.filter(r => r.origin === 'project').map(r => r.pattern)
console.log(projectRoutes)
},
}
}
}

上一个钩子: astro:routes:resolved

下一个钩子: 在“dev”模式下运行时为 astro:server:setup,或在生产构建期间为 astro:build:start

何时: 在 Astro 配置已解析并且其他集成已运行其 astro:config:setup 钩子之后。

为何: 获取最终配置以在其他钩子中使用。

'astro:config:done'?: (options: {
config: AstroConfig;
setAdapter: (adapter: AstroAdapter) => void;
injectTypes: (injectedType: InjectedType) => URL;
logger: AstroIntegrationLogger;
buildOutput: 'static' | 'server';
}) => void | Promise<void>;

类型: AstroConfig

用户提供的 Astro 配置的只读副本。它在其他集成运行之后被解析。

类型: (adapter: AstroAdapter) => void;

使集成成为一个适配器。请在适配器 API中阅读更多信息。

类型: (injectedType: { filename: string; content: string }) => URL

添加于: astro@4.14.0

允许你通过添加一个新的 *.d.ts 文件来向用户的项目中注入类型。

filename 属性将用于在 /.astro/integrations/<normalized_integration_name>/<normalized_filename>.d.ts 生成一个文件,并且必须以 ".d.ts" 结尾。

content 属性将创建文件的内容,并且必须是有效的 TypeScript。

此外,injectTypes() 会返回一个指向规范化路径的 URL,以便你以后可以覆盖其内容,或以任何你想要的方式操作它。

const path = injectTypes({
filename: "types.d.ts",
content: "declare module 'virtual:integration' {}"
})
console.log(path) // URL

类型: 'static' | 'server'

添加于: astro@5.0.0

允许你根据用户项目的输出来调整你的集成逻辑。

上一个钩子: astro:config:done

下一个钩子: astro:server:start

何时: 在“dev”模式下创建 Vite 服务器之后,但在 listen() 事件触发之前。 更多信息请参见 Vite 的 createServer API

为何: 更新 Vite 服务器选项和中间件,或启用对内容层刷新的支持。

'astro:server:setup'?: (options: {
server: vite.ViteDevServer;
logger: AstroIntegrationLogger;
toolbar: ReturnType<typeof getToolbarServerCommunicationHelpers>;
refreshContent: (options: {
loaders?: Array<string>;
context?: Record<string, any>;
}) => Promise<void>;
}) => void | Promise<void>;

类型: ViteDevServer

在“dev”模式下使用的 Vite 服务器的可变实例。例如,我们的 Partytown 集成用它来将 Partytown 服务器作为中间件注入。

export default {
name: 'partytown',
hooks: {
'astro:server:setup': ({ server }) => {
server.middlewares.use(
function middleware(req, res, next) {
// handle requests
}
);
}
}
}

类型: ReturnType<typeof getToolbarServerCommunicationHelpers>

添加于: astro@4.7.0

一个提供回调函数的对象,用于与开发工具栏进行交互

类型: <T>(event: string, callback: (data: T) => void) => void

一个函数,接受一个事件名称作为第一个参数,一个回调函数作为第二个参数。这允许你从开发工具栏应用接收与该事件相关联的数据的消息。

类型: (appId: string, callback: (data: Record<string, never>) => void) => void

当开发工具栏应用初始化时触发的函数。第一个参数是已初始化的应用的 ID。第二个参数是当应用初始化时要运行的回调函数。

类型: (appId: string, callback: (data: { state: boolean; }) => void) => void

当开发工具栏应用被打开或关闭时触发的函数。第一个参数是被切换的应用的 ID。第二个参数是一个回调函数,提供在应用切换时要执行的状态。

类型: <T>(event: string, payload: T) => void

一个向开发工具栏发送消息的函数,应用可以监听这个消息。它接受一个事件名称作为第一个参数,一个有效载荷作为第二个参数,有效载荷可以是任何可序列化的数据。

类型: (options: { loaders?: Array<string>; context?: Record<string, any>; }) => Promise<void>

添加于: astro@5.0.0

一个供集成在 astro dev 期间触发内容层更新的函数。例如,这可以用于在开发期间注册一个 webhook 端点,或者打开一个到 CMS 的套接字(socket)以监听变更。

默认情况下,refreshContent 将刷新所有内容集合。你可以选择性地传递一个 loaders 属性,它是一个加载器名称的数组。如果提供了该属性,则只有使用这些加载器的内容集合才会被刷新。例如,CMS 集成可以使用此属性仅刷新其自己的内容集合。

你也可以向加载器传递一个 context 对象。这可以用来传递任意数据,比如 webhook 的主体,或者来自 websocket 的事件。

my-integration.ts
{
name: 'my-integration',
hooks: {
'astro:server:setup': async ({ server, refreshContent }) => {
// Register a dev server webhook endpoint
server.middlewares.use('/_refresh', async (req, res) => {
if(req.method !== 'POST') {
res.statusCode = 405
res.end('Method Not Allowed');
return
}
let body = '';
req.on('data', chunk => {
body += chunk.toString();
});
req.on('end', async () => {
try {
const webhookBody = JSON.parse(body);
await refreshContent({
context: { webhookBody },
loaders: ['my-loader']
});
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Content refreshed successfully' }));
} catch (error) {
res.writeHead(500, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: 'Failed to refresh content: ' + error.message }));
}
});
});
}
}
}

然后加载器可以访问 refreshContextData 属性来获取 webhook 的主体。更多信息请参见 refreshContextData 属性。

上一个钩子: astro:server:setup

下一个钩子: astro:server:done

何时: 在服务器的 listen() 事件触发之后。

为何: 在指定地址拦截网络请求。如果你打算将此地址用于中间件,请考虑改用 astro:server:setup

'astro:server:start'?: (options: {
address: AddressInfo;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: AddressInfo

Node.js Net 模块提供的地址、族和端口号。

上一个钩子: astro:server:start

何时: 在开发服务器关闭之后。

为何: 运行你在 astro:server:setupastro:server:start 钩子中可能触发的任何清理事件。

'astro:server:done'?: (options: {
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

上一个钩子: astro:config:done

下一个钩子: astro:build:setup

何时:astro:config:done 事件之后,但在生产构建开始之前。

为何: 设置生产构建期间所需的任何全局对象或客户端。这也可以扩展适配器 API中的构建配置选项。

'astro:build:start'?: (options: {
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

上一个钩子: astro:build:start

下一个钩子: astro:build:ssr

何时:astro:build:start 钩子之后,构建前立即运行。

为何: 此时,构建的 Vite 配置已完全构建,这是你修改它的最后机会。例如,这对于覆盖某些默认值很有用。如果你不确定应该使用此钩子还是 astro:build:start,请改用 astro:build:start

'astro:build:setup'?: (options: {
vite: vite.InlineConfig;
pages: Map<string, PageBuildData>;
target: 'client' | 'server';
updateConfig: (newConfig: vite.InlineConfig) => void;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: InlineConfig

一个允许你访问构建中使用的 Vite 配置的对象。

如果你需要在集成中访问配置选项,这将非常有用

export default {
name: 'my-integration',
hooks: {
'astro:build:setup': ({ vite }) => {
const { publicDir, root } = vite;
},
}
}

类型: Map<string, PageBuildData>

一个 Map,其中键是页面列表,值是它们的构建数据。

这可以用来在路由匹配某个标准时执行操作

export default {
name: 'my-integration',
hooks: {
'astro:build:setup': ({ pages }) => {
pages.forEach((data) => {
if (data.route.pattern.test("/blog")) {
console.log(data.route.type);
}
});
},
}
}

类型: 'client' | 'server'

构建分为两个不同的阶段:clientserver。这个选项允许你确定当前的构建阶段。

这可以用来仅在特定阶段执行操作

export default {
name: 'my-integration',
hooks: {
'astro:build:setup': ({ target }) => {
if (target === "server") {
// do something in server build phase
}
},
}
}

类型: (newConfig: InlineConfig) => void

一个回调函数,用于更新构建中使用的 Vite 选项。你提供的任何配置都将与用户配置和其他集成的配置更新合并,所以你可以自由地省略一些键!

例如,这可以用于向用户的项目提供一个插件

import awesomeCssPlugin from 'awesome-css-vite-plugin';
export default {
name: 'my-integration',
hooks: {
'astro:build:setup': ({ updateConfig }) => {
updateConfig({
plugins: [awesomeCssPlugin()],
})
}
}
}

上一个钩子: astro:build:setup

下一个钩子: astro:build:generated

何时: 生产 SSR 构建完成之后。

为何: 访问 SSR 清单和发出的入口点映射。这在插件或集成中创建自定义 SSR 构建时很有用。

  • entryPoints 将页面路由映射到构建后发出的物理文件;
  • middlewareEntryPoint 是中间件文件的文件系统路径;
'astro:build:ssr'?: (options: {
manifest: SerializedSSRManifest;
entryPoints: Map<IntegrationRouteData, URL>;
middlewareEntryPoint: URL | undefined;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: SerializedSSRManifest

允许你通过访问 SSR 清单来创建自定义构建。

export default {
name: 'my-integration',
hooks: {
'astro:build:ssr': ({ manifest }) => {
const { i18n } = manifest;
if (i18n?.strategy === "domains-prefix-always") {
// do something
}
},
},
}

类型: Map<IntegrationRouteData, URL>

添加于: astro@2.7.0

一个已发出的入口点的 Map,以 IntegrationRouteData 为键,物理文件 URL 为值。

export default {
name: 'my-integration',
hooks: {
'astro:build:ssr': ({ entryPoints }) => {
entryPoints.forEach((url) => {
console.log(url.href);
});
},
},
}

类型: URL | undefined

添加于: astro@2.8.0

公开中间件文件路径。

export default {
name: 'my-integration',
hooks: {
'astro:build:ssr': ({ middlewareEntryPoint }) => {
if (middlewareEntryPoint) {
// do some operations if a middleware exist
}
},
},
}

添加于: astro@1.3.0

上一个钩子: astro:build:ssr

下一个钩子: astro:build:done

何时: 在静态生产构建完成生成路由和资产之后。

为何: 在构建产物被清理之前访问生成的路由和资产。这是一个非常不常见的用例。我们建议使用 astro:build:done,除非你真的需要在清理前访问生成的文件。

'astro:build:generated'?: (options: {
dir: URL;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: URL

一个指向构建输出目录的 URL 路径。请注意,如果你需要一个有效的绝对路径字符串,你应该使用 Node 的内置 fileURLToPath 工具。

import { fileURLToPath } from 'node:url';
export default {
name: 'my-integration',
hooks: {
'astro:build:generated': ({ dir }) => {
const outFile = fileURLToPath(new URL('./my-integration.json', dir));
}
}
}

上一个钩子: astro:build:generated

何时: 在生产构建(SSG 或 SSR)完成之后。

为何: 访问生成的路由和资产以进行扩展(例如,将内容复制到生成的 /assets 目录中)。如果你计划转换生成的资产,我们建议探索 Vite 插件 API 并通过 astro:config:setup 进行配置。

'astro:build:done'?: (options: {
pages: { pathname: string }[];
dir: URL;
/** @deprecated Use the `assets` map and the new `astro:routes:resolved` hook */
routes: IntegrationRouteData[];
assets: Map<string, URL[]>;
logger: AstroIntegrationLogger;
}) => void | Promise<void>;

类型: URL

一个指向构建输出目录的 URL 路径。请注意,如果你需要一个有效的绝对路径字符串,你应该使用 Node 的内置 fileURLToPath 工具。

import { writeFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
export default function myIntegration() {
return {
hooks: {
'astro:build:done': async ({ dir }) => {
const metadata = await getIntegrationMetadata();
// Use fileURLToPath to get a valid, cross-platform absolute path string
const outFile = fileURLToPath(new URL('./my-integration.json', dir));
await writeFile(outFile, JSON.stringify(metadata));
}
}
}
}

类型: IntegrationRouteData[]

所有生成的路由及其关联元数据的列表。

你可以在下面参考完整的 IntegrationRouteData 类型,但最常见的属性是

  • component - 相对于项目根目录的输入文件路径
  • pathname - 输出文件 URL(对于使用 [dynamic][...spread] 参数的路由为 undefined)

类型: Map<string, URL[]>

添加于: astro@5.0.0

包含输出文件路径的 URL,按 IntegrationResolvedRoutepattern 属性分组。

类型: { pathname: string }[]

所有已生成页面的列表。它是一个只有一个属性的对象。

  • pathname - 页面的最终路径。

通过全局增强扩展 IntegrationHooks 接口,可以为集成添加自定义钩子。

declare global {
namespace Astro {
export interface IntegrationHook {
'your:hook': (params: YourHookParameters) => Promise<void>
}
}
}

Astro 保留了 astro: 前缀用于未来的内置钩子。在命名你的自定义钩子时,请选择一个不同的前缀。

Astro 日志记录器的一个实例,可用于写入日志。此日志记录器使用通过 CLI 配置的相同日志级别

可用方法,用于向终端写入信息

  • logger.info("消息");
  • logger.warn("消息");
  • logger.error("消息");
  • logger.debug("消息");

所有消息都会前置一个标签,该标签的值与集成的名称相同。

integration.ts
import type { AstroIntegration } from "astro";
export function formatIntegration(): AstroIntegration {
return {
name: "astro-format",
hooks: {
"astro:build:done": ({ logger }) => {
// do something
logger.info("Integration ready.");
}
}
}
}

上面的例子会记录一条包含所提供的 info 消息的日志

终端窗口
[astro-format] Integration ready.

要使用不同的标签记录某些消息,请使用 .fork 方法来指定一个不同于默认 name 的备用标签

integration.ts
import type { AstroIntegration } from "astro";
export function formatIntegration(): AstroIntegration {
return {
name: "astro-format",
hooks: {
"astro:config:done": ({ logger }) => {
// do something
logger.info("Integration ready.");
},
"astro:build:done": ({ logger }) => {
const buildLogger = logger.fork("astro-format/build");
// do something
buildLogger.info("Build finished.")
}
}
}
}

上面的示例默认会生成带有 [astro-format] 的日志,在指定时则会生成带有 [astro-format/build] 的日志

终端窗口
[astro-format] Integration ready.
[astro-format/build] Build finished.

你可以通过将钩子的名称传递给 HookParameters 工具类型来获取钩子参数的类型。在下面的示例中,一个函数的 options 参数的类型被设置为与 astro:config:setup 钩子的参数相匹配

import type { HookParameters } from 'astro';
function mySetup(options: HookParameters<'astro:config:setup'>) {
options.updateConfig({ /* ... */ });
}
interface IntegrationResolvedRoute {
pattern: RouteData['route'];
patternRegex: RouteData['pattern'];
entrypoint: RouteData['component'];
isPrerendered: RouteData['prerender'];
redirectRoute?: IntegrationResolvedRoute;
generate: (data?: any) => string;
params: string[];
pathname?: string;
segments: RoutePart[][];
type: RouteType;
redirect?: RedirectConfig;
origin: 'internal' | 'external' | 'project';
}

类型: string

允许你根据路径识别路由类型。以下是一些路径及与其关联的模式的示例

  • src/pages/index.astro 对应 /
  • src/pages/blog/[...slug].astro 对应 /blog/[...slug]
  • src/pages/site/[blog]/[...slug].astro 对应 /site/[blog]/[...slug]

类型: RegExp

允许你访问一个用于将输入 URL 与请求路由进行匹配的正则表达式。

例如,对于路径 [fruit]/about.astro,其正则表达式将是 /^\/([^/]+?)\/about\/?$/。使用 pattern.test("banana/about") 将返回 true

类型: string

源组件的 URL 路径名。

类型: boolean

确定路由是否使用按需渲染。对于配置了以下选项的项目,该值为 true

  • output: 'static',且路由未导出 const prerender = true
  • output: 'server',且路由导出了 const prerender = false

类型: IntegrationResolvedRoute | undefined

IntegrationResolvedRoute.type 的值为 redirect 时,该值将是重定向目标的 IntegrationResolvedRoute。否则,该值为 undefined。

类型: (data?: any) => string

一个函数,它接收路由的可选参数,将它们与路由模式进行插值,并返回路由的路径名。

例如,对于像 /blog/[...id].astro 这样的路由,generate 函数可以返回

console.log(generate({ id: 'presentation' })) // will log `/blog/presentation`

类型: string[]

允许你访问路由的 params。例如,当一个项目使用以下动态路由 /pages/[lang]/[...slug].astro 时,其值将是 ['lang', '...slug']

类型: string | undefined

对于常规路由,该值将是此路由提供服务的 URL 路径名。当项目使用动态路由(即 [dynamic][...spread])时,pathname 将为 undefined。

类型: RoutePart[][]

允许你访问带有附加元数据的路由 params。每个对象包含以下属性

  • contentparam 的名称,
  • dynamic:路由是否为动态路由,
  • spread:动态路由是否使用扩展语法。

例如,以下路由 /pages/[blog]/[...slug].astro 将输出以下 segments

[
[ { content: 'pages', dynamic: false, spread: false } ],
[ { content: 'blog', dynamic: true, spread: false } ],
[ { content: '...slug', dynamic: true, spread: true } ]
]

类型: RouteType

允许你识别路由的类型。可能的值有

  • page:存在于文件系统中的路由,通常是一个 Astro 组件
  • endpoint:存在于文件系统中的路由,通常是暴露端点方法的 JS 文件
  • redirect:指向文件系统中另一个路由的路由
  • fallback:一个不存在于文件系统中的路由,需要通过其他方式处理,通常是中间件

类型: RedirectConfig | undefined

允许你访问要重定向到的路由。这可以是一个字符串,也可以是一个包含状态码及其目标信息的对象。

类型: 'internal' | 'external' | 'project'

确定一个路由是来自 Astro 核心(internal)、一个集成(external)还是用户的项目(project)。

这是 RouteData 的一个精简版本,用于集成中。

interface IntegrationRouteData {
type: RouteType;
component: string;
pathname?: string;
pattern: RegExp;
params: string[];
segments: { content: string; dynamic: boolean; spread: boolean; }[][];
generate: (data?: any) => string;
prerender: boolean;
distURL?: URL[];
redirect?: RedirectConfig;
redirectRoute?: IntegrationRouteData;
}

类型: RouteType

允许你识别路由的类型。其值可以是

  • page:存在于文件系统中的路由,通常是一个 Astro 组件
  • endpoint:存在于文件系统中的路由,通常是暴露端点方法的 JS 文件
  • redirect:一个指向文件系统中另一个路由的路由
  • fallback:一个不存在于文件系统中的路由,需要通过其他方式处理,通常是中间件

类型: string

允许你访问源组件的 URL 路径名。

类型: string | undefined

对于常规路由,该值将是此路由提供服务的 URL 路径名。当项目使用动态路由(即 [dynamic][...spread])时,pathname 将为 undefined。

类型: RegExp

允许你访问一个用于将输入 URL 与请求路由进行匹配的正则表达式。

例如,对于路径 [fruit]/about.astro,其正则表达式将是 /^\/([^/]+?)\/about\/?$/。使用 pattern.test("banana/about") 将返回 true

类型: string[]

允许你访问路由的 params。例如,当一个项目使用以下动态路由 /pages/[lang]/[...slug].astro 时,其值将是 ['lang', '...slug']

类型: { content: string; dynamic: boolean; spread: boolean; }[][]

允许你访问带有附加元数据的路由 params。每个对象包含以下属性

  • contentparam
  • dynamic:路由是否为动态路由,
  • spread:动态路由是否使用扩展语法。

例如,以下路由 /pages/[lang]/index.astro 将输出 segments [[ { content: 'lang', dynamic: true, spread: false } ]]

类型: (data?: any) => string

一个函数,它接收路由的可选参数,将它们与路由模式进行插值,并返回路由的路径名。

例如,对于像 /blog/[...id].astro 这样的路由,generate 函数可以返回

console.log(generate({ id: 'presentation' })) // will log `/blog/presentation`

类型: boolean

确定路由是否被预渲染。

类型: URL[] | undefined

此路由生成的物理文件的路径。当路由预渲染时,该值为 undefined 或空数组。

类型: RedirectConfig | undefined

允许你访问要重定向到的路由。这可以是一个字符串,也可以是一个包含状态码及其目标信息的对象。

类型: IntegrationRouteData | undefined

RouteData.type 的值为 redirect 时,该值将包含要重定向到的路由的 IntegrationRouteData。否则,该值为 undefined。

astro add 命令允许用户轻松地将集成和适配器添加到他们的项目中。如果你希望你的集成能通过此工具安装,请astro-integration 添加到你的 package.json 文件的 keywords 字段中

{
"name": "example",
"keywords": ["astro-integration"],
}

一旦你将你的集成发布到 npm,运行 astro add example 将会安装你的包以及在 package.json 中指定的任何同级依赖。这也会将你的集成应用到用户的 astro.config.* 文件中,如下所示

astro.config.mjs
import { defineConfig } from 'astro/config';
import example from 'example';
export default defineConfig({
integrations: [example()],
})

所有集成都按照它们配置的顺序运行。例如,对于用户 astro.config.* 文件中的数组 [react(), svelte()]react 将在 svelte 之前运行。

理想情况下,你的集成应该能以任何顺序运行。如果这不可能,我们建议你在文档中说明你的集成需要在用户的 integrations 配置数组中排在最前或最后。

一个集成也可以写成多个较小集成的集合。我们称这些集合为预设(presets)。预设不是创建一个返回单个集成对象的工厂函数,而是返回一个集成对象的数组。这对于用多个集成构建复杂功能非常有用。

integrations: [
// Example: where examplePreset() returns: [integrationOne, integrationTwo, ...etc]
examplePreset()
]
贡献 社区 赞助