Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/content/docs/en/reference/cache-provider-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -371,10 +371,45 @@ The incoming `request` is passed as a second argument so a provider can read the

<p>

**Type:** <code>(context: \{ request: Request; url: URL; waitUntil?: (promise: Promise\<unknown\>) => void \}, next: <a href="/en/reference/modules/astro-middleware/#middlewarenext">MiddlewareNext</a>) => Promise\<Response\></code>
**Type:** <code>(context: \{ request: Request; url: URL; waitUntil?: (promise: Promise\<unknown\>) => void; logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a> \}, next: <a href="/en/reference/modules/astro-middleware/#middlewarenext">MiddlewareNext</a>) => Promise\<Response\></code>
</p>

Intercepts requests to implement runtime caching. The `context` includes a `waitUntil()` function (when available in the runtime) for background work such as stale-while-revalidate.
An optional hook that intercepts a request before Astro generates the matching route. It receives a `context` object as its first argument and a callback to call the `next()` middleware in the chain.

The `context` contains the following properties:
- `request`: the incoming [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object.
- `url`: a normalized [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) derived from the request.
- `waitUntil()`: when available in the runtime, a function to define a background work, such as revalidating a stale cache entry.
- `logger`: since Astro v7.3.0, a [`logger`](/en/reference/api-reference/#logger) instance that respects the [configured logging destination](/en/reference/configuration-reference/#logger-options)

The following example implements a minimal `onRequest()` hook that logs each URL added to the cache:

```ts title="my-provider/runtime.ts" ins={7-17}
import type { CacheProviderFactory } from 'astro';

const factory: CacheProviderFactory = (config) => {
const cache = new Map();
return {
name: 'my-cache-provider',
async onRequest({ request, url, waitUntil, logger }, next) {
if (request.method !== 'GET') return next();

const cached = cache.get(url);
if (cached) return cached;

const response = await next();
cache.set(url, response.clone());
logger.info(`Cached response for ${url}.`);
return response;
},
async invalidate() {
// ...
},
};
};

export default factory;
```

#### `CacheProvider.invalidate()`

Expand Down
62 changes: 38 additions & 24 deletions src/content/docs/en/reference/image-service-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,21 @@ An external service points to a remote URL to be used as the `src` attribute of
import type { ExternalImageService, ImageTransform, AstroConfig } from "astro";

const service: ExternalImageService = {
validateOptions(options: ImageTransform, imageConfig: AstroConfig['image']) {
validateOptions(options: ImageTransform, imageConfig: AstroConfig['image'], logger) {
const serviceConfig = imageConfig.service.config;

// Enforce the user set max width.
if (options.width && options.width > serviceConfig.maxWidth) {
console.warn(`Image width ${options.width} exceeds max width ${serviceConfig.maxWidth}. Falling back to max width.`);
logger.warn(`Image width ${options.width} exceeds max width ${serviceConfig.maxWidth}. Falling back to max width.`);
options.width = serviceConfig.maxWidth;
}

return options;
},
getURL(options, imageConfig) {
getURL(options, imageConfig, logger) {
return `https://mysupercdn.com/${options.src}?q=${options.quality}&w=${options.width}&h=${options.height}`;
},
getHTMLAttributes(options, imageConfig) {
getHTMLAttributes(options, imageConfig, logger) {
const { src, format, quality, ...attributes } = options;
return {
...attributes,
Expand All @@ -68,7 +68,7 @@ import type { ImageTransform, LocalImageService, AstroConfig } from "astro";
import { mySuperLibraryThatEncodesImages } from "@example/my-super-library";

const service: LocalImageService<AstroConfig["image"]> = {
getURL(options: ImageTransform, imageConfig) {
getURL(options: ImageTransform, imageConfig, logger) {
const searchParams = new URLSearchParams();
searchParams.append('href', typeof options.src === "string" ? options.src : options.src.src);
options.width && searchParams.append('w', options.width.toString());
Expand All @@ -79,7 +79,7 @@ const service: LocalImageService<AstroConfig["image"]> = {
// Or use the built-in endpoint, which will call your parseURL and transform functions:
// return `/_image?${searchParams}`;
},
parseURL(url: URL, imageConfig) {
parseURL(url: URL, imageConfig, logger) {
const params = url.searchParams;
return {
src: params.get('href')!,
Expand All @@ -89,14 +89,14 @@ const service: LocalImageService<AstroConfig["image"]> = {
quality: params.get('q'),
};
},
async transform(inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig) {
async transform(inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig, logger) {
const { buffer } = await mySuperLibraryThatEncodesImages(options);
return {
data: buffer,
format: options.format,
};
},
getHTMLAttributes(options, imageConfig) {
getHTMLAttributes(options, imageConfig, logger) {
let targetWidth = options.width;
let targetHeight = options.height;
if (typeof options.src === "object") {
Expand Down Expand Up @@ -141,7 +141,7 @@ import { getConfiguredImageService, imageConfig } from "astro:assets";
import * as mime from "mrmime";
import { getImageBuffer } from "./my-custom-image-fetcher.js";

export const GET: APIRoute = async ({ request }) => {
export const GET: APIRoute = async ({ request, logger }) => {
const imageService = await getConfiguredImageService();

if (!isLocalService(imageService)) {
Expand All @@ -154,6 +154,7 @@ export const GET: APIRoute = async ({ request }) => {
const imageTransform = await imageService.parseURL(
new URL(request.url),
imageConfig,
logger,
);

if (!imageTransform) {
Expand All @@ -166,6 +167,7 @@ export const GET: APIRoute = async ({ request }) => {
inputBuffer,
imageTransform,
imageConfig,
logger,
);
return new Response(new Uint8Array(data), {
status: 200,
Expand All @@ -185,7 +187,7 @@ export const GET: APIRoute = async ({ request }) => {

<p>

**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>) => string | Promise\<string\></code><br />
**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => string | Promise\<string\></code><br />
<Since v="2.1.0" />
</p>

Expand All @@ -195,57 +197,69 @@ For local services, this hook returns the URL of the endpoint that generates you

For external services, this hook returns the final URL of the image.

For both types of services, `options` are the properties passed by the user as attributes of the `<Image />` component or as options to `getImage()`.
For both types of services, `options` are the properties passed by the user as attributes of the `<Image />` component or as options to `getImage()`. This hook also receives the image configuration and, since Astro v7.3.0, a logger.

### `parseURL()`

<p>

**Type:** <code>(url: URL, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>) => \{ src: string, [key: string]: any \} | undefined | Promise\<\{ src: string, [key: string]: any \}\> | Promise\<undefined\></code><br />
**Type:** <code>(url: URL, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => \{ src: string, [key: string]: any \} | undefined | Promise\<\{ src: string, [key: string]: any \}\> | Promise\<undefined\></code><br />
<Since v="2.1.0" />
</p>

**Required for local services only; unavailable for external services**

This hook parses the generated URLs by `getURL()` back into an object with the different properties to be used by `transform` (for on-demand rendering and in dev mode). It is unused during build.
This hook parses the generated URLs by `getURL()` back into an object with the different properties to be used by `transform` (for on-demand rendering and in dev mode). It is unused during build. This receives three parameters: the URL to parse, the image configuration and, since Astro v7.3.0, a logger.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could be wrong (not an English expert...) but I think "This" after "It" is confusing? And, maybe this requires a bit of reorganization to make the whole thing flow better? Something bothers me with this one.

Maybe:

Suggested change
This hook parses the generated URLs by `getURL()` back into an object with the different properties to be used by `transform` (for on-demand rendering and in dev mode). It is unused during build. This receives three parameters: the URL to parse, the image configuration and, since Astro v7.3.0, a logger.
This hook parses the generated URLs by `getURL()` back into an object with the different properties to be used by `transform`. This receives three parameters: the URL to parse, the image configuration and, since Astro v7.3.0, a logger.
This hook is used only for on-demand rendering and in development mode. It is unused during build.


### `transform()`

<p>

**Type:** <code>(inputBuffer: Uint8Array, options: \{ src: string, [key: string]: any \}, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>) => Promise\<\{ data: Uint8Array; format: <a href="/en/reference/modules/astro-assets/#imageoutputformat">ImageOutputFormat</a> \}\></code><br />
**Type:** <code>(inputBuffer: Uint8Array, options: \{ src: string, [key: string]: any \}, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => Promise\<\{ data: Uint8Array; format: <a href="/en/reference/modules/astro-assets/#imageoutputformat">ImageOutputFormat</a> \}\></code><br />
<Since v="2.1.0" />
</p>

**Required for local services only; unavailable for external services**

This hook transforms and returns the image and is called during the build to create the final asset files.
This hook transforms and returns the image and is called during the build to create the final asset files. This receives four parameters: the input image, an options object, the image configuration and, since Astro v7.3.0, a logger.

You must return a `format` to ensure that the proper MIME type is served to users for on-demand rendering and development mode.
You must return a `format` to ensure that the proper MIME type is served to users for on-demand rendering and development mode:

```ts
import type { LocalImageService } from 'astro';

const service: LocalImageService = {
// ...
async transform(inputBuffer, transform, imageConfig, logger) {
logger.warn(`Could not optimize "${transform.src}". Passing it through unchanged.`);
return { data: inputBuffer, format: 'png' };
},
};
```

### `getHTMLAttributes()`

<p>

**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a> ) => Record\<string, any\> | Promise\<Record\<string, any\>\></code><br />
**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => Record\<string, any\> | Promise\<Record\<string, any\>\></code><br />
<Since v="2.1.0" />
</p>

**Optional for both local and external services**

This hook returns all additional attributes used to render the image as HTML, based on the parameters passed by the user (`options`).
This hook returns all additional attributes used to render the image as HTML, based on the parameters passed by the user (`options`). It also receives the image configuration and, since Astro v7.3.0, a logger.

### `getSrcSet()`

<p>

**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a> ) => UnresolvedSrcSetValue[] | Promise\<UnresolvedSrcSetValue[]\></code><br />
**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => UnresolvedSrcSetValue[] | Promise\<UnresolvedSrcSetValue[]\></code><br />
<Since v="3.3.0" />
</p>

**Optional for both local and external services.**

This hook generates multiple variants of the specified image, for example, to generate a `srcset` attribute on an `<img>` or `<picture>`'s `source`.
This hook generates multiple variants of the specified image, for example, to generate a `srcset` attribute on an `<img>` or `<picture>`'s `source`. This receives three parameters: an options object, the image configuration and, since Astro v7.3.0, a logger.

This hook returns an array of objects with the following properties:

Expand All @@ -261,27 +275,27 @@ export type UnresolvedSrcSetValue = {

<p>

**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a> ) => ImageTransform | Promise\<ImageTransform\></code>
**Type:** <code>(options: <a href="/en/reference/modules/astro-assets/#imagetransform">ImageTransform</a>, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => ImageTransform | Promise\<ImageTransform\></code>
<Since v="2.1.4" />
</p>

**Optional for both local and external services**

This hook allows you to validate and augment the options passed by the user. This is useful for setting default options, or telling the user that a parameter is required.
This hook allows you to validate and augment the options passed by the user. This is useful for setting default options, or telling the user that a parameter is required. It also receives the image configuration and, since Astro v7.3.0, a logger you can use to warn the user about invalid options.

[See how `validateOptions()` is used in Astro built-in services](https://github.com/withastro/astro/blob/0ab6bad7dffd413c975ab00e545f8bc150f6a92f/packages/astro/src/assets/services/service.ts#L124).

### `getRemoteSize()`

<p>

**Type:** <code>(url: string, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a> ) => Omit\<<a href="/en/reference/modules/astro-assets/#imagemetadata-1">ImageMetadata</a>, 'src' | 'fsPath'\> | Promise\<Omit\<<a href="/en/reference/modules/astro-assets/#imagemetadata-1">ImageMetadata</a>, 'src' | 'fsPath'\>\></code>
**Type:** <code>(url: string, imageConfig: <a href="/en/reference/configuration-reference/#image-options">AstroConfig['image']</a>, logger: <a href="/en/reference/logger-reference/#astroruntimelogger">AstroRuntimeLogger</a>) => Omit\<<a href="/en/reference/modules/astro-assets/#imagemetadata-1">ImageMetadata</a>, 'src' | 'fsPath'\> | Promise\<Omit\<<a href="/en/reference/modules/astro-assets/#imagemetadata-1">ImageMetadata</a>, 'src' | 'fsPath'\>\></code>
<Since v="6.0.0" />
</p>

**Optional for both local and external services**

This hook allows you to extend the behavior of [`inferRemoteSize()`](/en/reference/modules/astro-assets/#inferremotesize). This is useful for reducing network traffic by caching images, or when you can predict image information from the image URL.
This hook allows you to extend the behavior of [`inferRemoteSize()`](/en/reference/modules/astro-assets/#inferremotesize). This is useful for reducing network traffic by caching images, or when you can predict image information from the image URL. This receives three parameters: the image URL, the image configuration and, since Astro v7.3.0, a logger.

## User configuration

Expand Down
Loading