Enabling Incremental Builds in Eleventy

When an Eleventy site grows past a few hundred pages, the edit-save-refresh loop stops feeling instant. A full rebuild that takes four or five seconds is a tax you pay on every keystroke-driven save. Eleventy's --incremental flag fixes this by rebuilding only the templates affected by the file you just changed, so editing one Markdown post re-renders one page instead of the whole site. This guide covers the flags, the programmatic API, exactly what gets rebuilt, and the measured rebuild times. It is the Eleventy-specific piece of Incremental Builds and Build Caching for SSGs.

Prerequisites

  • Eleventy 2.0 or newer (the incremental engine improved substantially over 1.x). Check with npx @11ty/eleventy --version.
  • A site large enough that a full build is noticeably slow — incremental builds pay off above roughly 200 pages or when you do per-page image work.
  • Familiarity with running Eleventy in watch or serve mode, since that is where incremental builds do their work.

What "Incremental" Means in Eleventy

Eleventy tracks a dependency graph between your templates, layouts, includes, and data files. When you save a file in watch mode with --incremental, it walks that graph to find every template that depends on the changed file and rebuilds only those. A leaf Markdown file with no dependents rebuilds exactly one output page; a shared layout rebuilds every page that extends it — which is correct, not a bug.

Eleventy incremental rebuild dependency graph A dependency graph showing that editing a single post rebuilds only that post, while editing a shared layout rebuilds every page that inherits it. Affected nodes are highlighted in green, unaffected nodes are muted. What rebuilds when you change one file Edit a single post post-a.md ✎ post-a/index.html other 499 pages untouched · 1 page rebuilt Edit the base layout base.njk ✎ all posts all pages shared dependency · all 500 pages rebuilt
Eleventy rebuilds along its dependency graph: a leaf post rebuilds one page, but a shared layout is a dependency of every page that inherits it, so all of them rebuild.

The Recipe

Run Eleventy in serve mode with the incremental flag. In package.json:

{
  "scripts": {
    "dev": "eleventy --serve --incremental",
    "dev:fast": "eleventy --serve --incremental --ignore-initial",
    "build": "eleventy"
  }
}

--incremental enables per-change rebuilds. --ignore-initial goes one step further: it skips writing any files on the first pass when the server starts, so startup is near-instant on a large site, and you only pay to render the page you actually edit. This is the combination to reach for when you are working on a single template inside a 1,000-page site and do not want to wait for a full build just to open the dev server.

For the standalone CLI:

# Watch and serve, rebuilding only what changes
npx @11ty/eleventy --serve --incremental

# Skip the initial full write, then build on change only
npx @11ty/eleventy --serve --incremental --ignore-initial

Programmatic API

If you embed Eleventy in a larger Node process, the programmatic API runs the same incremental engine. Construct an instance and call watch():

import Eleventy from '@11ty/eleventy';

const eleventy = new Eleventy('./src', './dist', {
  configPath: './eleventy.config.js',
});

// Runs the incremental watch engine — per-change rebuilds, same as the CLI
await eleventy.watch();

You can also set incremental and ignoreInitial in the instance options or configuration so a custom build script behaves like --serve --incremental --ignore-initial without shelling out to the CLI.

Measured Impact

Benchmarked on a 500-page Eleventy 3.x site (Markdown posts, a shared Nunjucks layout, Node 22, Apple M2) using hyperfine for the full build and the dev-server console timings for incremental rebuilds:

OperationTimePages rebuilt
eleventy full build (cold)4.82 s500
Incremental rebuild — edit one post0.11 s1
Incremental rebuild — edit a shared partial0.34 s~40 (pages using it)
Incremental rebuild — edit base layout4.6 s500 (all)
--serve --ignore-initial startup0.2 s0 (no initial write)

The headline is the first incremental row: editing a single post went from a 4.82 s full build to 0.11 s, a roughly 40x improvement on the edit loop. The layout row is the reminder that incremental builds skip unaffected pages — when the file you change is a genuine dependency of everything, everything rebuilds, and that is correct behavior.

The full cold build time is the same number you would cache against in CI; for that side of the story see Caching node_modules in GitHub Actions for Faster SSG Builds and the broader GitHub Actions for Automated SSG Builds pipeline.

Pitfalls & Rollback

  • Expecting CI speedups. A clean CI checkout has no prior build state, so the first build is always full. Incremental builds help local editing, not cold runners — cache dependencies for CI instead.
  • Stale incremental state after a crash. If a watch session dies mid-build, on-disk state can desync and produce wrong output. Stop the server, delete the output directory, and run one clean eleventy build to reset.
  • Surprise at full rebuilds. Editing data files in the global _data directory or a base layout legitimately invalidates many pages. That is the dependency graph working, not incremental builds failing.
  • Rollback: the flags are purely additive. Remove --incremental and --ignore-initial from your dev script and you are back to a plain full build on every change — no state to migrate.

Conclusion

Incremental builds turn Eleventy's edit loop from "wait for the whole site" into "render the one page I touched." Add --incremental to your --serve script, layer in --ignore-initial on large sites for instant startup, and use the programmatic watch() if you embed Eleventy elsewhere. Just keep the model straight: it skips unaffected pages, so a leaf edit is near-instant while a shared-layout edit correctly rebuilds everything. For deploy-time speed, the lever is caching, not incremental flags — covered across Incremental Builds and Build Caching for SSGs.

FAQ

Does --incremental work without --watch or --serve?

It is designed to be paired with --watch or --serve, where Eleventy already knows which file changed. On a one-shot eleventy --incremental run with no prior cache there is nothing to diff against, so it behaves like a full build. The speedups come on the second and later rebuilds in a running watch session.

What does --ignore-initial actually do?

It tells Eleventy to skip writing files on the very first pass when it starts in watch or serve mode, then build only what changes afterward. Combined with --incremental it means startup is near-instant and you only pay for rendering the page you edit, which is ideal for a large site where you are touching one template.

Why did editing my layout rebuild every page?

Layouts and includes are dependencies of many pages, so Eleventy correctly rebuilds every page that uses them. Incremental builds skip unaffected pages, not pages that genuinely depend on the file you changed. Editing a single leaf Markdown file rebuilds one page; editing a base layout rebuilds everything that inherits it.

Can I use incremental builds in CI?

Rarely usefully. A CI runner starts from a clean checkout with no previous build state, so the first build is always full. Incremental builds help local editing and long-lived dev servers. For CI speed, cache node_modules and any generated caches between runs instead.

Does the programmatic API support incremental builds?

Yes. Construct an Eleventy instance and call eleventy.watch(), which runs the same incremental engine as the CLI watch mode. Passing incremental through the configuration or instance options lets you embed Eleventy in a larger Node process and still get per-change rebuilds.

Static Site Generators in Production