コンテンツにスキップ

画像サービスAPI

astro:assets は、どんな画像最適化サービスでも簡単にAstro上に構築できるように設計されています。

Astroには、ローカルと外部の2種類の画像サービスがあります。

  • ローカルサービスは、静的サイトのビルド時や、開発モードとSSRの実行時に直接画像を変換します。多くの場合、Sharp、ImageMagick、Squooshなどのライブラリをラップしたものです。開発モードとSSRでは、APIエンドポイントを使って画像変換を行います。
  • 外部サービスは、URLを指定して使います。Cloudinary、Vercel、その他のRIAPIに準拠したサーバーなどのサービスをサポートできます。

サービスの定義は、エクスポートされたデフォルトオブジェクトの形を取り、いくつかの必須メソッド(「フック」と呼ばれます)を含みます。

外部サービスは、最終的な <img> タグの src を指定する getURL() を提供します。

ローカルサービスは、画像変換を行う transform() メソッドと、開発モードとSSRでエンドポイントを使うための getURL()parseURL() メソッドを提供します。

どちらのタイプのサービスも、出力される <img> の他の属性を決定する getHTMLAttributes() や、渡されたオプションを検証・拡張する validateOptions() を提供できます。

外部サービスは、最終的な <img> タグの src 属性として使われるリモートURLを指定します。このリモート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 > serviceConfig.maxWidth) {
console.warn(`画像幅${options.width}は最大幅${serviceConfig.maxWidth}を超えています。最大幅にフォールバックします。`);
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;

独自のローカルサービスを作るには、Astroに組み込まれているエンドポイント/_image)を使うか、サービスのメソッドを呼び出せる独自のエンドポイントを新たに作成することができます。

import type { LocalImageService, AstroConfig } from "astro";
const service: LocalImageService = {
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) {
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'),
};
},
transform(buffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig): { data: Uint8Array, format: OutputFormat } {
const { buffer } = 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',
};
}
};
export default service;

静的サイトや事前レンダリングされたルートをビルドする際、<Image />getImage(options) はどちらも transform() 関数を呼び出します。オプションは、それぞれコンポーネントの属性や options 引数を通じて渡されます。変換された画像は dist/_astro フォルダに出力されます。

開発モードやSSRモードでは、Astroはどの画像を最適化すべきか事前にわかりません。そのため、実行時に画像を処理するためのGETエンドポイント(デフォルトは /_image)を使います。<Image />getImage() は、それぞれのオプションを getURL() に渡してエンドポイントのURLを取得します。その後、エンドポイントが parseURL() を呼び出し、得られたプロパティを transform() に渡します。

Astroのエンドポイントとして独自のエンドポイントを実装する場合、getConfiguredImageServiceimageConfig を使って、サービスの parseURLtransform メソッドを呼び出し、画像の設定を提供できます。

画像サービスの設定(image.service.config)にアクセスするには、imageConfig.service.config を使います。

src/api/my_custom_endpoint_that_transforms_images.ts
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) || ''
}
}
);
}

詳しい例は、Astroに組み込まれているエンドポイントのコードをご覧ください。

ローカルサービスと外部サービスの両方に必須

getURL(options: ImageTransform, imageConfig: AstroConfig['image']): string

ローカルサービスの場合、このフックは画像を生成するエンドポイントのURLを返します(SSRと開発モードで使用)。ビルド時には使われません。getURL()が指すローカルエンドポイントは、parseURL()transform()の両方を呼び出すことがあります。

外部サービスの場合、このフックは画像の最終的なURLを返します。

どちらのサービスタイプでも、optionsはユーザーが<Image />コンポーネントの属性やgetImage()のオプションとして渡したプロパティです。

export type ImageTransform = {
// ESM imported images | remote/public image paths
src: ImageMetadata | string;
width?: number;
height?: number;
widths?: number[] | undefined;
densities?: (number | `${number}x`)[] | undefined;
quality?: ImageQuality;
format?: OutputFormat;
alt?: string;
[key: string]: any;
};

ローカルサービスのみ必須(外部サービスでは使用不可)

parseURL(url: URL, imageConfig: AstroConfig['image']): { src: string, [key: string]: any}

このフックは、getURL()で生成されたURLを、transformで使用するためのプロパティを持つオブジェクトに変換します(SSRと開発モードで使用)。ビルド時には使われません。

ローカルサービスのみ必須(外部サービスでは使用不可)

transform(buffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig: AstroConfig['image']): { data: Uint8Array, format: OutputFormat }

このフックは画像を変換し、最終的なアセットファイルを作成するためにビルド時に呼び出されます。

SSRと開発モードでは、適切なMIMEタイプをユーザーに提供するためにformatを返す必要があります。

ローカルサービスと外部サービスの両方でオプション

getHTMLAttributes(options: ImageTransform, imageConfig: AstroConfig['image']): Record<string, any>

このフックは、ユーザーが渡したパラメータ(options)に基づいて、画像をHTMLとしてレンダリングする際に使用される追加の属性をすべて返します。

追加: astro@3.3.0

ローカルサービスと外部サービスの両方でオプション

getSrcSet?: (options: ImageTransform, imageConfig: AstroConfig['image']): SrcSetValue[] | Promise<SrcSetValue[]>;

このフックは、指定された画像の複数のバリエーションを生成します。例えば、<img><picture>srcset属性を生成するのに使います。

このフックは、特定のプロパティを持つオブジェクトの配列を返します。

export type SrcSetValue = {
transform: ImageTransform;
descriptor?: string;
attributes?: Record<string, any>;
};

ローカルサービスと外部サービスの両方でオプション

validateOptions(options: ImageTransform, imageConfig: AstroConfig['image']): ImageTransform

このフックを使うと、ユーザーが渡したオプションを検証したり拡張したりできます。デフォルトのオプションを設定したり、必須のパラメータをユーザーに知らせたりするのに便利です。

Astroの組み込みサービスでvalidateOptions()がどう使われているかはこちらを参照してください

使用する画像サービスはastro.config.mjsで設定します。設定は以下の形式になります。

astro.config.mjs
import { defineConfig } from "astro/config";
export default defineConfig({
image: {
service: {
entrypoint: "your-entrypoint", // 'astro/assets/services/squoosh' | 'astro/assets/services/sharp' | string,
config: {
// ... サービス固有の設定。任意。
}
}
},
});
貢献する

どんなことを?

GitHub Issueを作成

チームに素早く問題を報告できます。

コミュニティ