跳转到内容

Astro 容器 API (实验性)

新增于: astro@4.9.0

容器 API 允许你独立地渲染 Astro 组件。

这个实验性的服务端 API 解锁了多种潜在的未来用途,但目前其范围仅限于在 vite 环境(如 vitest)中对 测试 .astro 组件的输出

它还允许你手动加载渲染脚本,以便在按需渲染的页面或其他 vite 之外的“外壳”环境(例如,在 PHP 或 Elixir 应用程序内部)中创建容器。

该 API 允许你创建一个新的容器,并渲染一个 Astro 组件,返回一个字符串或一个Response

此 API 是实验性的,可能会发生破坏性更改,即使是在次要版本或补丁版本中。请查阅 Astro 更新日志以了解发生的更改。此页面将始终更新为最新版 Astro 的最新信息。

创建一个新的容器实例。

import { experimental_AstroContainer } from "astro/container";
const container = await experimental_AstroContainer.create();

它接受一个包含以下选项的对象

export type AstroContainerOptions = {
streaming?: boolean;
renderers?: AddServerRenderer[];
};
export type AddServerRenderer =
| {
renderer: NamedSSRLoadedRendererValue;
name: never;
}
| {
renderer: SSRLoadedRendererValue;
name: string;
};

类型: boolean

启用使用HTML 流式传输来渲染组件。

类型: AddServerRenderer[]

组件所需的已加载的客户端渲染器列表。如果你的 .astro 组件使用官方 Astro 集成(例如 React、Vue 等)渲染任何UI 框架组件或 MDX,请使用此选项。

对于静态应用程序,或容器不在运行时调用的情况(例如,使用 vitest 进行测试),渲染器可以通过容器 API 自动添加。

对于按需渲染的应用程序,或容器在运行时或在其他“外壳”(例如 PHP、Ruby、Java 等)内部调用的情况,必须手动导入渲染器。

对于每个官方 Astro 集成,导入并使用 getContainerRenderer() 辅助函数来暴露其客户端和服务器渲染脚本。这些脚本可用于 @astrojs/react@astrojs/preact@astrojs/solid-js@astrojs/svelte@astrojs/vue@astrojs/mdx

对于 @astrojs npm 组织之外的渲染器包,请在其文档中查找 getContainerRenderer() 或提供的类似函数。

当使用 vitevitest、Astro 集成等)时,渲染器会从虚拟模块 astro:container 中使用 loadRenderers() 函数加载。

以下示例提供了渲染一个同时渲染 React 组件和 Svelte 组件的 Astro 组件所需的对象

import { getContainerRenderer as reactContainerRenderer } from "@astrojs/react";
import { getContainerRenderer as svelteContainerRenderer } from "@astrojs/svelte";
import { loadRenderers } from "astro:container";
const renderers = await loadRenderers([reactContainerRenderer(), svelteContainerRenderer()]);
const container = await experimental_AstroContainer.create({
renderers
})
const result = await container.renderToString(ReactWrapper);

当容器在运行时或在其他“外壳”内部调用时,astro:container 虚拟模块的辅助函数不可用。你必须手动导入必要的服务器和客户端渲染器,并使用 addServerRendereraddClientRenderer 将它们存储在容器内部。

构建项目需要服务器渲染器,并且必须为使用的每个框架将其存储在容器中。此外,使用client:* 指令激活任何客户端组件也需要客户端渲染器。

每个框架只需要一个导入语句。导入一个渲染器会使服务器和客户端渲染器都可用于你的容器。但是,服务器渲染器必须在客户端渲染器之前添加到你的容器中。这允许你的整个容器首先渲染,然后再激活任何交互式组件。

以下示例手动导入必要的服务器渲染器,以便能够显示静态 Vue 组件和 .mdx 页面。它还为交互式 React 组件添加了服务器和客户端渲染器。

import reactRenderer from "@astrojs/react/server.js";
import vueRenderer from "@astrojs/vue/server.js";
import mdxRenderer from "@astrojs/mdx/server.js";
const container = await experimental_AstroContainer.create();
container.addServerRenderer({renderer: vueRenderer});
container.addServerRenderer({renderer: mdxRenderer});
container.addServerRenderer({ renderer: reactRenderer });
container.addClientRenderer({ name: "@astrojs/react", entrypoint: "@astrojs/react/client.js" });

此函数在容器内渲染指定的组件。它以一个 Astro 组件作为参数,并返回一个表示该 Astro 组件渲染的 HTML/内容的字符串。

import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();
const result = await container.renderToString(Card);

在底层,此函数调用 renderToResponse 并调用 Response.text()

它还接受一个对象作为第二个参数,该对象可以包含多个选项

它渲染一个组件,并返回一个 Response 对象。

import { experimental_AstroContainer } from "astro/container";
import Card from "../src/components/Card.astro";
const container = await experimental_AstroContainer.create();
const result = await container.renderToResponse(Card);

它还接受一个对象作为第二个参数,该对象可以包含多个选项

renderToResponserenderToString 都接受一个对象作为它们的第二个参数

export type ContainerRenderOptions = {
slots?: Record<string, any>;
props?: Record<string, unknown>;
request?: Request;
params?: Record<string, string | undefined>;
locals?: App.Locals;
routeType?: "page" | "endpoint";
};

这些可选值可以传递给渲染函数,以便提供 Astro 组件正确渲染所需的附加信息。

类型: Record<string, any>;

一个用于传递内容以通过 <slots> 渲染的选项。

如果你的 Astro 组件渲染一个默认插槽,请传递一个以 default 为键的对象

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
slots: { default: "Some value" }
});

如果你的组件渲染具名插槽,请使用插槽名称作为对象键

---
---
<div>
<slot name="header" />
<slot name="footer" />
</div>
import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
slots: {
header: "Header content",
footer: "Footer"
}
});

你还可以级联渲染组件

---
---
<div>
<slot name="header" />
<slot name="footer" />
</div>
import Card from "../src/components/Card.astro";
import CardHeader from "../src/components/CardHeader.astro";
import CardFooter from "../src/components/CardFooter.astro";
const result = await container.renderToString(Card, {
slots: {
header: await container.renderToString(CardHeader),
footer: await container.renderToString(CardFooter)
}
});

类型: Record<string, unknown>

一个用于为 Astro 组件传递属性的选项。

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
props: { name: "Hello, world!" }
});
---
// For TypeScript support
interface Props {
name: string;
};
const { name } = Astro.props;
---
<div>
{name}
</div>

类型: Request

一个用于传递 Request 对象的选项,其中包含组件将渲染的路径/URL 信息。

当你的组件需要读取像 Astro.urlAstro.request 这样的信息时,请使用此选项。

你还可以注入可能的请求头或 cookie。

import Card from "../src/components/Card.astro";
const result = await container.renderToString(Card, {
request: new Request("https://example.com/blog", {
headers: {
"x-some-secret-header": "test-value"
}
})
});

类型: Record<string, string | undefined>;

一个用于将路径参数信息传递给负责生成动态路由的 Astro 组件的对象。

当你的组件需要 Astro.params 的值以动态生成单个路由时,请使用此选项。

---
const { locale, slug } = Astro.params;
---
<div></div>
import LocaleSlug from "../src/components/[locale]/[slug].astro";
const result = await container.renderToString(LocaleSlug, {
params: {
locale: "en",
slug: "getting-started"
}
});

类型: App.Locals

一个用于从 Astro.locals 传递信息以渲染组件的选项。

当你的组件需要请求生命周期中存储的信息(例如登录状态)才能渲染时,请使用此选项。

---
const { checkAuth } = Astro.locals;
const isAuthenticated = checkAuth();
---
{isAuthenticated ? <span>You're in</span> : <span>You're out</span> }
import Card from "../src/components/Card.astro";
test("User is in", async () => {
const result = await container.renderToString(Card, {
locals: {
checkAuth() { return true; }
}
});
// assert result contains "You're in"
});
test("User is out", async () => {
const result = await container.renderToString(Card, {
locals: {
checkAuth() { return false; }
}
});
// assert result contains "You're out"
});

类型: "page" | "endpoint"

使用 renderToResponse 时可用的一个选项,用于指定你正在渲染一个端点

container.renderToString(Endpoint, { routeType: "endpoint" });
import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, {
routeType: "endpoint"
});
const json = await response.json();

要在 POSTPATCH 等方法上测试你的端点,请使用 request 选项来调用正确的函数

export function GET() {}
// need to test this
export function POST() {}
import * as Endpoint from "../src/pages/api/endpoint.js";
const response = await container.renderToResponse(Endpoint, {
routeType: "endpoint",
request: new Request("https://example.com", {
method: "POST" // Specify POST method for testing
})
});
const json = await response.json();

类型: boolean
默认值: true

添加于: astro@4.16.6

容器 API 是否像渲染页面局部片段一样渲染组件。当你渲染 components.boolean 时,这通常是你想要的行为,这样你就可以在没有完整页面外壳的情况下渲染组件。

要将组件渲染为完整的 Astro 页面,包括 <!DOCTYPE html>,你可以通过将 partial 设置为 false 来选择退出此行为

import Blog from "../src/pages/Blog.astro";
const result = await container.renderToString(Card, {
partial: false
});
console.log(result) // includes `<!DOCTYPE html>` at the beginning of the HTML
贡献 社区 赞助