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
1 change: 1 addition & 0 deletions astro.sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
title: Experimental incremental static builds
sidebar:
label: Incremental builds
i18nReady: true
---

import Since from '~/components/Since.astro'

<p>

**Type:** `boolean`<br />
**Default:** `false`<br />
<Since v="7.2.0" />
</p>

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/), 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"
---
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 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, `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**: 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.
Loading