Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(assets): Allow customising the route of the image endpoint #11908

Merged
merged 10 commits into from
Sep 10, 2024
9 changes: 6 additions & 3 deletions packages/astro/src/assets/endpoint/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import type { AstroSettings } from '../../types/astro.js';

export function injectImageEndpoint(settings: AstroSettings, mode: 'dev' | 'build') {
const endpointEntrypoint =
settings.config.image.endpoint ??
(mode === 'dev' ? 'astro/assets/endpoint/node' : 'astro/assets/endpoint/generic');
settings.config.image.endpoint.entrypoint === 'default'
? mode === 'dev'
? 'astro/assets/endpoint/node'
: 'astro/assets/endpoint/generic'
: settings.config.image.endpoint.entrypoint;

settings.injectedRoutes.push({
pattern: '/_image',
pattern: settings.config.image.endpoint.route,
entrypoint: endpointEntrypoint,
prerender: false,
});
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/assets/services/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ interface SharedServiceProps<T extends Record<string, any> = Record<string, any>
/**
* Return the URL to the endpoint or URL your images are generated from.
*
* For a local service, your service should expose an endpoint handling the image requests, or use Astro's at `/_image`.
* For a local service, your service should expose an endpoint handling the image requests, or use Astro's which by default, is located at `/_image`.
*
* For external services, this should point to the URL your images are coming from, for instance, `/_vercel/image`
*
Expand Down Expand Up @@ -343,7 +343,7 @@ export const baseService: Omit<LocalImageService, 'transform'> = {
options[key] && searchParams.append(param, options[key].toString());
});

const imageEndpoint = joinPaths(import.meta.env.BASE_URL, '/_image');
const imageEndpoint = joinPaths(import.meta.env.BASE_URL, imageConfig.endpoint.route);
return `${imageEndpoint}?${searchParams}`;
},
parseURL(url) {
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default function assets({
};

return [
// Expose the components and different utilities from `astro:assets` and handle serving images from `/_image` in dev
// Expose the components and different utilities from `astro:assets`
{
name: 'astro:assets',
async resolveId(id) {
Expand Down
8 changes: 7 additions & 1 deletion packages/astro/src/core/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const ASTRO_CONFIG_DEFAULTS = {
inlineStylesheets: 'auto',
},
image: {
endpoint: { entrypoint: 'default', route: '/_image' },
service: { entrypoint: 'astro/assets/services/sharp', config: {} },
},
devToolbar: {
Expand Down Expand Up @@ -241,7 +242,12 @@ export const AstroConfigSchema = z.object({
.optional(),
image: z
.object({
endpoint: z.string().optional(),
endpoint: z
.object({
route: z.literal('/_image').or(z.string()).default('/_image'),
entrypoint: z.literal('default').or(z.string()).default('default'),
Princesseuh marked this conversation as resolved.
Show resolved Hide resolved
})
.default(ASTRO_CONFIG_DEFAULTS.image.endpoint),
service: z
.object({
entrypoint: z
Expand Down
16 changes: 10 additions & 6 deletions packages/astro/src/types/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -905,24 +905,28 @@ export interface AstroUserConfig {
/**
* @docs
* @name image.endpoint
* @type {string}
* @type {{route: '/_image' | (string & {}), entrypoint: 'default' | (string & {})}}
* @default `undefined`
* @version 3.1.0
* @description
* Set the endpoint to use for image optimization in dev and SSR. Set to `undefined` to use the default endpoint.
*
* The endpoint will always be injected at `/_image`.
* Set the endpoint to use for image optimization in dev and SSR.
*
* ```js
* {
* image: {
* // Example: Use a custom image endpoint
* endpoint: './src/image-endpoint.ts',
* endpoint: {
* route: '/_image',
* entrypoint: 'src/my_endpoint.ts',
* },
* },
* }
* ```
*/
endpoint?: string;
endpoint?: {
route: '/_image' | (string & {});
entrypoint: 'default' | (string & {});
};

/**
* @docs
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/test/core-image.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ describe('astro:image', () => {
customEndpointFixture = await loadFixture({
root: './fixtures/core-image/',
image: {
endpoint: './src/custom-endpoint.ts',
endpoint: { entrypoint: './src/custom-endpoint.ts' },
service: testImageService({ foo: 'bar' }),
domains: ['avatars.githubusercontent.com'],
},
Expand Down Expand Up @@ -1145,7 +1145,7 @@ describe('astro:image', () => {
},
adapter: testAdapter(),
image: {
endpoint: 'astro/assets/endpoint/node',
endpoint: { entrypoint: 'astro/assets/endpoint/node' },
service: testImageService(),
},
});
Expand Down
Loading