图像服务 API
astro:assets 旨在使任何图像优化服务都能轻松地在 Astro 上构建服务。
什么是图像服务?
Section titled “什么是图像服务?”Astro 提供两种类型的图像服务:本地和外部。
- 本地服务在构建静态站点时直接处理图像转换,或者在运行时同时处理开发模式和按需渲染中的图像转换。这些通常是围绕 Sharp、ImageMagick 或 Squoosh 等库的封装。在开发模式和按需渲染的生产路径中,本地服务使用 API 端点进行转换。
- 外部服务指向 URL,可以添加对 Cloudinary、Vercel 或任何符合 RIAPI 的服务器等服务的支持。
使用图像服务 API 构建
Section titled “使用图像服务 API 构建”服务定义采用导出默认对象的形式,具有各种必需的方法(“钩子”)。
外部服务提供一个 getURL(),它指向输出 <img> 标记的 src。
本地服务为开发模式和按需渲染提供 transform() 方法来对图像执行转换,并提供 getURL() 和 parseURL() 方法来使用端点。
两种类型的服务都可以提供 getHTMLAttributes() 来确定输出 <img> 的其他属性,并提供 validateOptions() 来验证和增强传递的选项。
外部服务指向一个远程 URL,用作最终 <img> 标记的 src 属性。该远程 URL 负责下载、转换和返回图像。
import type { ExternalImageService, ImageTransform, AstroConfig } from "astro";
const service: ExternalImageService = { validateOptions(options: ImageTransform, imageConfig: AstroConfig['image']) { const serviceConfig = imageConfig.service.config; // 强制用户设置最大宽度。 if (options.width && options.width > serviceConfig.maxWidth) { console.warn(`Image width ${options.width} exceeds max width ${serviceConfig.maxWidth}. Falling back to max width.`); options.width = serviceConfig.maxWidth; }
return options; }, getURL(options, imageConfig) { return `https://mysupercdn.com/${options.src}?q=${options.quality}&w=${options.width}&h=${options.height}`; }, getHTMLAttributes(options, imageConfig) { const { src, format, quality, ...attributes } = options; return { ...attributes, loading: options.loading ?? 'lazy', decoding: options.decoding ?? 'async', }; }};
export default service;要创建自己的本地服务,可以指向内置端点(/_image),或者你还可以创建自己的端点来调用服务的方法。
import type { ImageTransform, LocalImageService, AstroConfig } from "astro";
const service: LocalImageService<AstroConfig["image"]> = { getURL(options: ImageTransform, imageConfig: AstroConfig['image']) { const searchParams = new URLSearchParams(); searchParams.append('href', typeof options.src === "string" ? options.src : options.src.src); options.width && searchParams.append('w', options.width.toString()); options.height && searchParams.append('h', options.height.toString()); options.quality && searchParams.append('q', options.quality.toString()); options.format && searchParams.append('f', options.format); return `/my_custom_endpoint_that_transforms_images?${searchParams}`; // 或者使用内置端点,它将调用你的 parseURL 和 transform 函数: // return `/_image?${searchParams}`; }, parseURL(url: URL, imageConfig) { const params = url.searchParams; return { src: params.get('href')!, width: params.has('w') ? parseInt(params.get('w')!) : undefined, height: params.has('h') ? parseInt(params.get('h')!) : undefined, format: params.get('f'), quality: params.get('q'), }; }, async transform(inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig) { const { buffer } = await mySuperLibraryThatEncodesImages(options); return { data: buffer, format: options.format, }; }, getHTMLAttributes(options, imageConfig) { let targetWidth = options.width; let targetHeight = options.height; if (typeof options.src === "object") { const aspectRatio = options.src.width / options.src.height;
if (targetHeight && !targetWidth) { targetWidth = Math.round(targetHeight * aspectRatio); } else if (targetWidth && !targetHeight) { targetHeight = Math.round(targetWidth / aspectRatio); } }
const { src, width, height, format, quality, ...attributes } = options;
return { ...attributes, width: targetWidth, height: targetHeight, loading: attributes.loading ?? 'lazy', decoding: attributes.decoding ?? 'async', }; }, propertiesToHash: ['src', 'width', 'height', 'format', 'quality'],};export default service;在构建静态站点和预渲染路由时,<Image /> 和 getImage(options) 都会调用 transform() 函数。它们分别通过组件属性或 options 参数传递选项。转换后的图像将构建到 dist/_astro 文件夹中。它们的文件名将包含传递给 propertiesToHash 属性的哈希值。此属性是可选的,默认为 ['src', 'width', 'height', 'format', 'quality']。如果你的自定义图像服务有更多可以更改生成图像的选项,请将它们添加到数组中。
在开发模式和使用适配器进行按需渲染时,Astro 并不提前知道哪些图像需要优化。Astro 使用 GET 端点(默认情况下为 /_image )在运行时处理图像。 <Image /> 和 getImage() 将它们的选项传递给 getURL(),后者将返回端点 URL。然后,端点调用 parseURL() 并将结果属性传递给 transform()。
getConfiguredImageService 和 imageConfig
Section titled “getConfiguredImageService 和 imageConfig”如果你将自己的端点实现为 Astro 端点,则可以使用 getConfiguredImageService 和 imageConfig 来调用服务的 parseURL 和 transform 方法并提供服务的配置对象。
要访问图像服务配置(image.service.config),你可以使用 imageConfig.service.config。
import type { APIRoute } from "astro";import { getConfiguredImageService, imageConfig } from 'astro:assets';
export const GET: APIRoute = async ({ request }) => { const imageService = await getConfiguredImageService();
const imageTransform = imageService.parseURL(new URL(request.url), imageConfig); // ... 从 imageTransform.src 获取图像并将其存储在 inputBuffer 中 const { data, format } = await imageService.transform(inputBuffer, imageTransform, imageConfig); return new Response(data, { status: 200, headers: { 'Content-Type': mime.getType(format) || '' } } );}请参阅内置端点 了解完整示例。
getURL()
Section titled “getURL()”类型: (options: ImageTransform, imageConfig: AstroConfig[‘image’]) => string | Promise<string>
astro@2.1.0
本地和外部服务所需
对于本地服务,该钩子返回生成图像的端点的 URL(在按需渲染和开发模式下)。在构建期间它不可用。 getURL() 指向的本地端点可以调用 parseURL() 和 transform()。
对于外部服务,该钩子返回图像的最终 URL。
对于这两种类型的服务,options 是用户作为 <Image /> 组件的属性或 getImage() 选项传递的属性。
parseURL()
Section titled “parseURL()”类型: (url: URL, imageConfig: AstroConfig[‘image’]) => { src: string, [key: string]: any } | undefined | Promise<{ src: string, [key: string]: any }> | Promise<undefined>
astro@2.1.0
本地服务所需;外部服务不可用
该钩子通过 getURL() 将生成的 URL 解析成一个对象,该对象具有可供 transform 使用的不同属性(在按需渲染和开发模式下)。在构建期间它不可用。
transform()
Section titled “transform()”类型: (inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig: AstroConfig[‘image’]) => Promise<{ data: Uint8Array; format: ImageOutputFormat }>
astro@2.1.0
仅本地服务需要;外部服务不可用
该钩子转换并返回图像,并在构建过程中被调用以创建最终的资源文件。
你必须返回 format 以确保在按需渲染和开发模式下向用户提供正确的 MIME 类型。
getHTMLAttributes()
Section titled “getHTMLAttributes()”类型: (options: ImageTransform, imageConfig: AstroConfig[‘image’] ) => Record<string, any> | Promise<Record<string, any>>
astro@2.1.0
本地和外部服务可选
该钩子根据用户传递的参数 (options) 返回用于将图像呈现为 HTML 的所有附加属性。
getSrcSet()
Section titled “getSrcSet()”类型: (options: ImageTransform, imageConfig: AstroConfig[‘image’] ) => UnresolvedSrcSetValue[] | Promise<UnresolvedSrcSetValue[]>
astro@3.3.0
对于本地和外部服务而言是可选的。
这个钩子函数会生成指定图像的多个变体,例如,在 <img> 或 <picture> 的 source 上生成 srcset 属性。
该钩子函数返回一个包含以下属性的对象数组:
export type UnresolvedSrcSetValue = { transform: ImageTransform; descriptor?: string; attributes?: Record<string, any>;};validateOptions()
Section titled “validateOptions()”类型: (options: ImageTransform, imageConfig: AstroConfig[‘image’] ) => ImageTransform | Promise<ImageTransform>
astro@2.1.4
本地和外部服务可选
该钩子允许你验证和增强用户传递的选项。对于设置默认选项或告诉用户参数必传来说,这非常有用。
查看 Astro 的内置服务中是如何使用 validateOptions() 的 。
在 astro.config.mjs 中配置要使用的图像服务。配置采用以下形式:
import { defineConfig } from "astro/config";
export default defineConfig({ image: { service: { entrypoint: "your-entrypoint", // 'astro/assets/services/sharp' | string, config: { // 特定的服务配置,可选。 } } },});为自定义图像服务属性定义类型
Section titled “为自定义图像服务属性定义类型”
添加于:
astro@5.16.6
新
如果你的图像服务在 Astro 的 <Image> 组件、<Picture> 组件或 getImage() 函数中支持额外的属性,你可以通过扩展 Astro.CustomImageProps 接口来为这些属性添加类型。
例如,要添加你的图像服务支持的自定义 blur 属性:
declare namespace Astro { interface CustomImageProps { /** 对图像应用指定半径的高斯模糊。 */ blur?: number; }}你可以通过将图像服务打包为 Astro 集成 并使用 injectTypes() 辅助函数来向用户暴露这些类型。
然后,用户将能够获得自定义属性的自动补全和类型安全:
<Image blur="yes" src={myPhoto} />// ^^^^^^^^^^// Type 'string' is not assignable to type 'number | undefined'.