
Build Note
Build without breaking a running dev server
next build and next dev share .next/, so a build pulls chunks out from under a running dev server. One env-driven distDir gives the build its own directory.
Published July 26, 2026
next build and next dev both write to .next/, so running a build pulls compiled chunks out from under a dev server that's still serving them. Point the build at its own directory with an environment variable and the two stop colliding.
The symptom
A dev server that was working starts throwing Cannot find module './NNN.js' — a numeric chunk filename you have never seen and cannot grep for. Pages that rendered a minute ago return 500s. Restarting the dev server fixes it, right up until the next build.
The tell is the timing: it starts the moment somebody runs a production build in the same checkout.
Why it happens
Both commands use .next/ as their output directory, and the build rewrites it. The dev server is holding references to chunk files by hashed name; the build removes and regenerates those files with different hashes; the next request asks for a module that no longer exists. Nothing is corrupted in any interesting sense — two processes are simply writing to the same folder.
The fix
Make the output directory configurable, defaulting to the normal one:
// NEXT_DIST_DIR lets a build run isolated from the .next/ that concurrently
// running dev servers depend on (this repo gets edited by parallel sessions).
// Unset in normal dev/deploy, so Vercel and `next start` see no change.
distDir: process.env.NEXT_DIST_DIR || ".next",Then build into a scratch directory whenever something else is running:
NEXT_DIST_DIR=.next-verify npm run buildFour lines of config, and the dev server never notices. Add the directory prefix to .gitignore — these outputs are disposable, and you may end up with several.
When this earns its keep
Any time a build and a dev server share a checkout. That is most obviously two people on one machine, but the case that made it necessary here is parallel agent sessions working in the same repository — each one wanting to verify its own changes with a production build while another is still serving the site locally.
It also makes the build safe to run as a routine check rather than an event, which matters when the check is the thing enforcing a standard — like reading First Load JS out of the route table after every change. A verification step nobody can run without disrupting someone else is a verification step that quietly stops happening.
Small workflow frictions like this compound quietly across a project. Removing them is unglamorous and it is most of what makes a long engagement stay quick.
Questions
Isn't deleting .next the standard fix?
It is, and it works — for you. It also throws away the running dev server's compiled state, which is fine when you're alone and rude when somebody else, or another agent session, is mid-task in the same checkout. Giving the build its own directory means nobody has to be interrupted.
Does this change anything on deploy?
No. The variable is unset in normal development and in CI, so the config falls through to ".next" and the hosting platform sees exactly what it saw before. It only does something when you explicitly ask it to.
Should I gitignore the extra directory?
Yes — add the pattern you use, or ignore the prefix outright. These are disposable build outputs, and the whole point is that you can create one per concurrent task and delete them without ceremony.
Related notes
- Keeping First Load JS under budget in Next.js
- Use a content registry instead of a CMS
- Keeping 100 Lighthouse scores behind a strict CSP
More on web development
- Claude Code rules for Elementor sites
- Claude Code rules for WCAG testing
- Cursor rules for WCAG testing
- Animating hero text without layout shift
Related service: Web Development
Want this kind of engineering on your project?
Tall Karol takes on fractional and project-based engagements for startups and agencies.
Book a working session