From 1af38247b32136cb95a9c7010da8e285dff031e5 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 4 Aug 2026 08:44:34 -0400 Subject: [PATCH 1/5] Add docs for experimental incremental static builds --- astro.sidebar.ts | 1 + .../experimental-flags/incremental-build.mdx | 86 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 src/content/docs/en/reference/experimental-flags/incremental-build.mdx diff --git a/astro.sidebar.ts b/astro.sidebar.ts index 620f9ce7edf80..82405ff4c5ffc 100644 --- a/astro.sidebar.ts +++ b/astro.sidebar.ts @@ -164,6 +164,7 @@ export const sidebar = [ 'reference/experimental-flags/chrome-devtools-workspace', 'reference/experimental-flags/svg-optimization', 'reference/experimental-flags/collection-storage', + 'reference/experimental-flags/incremental-build', ], }), 'reference/legacy-flags', diff --git a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx new file mode 100644 index 0000000000000..d8337515b5a3e --- /dev/null +++ b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx @@ -0,0 +1,86 @@ +--- +title: Experimental incremental static builds +sidebar: + label: Incremental builds +i18nReady: true +--- + +import Since from '~/components/Since.astro' + +

+ +**Type:** `boolean`
+**Default:** `false`
+ +

+ +This experimental feature reuses the output of a previous build so that unchanged pages are not rendered again. + +When enabled, Astro can skip a static page generated by [`getStaticPaths()`](/en/reference/routing-reference/#getstaticpaths) if both its data and the code it depends on are unchanged since the last build. You mark a page's data by returning a `cacheKey` for it, and Astro tracks the code by hashing the page's module dependency graph. When both match the previous build, Astro copies the earlier output instead of rendering the page again. + +On large sites where most pages change infrequently, this can reduce build times significantly because rendering is skipped for pages that would produce identical output. + +To enable incremental builds, add the flag to your Astro config: + +```js title="astro.config.mjs" ins={5} +import { defineConfig } from "astro/config"; + +export default defineConfig({ + experimental: { + incrementalBuild: true, + }, +}); +``` + +## Providing a cache key + +Only pages returned from `getStaticPaths()` that include a `cacheKey` can be skipped. Every other page, including static pages that do not use `getStaticPaths()`, is rendered on each build. + +A `cacheKey` is a string that identifies the data used to render a page. Choose a value that changes whenever the page's content changes, such as a content hash, a version number, or an updated timestamp from your data source. Astro re-renders the page when its `cacheKey` differs from the previous build, and reuses the previous output when it is the same. + +```astro title="src/pages/blog/[slug].astro" +--- +export async function getStaticPaths() { + const posts = await fetchPosts(); + + return posts.map((post) => ({ + params: { slug: post.slug }, + props: { post }, + cacheKey: post.updatedAt, + })); +} +--- +``` + +When you generate pages from a [content collection](/en/guides/content-collections/), each entry provides a `digest` value that changes when the entry's data changes. This makes it a convenient `cacheKey`: + +```astro title="src/pages/docs/[...slug].astro" +--- +import { getCollection, render } from "astro:content"; + +export async function getStaticPaths() { + const entries = await getCollection("docs"); + + return entries.map((entry) => ({ + params: { slug: entry.id }, + props: { entry }, + cacheKey: String(entry.digest), + })); +} + +const { entry } = Astro.props; +const { Content } = await render(entry); +--- +``` + +## How pages are invalidated + +A page with a matching `cacheKey` is still re-rendered when the code it relies on changes. Astro hashes the page's module dependency graph, including the contents of its layouts, components, and imported files, so editing any of them invalidates the pages that use them. Changing your Astro configuration or your project's dependencies invalidates the entire cache, since those can affect the output of every page. + +Pages that are removed from `getStaticPaths()` between builds have their previous output cleaned up automatically. + +## Preserving the cache between builds + +Astro writes a cache manifest to `node_modules/.astro/` and keeps the previous build output in `dist/` instead of emptying it at the start of each build. + +For pages to be skipped in a continuous integration environment, both directories must be restored before running `astro build`. Cache `node_modules/.astro/` and restore `dist/` from your previous build. If `dist/` is missing, Astro has no output to reuse and re-renders every page even when the manifest is present. From 70693ba3e88598b1a25bb1617ff93ece0de326a4 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 4 Aug 2026 16:10:29 -0400 Subject: [PATCH 2/5] Update src/content/docs/en/reference/experimental-flags/incremental-build.mdx Co-authored-by: Armand Philippot --- .../docs/en/reference/experimental-flags/incremental-build.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx index d8337515b5a3e..e443d8dac18b3 100644 --- a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx +++ b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx @@ -52,7 +52,7 @@ export async function getStaticPaths() { --- ``` -When you generate pages from a [content collection](/en/guides/content-collections/), each entry provides a `digest` value that changes when the entry's data changes. This makes it a convenient `cacheKey`: +When you generate pages from a [content collection](/en/guides/content-collections/), a loader can provide a `digest` for each entry. The loader is responsible for updating this value whenever the entry's data changes. This makes it a convenient `cacheKey`: ```astro title="src/pages/docs/[...slug].astro" --- From 93e832507cf30c01c7d432a6e74b33a42b20552a Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Tue, 4 Aug 2026 16:55:50 -0400 Subject: [PATCH 3/5] Clarify incremental build cache persistence and add limitations --- .../experimental-flags/incremental-build.mdx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx index e443d8dac18b3..40176ffc63585 100644 --- a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx +++ b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx @@ -81,6 +81,18 @@ Pages that are removed from `getStaticPaths()` between builds have their previou ## Preserving the cache between builds -Astro writes a cache manifest to `node_modules/.astro/` and keeps the previous build output in `dist/` instead of emptying it at the start of each build. +Astro stores the incremental cache in your project's [`cacheDir`](/en/reference/configuration-reference/#cachedir), which is `node_modules/.astro/` by default. This holds both the build manifest and the reusable output of previously-rendered pages. The output directory is emptied at the start of every build, and skipped pages are restored from `cacheDir`. -For pages to be skipped in a continuous integration environment, both directories must be restored before running `astro build`. Cache `node_modules/.astro/` and restore `dist/` from your previous build. If `dist/` is missing, Astro has no output to reuse and re-renders every page even when the manifest is present. +For pages to be skipped in a continuous integration environment, `cacheDir` must be restored before running `astro build`. Cache and restore this single directory between builds; nothing else needs to persist. If it is missing, Astro re-renders every page. + +To ignore the cache and re-render every page, run `astro build --force`. Astro still writes a fresh cache for the next build. + +## Limitations + +This experimental feature currently has the following limitations: + +- **`build.concurrency`**: The incremental cache is disabled when [`build.concurrency`](/en/reference/configuration-reference/#buildconcurrency) is greater than `1`. Astro logs a warning and re-renders every page. + +- **Server islands**: A page that renders a [server island](/en/guides/server-islands/) embeds props encrypted with a key that is [regenerated on each build by default](/en/guides/server-islands/#reusing-the-encryption-key). Set a stable `ASTRO_KEY` so these pages can be reused between builds; without one, they are re-rendered every time. Changing the key also invalidates them, so their embedded content stays decryptable. + +- **Middleware**: Changes to your [middleware](/en/guides/middleware/) do not invalidate cached pages. If your middleware changes the HTML of prerendered pages, run `astro build --force` after editing it. From 42f0e113ce5082e919adbeca31447cfd7f76b7c6 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 5 Aug 2026 13:54:37 -0400 Subject: [PATCH 4/5] Update src/content/docs/en/reference/experimental-flags/incremental-build.mdx Co-authored-by: Armand Philippot --- .../docs/en/reference/experimental-flags/incremental-build.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx index 40176ffc63585..754c536451283 100644 --- a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx +++ b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx @@ -52,7 +52,7 @@ export async function getStaticPaths() { --- ``` -When you generate pages from a [content collection](/en/guides/content-collections/), a loader can provide a `digest` for each entry. The loader is responsible for updating this value whenever the entry's data changes. This makes it a convenient `cacheKey`: +When you generate pages from a [content collection](/en/guides/content-collections/), a loader can provide a [`digest`](/en/reference/content-loader-reference/#dataentrydigest) for each entry. The loader is responsible for updating this value whenever the entry's data changes. This makes it a convenient `cacheKey`: ```astro title="src/pages/docs/[...slug].astro" --- From 2e68a81ae25e85eca503159f65bffe022374067b Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 5 Aug 2026 13:54:47 -0400 Subject: [PATCH 5/5] Update src/content/docs/en/reference/experimental-flags/incremental-build.mdx Co-authored-by: Armand Philippot --- .../docs/en/reference/experimental-flags/incremental-build.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx index 754c536451283..cd38e2a5f226b 100644 --- a/src/content/docs/en/reference/experimental-flags/incremental-build.mdx +++ b/src/content/docs/en/reference/experimental-flags/incremental-build.mdx @@ -93,6 +93,6 @@ This experimental feature currently has the following limitations: - **`build.concurrency`**: The incremental cache is disabled when [`build.concurrency`](/en/reference/configuration-reference/#buildconcurrency) is greater than `1`. Astro logs a warning and re-renders every page. -- **Server islands**: A page that renders a [server island](/en/guides/server-islands/) embeds props encrypted with a key that is [regenerated on each build by default](/en/guides/server-islands/#reusing-the-encryption-key). Set a stable `ASTRO_KEY` so these pages can be reused between builds; without one, they are re-rendered every time. Changing the key also invalidates them, so their embedded content stays decryptable. +- **Server islands**: Pages that renders [server islands](/en/guides/server-islands/) embed props with a key that is [regenerated on each build by default](/en/guides/server-islands/#reusing-the-encryption-key). They are re-rendered every time. To cache these pages and reuse them between builds, set a stable `ASTRO_KEY`. Changing the key invalidates them, ensuring that their embedded content stays decryptable. - **Middleware**: Changes to your [middleware](/en/guides/middleware/) do not invalidate cached pages. If your middleware changes the HTML of prerendered pages, run `astro build --force` after editing it.