diff --git a/docs/api-reference/next/image.md b/docs/api-reference/next/image.md index 2e75c38e14e72..f398f0bdac264 100644 --- a/docs/api-reference/next/image.md +++ b/docs/api-reference/next/image.md @@ -497,6 +497,18 @@ The default [loader](#loader) will automatically bypass Image Optimization for a Auto-detection for animated files is best-effort and supports GIF, APNG, and WebP. If you want to explicitly bypass Image Optimization for a given animated image, use the [unoptimized](#unoptimized) prop. +### Remote Cache Control + +By default, when an image came from a remote server the `Cache-Control` header is set as `public, max-age=0, must-revalidate`. To disable cache revalidation and change this behavior you can rewrite the header value by configuring `remoteCacheControl` option. + +```js +module.exports = { + images: { + remoteCacheControl: 'public, max-age=315360000', + }, +} +``` + ## Related For an overview of the Image component features and usage guidelines, see: diff --git a/packages/next/server/image-optimizer.ts b/packages/next/server/image-optimizer.ts index 8a84ce7a8bb58..7d9c14d69b125 100644 --- a/packages/next/server/image-optimizer.ts +++ b/packages/next/server/image-optimizer.ts @@ -565,14 +565,13 @@ function setResponseHeaders( contentType: string | null, isStatic: boolean, xCache: XCacheHeader, - contentSecurityPolicy: string + contentSecurityPolicy: string, + remoteCacheControl: string ) { res.setHeader('Vary', 'Accept') res.setHeader( 'Cache-Control', - isStatic - ? 'public, max-age=315360000, immutable' - : `public, max-age=0, must-revalidate` + isStatic ? 'public, max-age=315360000, immutable' : remoteCacheControl ) if (sendEtagResponse(req, res, etag)) { // already called res.end() so we're finished @@ -606,7 +605,8 @@ export function sendResponse( buffer: Buffer, isStatic: boolean, xCache: XCacheHeader, - contentSecurityPolicy: string + contentSecurityPolicy: string, + remoteCacheControl: string ) { const contentType = getContentType(extension) const etag = getHash([buffer]) @@ -618,7 +618,8 @@ export function sendResponse( contentType, isStatic, xCache, - contentSecurityPolicy + contentSecurityPolicy, + remoteCacheControl ) if (!result.finished) { res.end(buffer) diff --git a/packages/next/server/next-server.ts b/packages/next/server/next-server.ts index d7fa9a4d5f8c7..9e788161e9e55 100644 --- a/packages/next/server/next-server.ts +++ b/packages/next/server/next-server.ts @@ -263,7 +263,8 @@ export default class NextNodeServer extends BaseServer { cacheEntry.value.buffer, paramsResult.isStatic, cacheEntry.isMiss ? 'MISS' : cacheEntry.isStale ? 'STALE' : 'HIT', - imagesConfig.contentSecurityPolicy + imagesConfig.contentSecurityPolicy, + imagesConfig.remoteCacheControl ) } catch (err) { if (err instanceof ImageError) { diff --git a/packages/next/shared/lib/image-config.ts b/packages/next/shared/lib/image-config.ts index 001745447c1aa..b37e86da455ee 100644 --- a/packages/next/shared/lib/image-config.ts +++ b/packages/next/shared/lib/image-config.ts @@ -45,6 +45,9 @@ export type ImageConfigComplete = { /** @see [Dangerously Allow SVG](https://nextjs.org/docs/api-reference/next/image#dangerously-allow-svg) */ contentSecurityPolicy: string + + /** @see [Remote Cache Control](https://nextjs.org/docs/api-reference/next/image#remote-cache-control) */ + remoteCacheControl: string } export type ImageConfig = Partial @@ -60,4 +63,5 @@ export const imageConfigDefault: ImageConfigComplete = { formats: ['image/webp'], dangerouslyAllowSVG: false, contentSecurityPolicy: `script-src 'none'; frame-src 'none'; sandbox;`, + remoteCacheControl: `public, max-age=0, must-revalidate`, }