Skip to content
Merged
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
35 changes: 35 additions & 0 deletions .changeset/stable-route-caching.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
'astro': minor
---

Stabilizes route caching, removing the `experimental.cache` and `experimental.routeRules` flags and replacing them with the top-level `cache` and `routeRules` configuration options.

Route caching, introduced experimentally in v6.0.0, is now stable. It gives you a platform-agnostic way to cache responses from [on-demand rendered](https://docs.astro.build/en/guides/on-demand-rendering/) pages and endpoints, based on standard HTTP caching semantics.

Update your config to move `cache` and `routeRules` out of the `experimental` block:

```diff
// astro.config.mjs
import { defineConfig, memoryCache } from 'astro/config';

export default defineConfig({
- experimental: {
- cache: {
- provider: memoryCache(),
- },
- routeRules: {
- '/blog/[...path]': { maxAge: 300, swr: 60 },
- },
- },
+ cache: {
+ provider: memoryCache(),
+ },
+ routeRules: {
+ '/blog/[...path]': { maxAge: 300, swr: 60 },
+ },
});
```

Set caching directives in your routes with `Astro.cache` (in `.astro` pages) or `context.cache` (in API routes and middleware), and Astro translates them into the appropriate headers or runtime behavior depending on your configured cache provider. You can also define cache rules for routes declaratively in your config using `routeRules`, without modifying route code.

See the [route caching guide](https://docs.astro.build/en/guides/caching/) for more information.
5 changes: 1 addition & 4 deletions packages/astro/src/core/build/plugins/plugin-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,7 @@ async function buildManifest(
allowedDomains: settings.config.security?.allowedDomains,
key: encodedKey,
sessionConfig: sessionConfigToManifest(settings.config.session),
cacheConfig: cacheConfigToManifest(
settings.config.experimental?.cache,
settings.config.experimental?.routeRules,
),
cacheConfig: cacheConfigToManifest(settings.config.cache, settings.config.routeRules),
csp,
image: {
objectFit: settings.config.image.objectFit,
Expand Down
13 changes: 7 additions & 6 deletions packages/astro/src/core/cache/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ const CacheOptionsSchema = z.object({
});

/**
* Cache provider configuration (experimental.cache).
* Provider only - routes are configured via experimental.routeRules.
* Cache provider configuration (`cache`).
* Provider only - routes are configured via `routeRules`.
*/
export const CacheSchema = z.object({
provider: CacheProviderConfigSchema.optional(),
Expand All @@ -26,14 +26,15 @@ export const CacheSchema = z.object({
const RouteRuleSchema = CacheOptionsSchema;

/**
* Route rules configuration (experimental.routeRules).
* Maps glob patterns to route rules.
* Route rules configuration (`routeRules`).
* Maps route patterns to route rules. Patterns use the same `[param]` and
* `[...rest]` syntax as file-based routing; glob wildcards (`*`) are not supported.
*
* Example:
* ```ts
* routeRules: {
* '/api/*': { swr: 600 },
* '/products/*': { maxAge: 3600, tags: ['products'] },
* '/api/[...path]': { swr: 600 },
* '/products/[...slug]': { maxAge: 3600, tags: ['products'] },
* }
* ```
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/cache/runtime/noop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class DisabledAstroCache implements CacheLike {
hasWarned = true;
this.#logger?.warn(
'cache',
'`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `experimental.cache` to enable caching.',
'`cache.set()` was called but caching is not enabled. Configure a cache provider in your Astro config under `cache` to enable caching.',
);
}
}
Expand Down
8 changes: 4 additions & 4 deletions packages/astro/src/core/cache/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ export function normalizeRouteRuleCacheOptions(
}

/**
* Extract cache routes from experimental.routeRules config.
* Extract cache routes from the `routeRules` config.
*/
export function extractCacheRoutesFromRouteRules(
routeRules: AstroConfig['experimental']['routeRules'],
routeRules: AstroConfig['routeRules'],
): Record<string, CacheOptions> | undefined {
if (!routeRules) return undefined;

Expand All @@ -62,8 +62,8 @@ export function extractCacheRoutesFromRouteRules(
}

export function cacheConfigToManifest(
cacheConfig: AstroConfig['experimental']['cache'],
routeRulesConfig: AstroConfig['experimental']['routeRules'],
cacheConfig: AstroConfig['cache'],
routeRulesConfig: AstroConfig['routeRules'],
): SSRManifestCache | undefined {
if (!cacheConfig?.provider) {
return undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/cache/vite-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export function vitePluginCacheProvider({
}: {
settings: AstroSettings;
}): VitePlugin | undefined {
const providerConfig = settings.config.experimental?.cache?.provider;
const providerConfig = settings.config.cache?.provider;
if (!providerConfig) {
return;
}
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/config/schemas/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@ export const AstroConfigSchema = z.object({
})
.optional(),
fonts: z.array(FontFamilySchema).optional(),
cache: CacheSchema.optional(),
routeRules: RouteRulesSchema.optional(),
experimental: z
.strictObject({
clientPrerender: z
Expand All @@ -575,8 +577,6 @@ export const AstroConfigSchema = z.object({
.optional()
.default(ASTRO_CONFIG_DEFAULTS.experimental.chromeDevtoolsWorkspace),
svgOptimizer: SvgOptimizerSchema.optional(),
cache: CacheSchema.optional(),
routeRules: RouteRulesSchema.optional(),
})
.prefault({}),
legacy: z
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/errors/errors-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2237,8 +2237,8 @@ export const CacheNotEnabled = {
name: 'CacheNotEnabled',
title: 'Cache is not enabled.',
message:
'`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `experimental.cache`.',
hint: 'Use an adapter that provides a default cache provider, or set one explicitly: `experimental: { cache: { provider: "..." } }`. See https://docs.astro.build/en/reference/experimental-flags/route-caching/.',
'`Astro.cache` is not available because the cache feature is not enabled. To use caching, configure a cache provider in your Astro config under `cache`.',
hint: 'Use an adapter that provides a default cache provider, or set one explicitly: `cache: { provider: "..." }`. See https://docs.astro.build/en/guides/caching/.',
} satisfies ErrorData;

/**
Expand Down
7 changes: 2 additions & 5 deletions packages/astro/src/manifest/serialized.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export function serializedManifestPlugin({
const serialized = await createSerializedManifest(settings, await getEncodedKey());
manifestData = JSON.stringify(serialized);
}
const hasCacheConfig = !!settings.config.experimental?.cache?.provider;
const hasCacheConfig = !!settings.config.cache?.provider;
const cacheProviderLine = hasCacheConfig
? `cacheProvider: () => import('${VIRTUAL_CACHE_PROVIDER_ID}'),`
: '';
Expand Down Expand Up @@ -217,10 +217,7 @@ async function createSerializedManifest(
encodedKey ??
(await encodeKey(hasEnvironmentKey() ? await getEnvironmentKey() : await createKey())),
sessionConfig: sessionConfigToManifest(settings.config.session),
cacheConfig: cacheConfigToManifest(
settings.config.experimental?.cache,
settings.config.experimental?.routeRules,
),
cacheConfig: cacheConfigToManifest(settings.config.cache, settings.config.routeRules),
csp,
image: {
objectFit: settings.config.image.objectFit,
Expand Down
160 changes: 81 additions & 79 deletions packages/astro/src/types/public/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2902,6 +2902,87 @@ export interface AstroUserConfig<
[K in keyof TFontProviders]: FontFamily<TFontProviders[K]>;
};

/**
* @docs
* @kind heading
* @name cache
* @type {object}
* @default `undefined`
* @version 7.0.0
* @description
*
* Enables route caching for SSR responses. Provides a platform-agnostic API
* for caching rendered pages and API responses, with pluggable providers
* that adapters can configure automatically.
*
* ```js
* // astro.config.mjs
* import { memoryCache } from 'astro/config';
*
* {
* cache: {
* provider: memoryCache(),
* },
* routeRules: {
* '/blog/[...path]': { maxAge: 300, swr: 60 },
* },
* }
* ```
*
* Use `Astro.cache.set()` in routes and `context.cache.set()` in middleware
* or API routes to control caching per-request.
*/
cache?: {
/**
* @docs
* @name cache.provider
* @type {CacheProviderConfig}
* @version 7.0.0
* @description
*
* A provider that controls how responses are cached.
*
* Use the provider's config function to get type-safe configuration:
*
* ```js
* import { defineConfig, memoryCache } from 'astro/config';
*
* export default defineConfig({
* cache: { provider: memoryCache() },
* });
* ```
*/
provider?: CacheProviderConfig;
};

/**
* @docs
* @kind heading
* @name routeRules
* @type {Record<string, RouteRule>}
* @default `undefined`
* @version 7.0.0
* @description
*
* Route patterns mapped to cache rules.
* Uses the same `[param]` and `[...rest]` syntax as [file-based routing](/en/guides/routing/#route-priority-order).
* Use a `[...rest]` parameter to match a group of routes:
*
* ```js
* // astro.config.mjs
* import { memoryCache } from 'astro/config';
*
* {
* cache: { provider: memoryCache() },
* routeRules: {
* '/api/[...path]': { swr: 600 },
* '/products/[...slug]': { maxAge: 3600, tags: ['products'] },
* },
* }
* ```
*/
routeRules?: RouteRules;

/**
*
* @kind heading
Expand Down Expand Up @@ -3049,85 +3130,6 @@ export interface AstroUserConfig<
* See the [experimental SVG optimization docs](https://docs.astro.build/en/reference/experimental-flags/svg-optimization/) for more information.
*/
svgOptimizer?: SvgOptimizer;

/**
* @name experimental.cache
* @type {object}
* @default `undefined`
* @description
*
* Enables route caching for SSR responses. Provides a platform-agnostic API
* for caching rendered pages and API responses, with pluggable providers
* that adapters can configure automatically.
*
* ```js
* // astro.config.mjs
* import { memoryCache } from 'astro/config';
*
* {
* experimental: {
* cache: {
* provider: memoryCache(),
* },
* routeRules: {
* '/blog/[...path]': { maxAge: 300, swr: 60 },
* },
* },
* }
* ```
*
* Use `Astro.cache.set()` in routes and `context.cache.set()` in middleware
* or API routes to control caching per-request.
*/
cache?: {
/**
* @name experimental.cache.provider
* @type {import('../../core/cache/types.js').CacheProviderConfig}
* @description
*
* The cache provider. Adapters typically set a default, but you can
* override it with your own.
*
* Use the provider's config function to get type-safe configuration:
*
* ```js
* import { memoryCache } from 'astro/config';
*
* export default defineConfig({
* experimental: {
* cache: { provider: memoryCache() },
* },
* });
* ```
*/
provider?: CacheProviderConfig;
};

/**
* @name experimental.routeRules
* @type {Record<string, RouteRule>}
* @default `undefined`
* @description
*
* Route patterns mapped to cache rules.
* Uses the same `[param]` and `[...rest]` syntax as file-based routing.
*
* ```js
* // astro.config.mjs
* import { memoryCache } from 'astro/config';
*
* {
* experimental: {
* cache: { provider: memoryCache() },
* routeRules: {
* '/api/*': { swr: 600 },
* '/products/*': { maxAge: 3600, tags: ['products'] },
* },
* },
* }
* ```
*/
routeRules?: RouteRules;
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@
import { defineConfig, memoryCache } from 'astro/config';

export default defineConfig({
experimental: {
cache: {
provider: memoryCache({
query: {
include: ['page', 'sort'],
},
}),
},
cache: {
provider: memoryCache({
query: {
include: ['page', 'sort'],
},
}),
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { defineConfig, memoryCache } from 'astro/config';
// Uses default query config — tracking params (utm_*, fbclid, etc.) are
// excluded automatically, and params are sorted.
export default defineConfig({
experimental: {
cache: {
provider: memoryCache(),
},
cache: {
provider: memoryCache(),
},
});
Loading
Loading