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.
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:
| Operation | Time | Pages rebuilt |
|---|---|---|
eleventy full build (cold) | 4.82 s | 500 |
| Incremental rebuild — edit one post | 0.11 s | 1 |
| Incremental rebuild — edit a shared partial | 0.34 s | ~40 (pages using it) |
| Incremental rebuild — edit base layout | 4.6 s | 500 (all) |
--serve --ignore-initial startup | 0.2 s | 0 (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
eleventybuild to reset. - Surprise at full rebuilds. Editing data files in the global
_datadirectory 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
--incrementaland--ignore-initialfrom 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.
Related
- Parent: Incremental Builds and Build Caching for SSGs — incremental vs. caching across generators.
- Caching Hugo Builds in GitHub Actions — the caching side for Hugo.
- Sharing Build Cache Across CI Runners — remote caches for parallel jobs.
- GitHub Actions for Automated SSG Builds — where cold full builds happen and what to cache.