Faster builds for Talent One Employer
The app employers use on Navigos Talent One now builds 2.4x faster, and its CI job takes half as long.
All work- Product
- Talent One Employer, a Next.js and React monorepo
- Merged
- Build 2.4x faster, CI job halved
- Prototyped
- A 4x faster build, not merged yet
A build that grew with the product
Employers use Talent One Employer to post jobs, source candidates and run campaigns. It is a Next.js and React monorepo with a shared UI library, LaUI, and feature packages kept as Git submodules.
Before this work, the August code took 98.3 s to build cold on my machine, measured on 7 November. The staging Jenkins job averaged 409 s over four builds on 8 and 9 October, before Turbopack, and the dev server reached 8.9 GiB of memory on a cold start. Meanwhile the codebase kept growing, mostly in the block builder.
Finding where the time went
The build had separate slow phases: a single-threaded tsc check, a webpack compile whose cache made warm builds slower than cold ones, the LaUI library build and the dependency install. A faster phase does not always make the whole build faster, so I sampled the build’s processes every quarter second and gave each phase its own time and memory figure.
What I changed, and why
Most of the work was configuration. After a dependency cleanup the workspace moved from Yarn 1 to Yarn 4 on Node 24, and Tailwind went from 3.4 to 4.3. I narrowed the helper and bootstrap imports so each page pulls in less code, and lowered the memory that LaUI and the production build need. The build now runs two workers, and a shared Vite+ toolchain replaced Turborepo for workspace tasks.
The type-check now runs on the TypeScript 7 native checker, which checks files in parallel, with tuned garbage collection and fresh-check settings. TypeScript 6 stays for declaration output and for tools that use the compiler API, because they still need it.
Turbopack replaced webpack for production builds. I first tried a lower-memory webpack setup with its cache off. It saved memory and made repeat builds slower. Turbopack cut compile time and keeps no build cache that grows on every run.
In development, the server now waits for checked LaUI output before it compiles, so it never builds against stale library files, and its caches survive a production build. All of this is merged.
Before and after
Three runs each on the same machine; the merged side ran later at lower load, so treat the build gain as approximate. The Jenkins figures come from the build history.
| Measure | Before | Merged |
|---|---|---|
| Cold production build | 98.3 s | 40.6 s |
| Type-check | 18.8 s with tsc 5.9 | 10.3 s with TypeScript 7 |
| Next.js compile | 57 s | 25 s |
| Staging Jenkins job | 409 s, mean of 4 builds (8 and 9 Oct) | 198 s, median of 28 builds |
| Dev server peak memory, cold start | 8.9 GiB | 6.0 GiB |
A second round, prototyped
In November I prototyped a second round: Bun for local type-checks, tsrs for LaUI declarations, a Tailwind scan that skips a generated icon catalog, and dev restarts that keep Turbopack’s cache. The local build drops to 24.1 s, about 4x faster than in August, and a LaUI edit shows on screen in 2.6 s instead of 7.2 s.
It has costs. Ctrl-C takes up to 3.5 s instead of 0.6 s while Turbopack saves its cache, and Next.js is ready about a second later. None of the second round is merged yet.
What I would fix next
On the sign-in pages, blocking time fell from 769 ms to about 200 ms in Lighthouse. Those pages also download 27% more JavaScript and paint later, because the login route still loads nearly the whole app. That route is the next thing I would fix.
Merged
- Local production build 2.4x faster: 98.3 s to 40.6 s.
- Staging CI job halved: 409 s to 198 s.
- A third less dev server memory on a cold start.