On this page
Why there are no screenshotsThe guard that scopes everythingOptimization 1 — cap the minifier's worker countOptimization 2 — drop the TypeScript checker pluginOptimization 3 — persistent filesystem cacheWhat a build operator would actually observeWalkthrough
There is no application screen to walk through — this PR touches build tooling, not product UI. This page substitutes a guided tour of the actual code change (the closest thing this PR has to a "screen"), plus what a build operator would see happen around it.
Why there are no screenshots
The sandbox this PR would normally be demoed in — web app, API, and even the sandbox terminal — returned HTTP 404 across the board when checked for this documentation run. That's a full-stack outage of the preview environment, not a quirk of this one app, so no login screen or dashboard was reachable to photograph. Even with a live sandbox, this specific change wouldn't produce a visual difference: it only affects how the clinic-web bundle is built, not anything it renders once built. The tour below is annotated code instead of annotated screenshots.
The guard that scopes everything
Every change in this PR lives inside one if, in packages/clinic-web/craco.config.js (around line 99):
if (isProduction && process.env.SANDBOX_BUILD === 'true') {
// ...the three optimizations...
}
Two conditions must both be true:
isProduction— the build is running in webpack'sproductionmode (i.e., a real
build, not the dev/start server).
process.env.SANDBOX_BUILD === 'true'— an environment variable that only the
sandbox overlay Dockerfile sets (ENV SANDBOX_BUILD=true, Dockerfile:156).
Strict equality against the string 'true' means anything else — unset, empty, 'false', '1' — leaves the block skipped. Production release scripts (clinic:web:build:prod, build:with-sourcemaps, etc.) never set this variable, so for them this whole block is dead code that never executes.
Optimization 1 — cap the minifier's worker count
webpackConfig.optimization.minimizer.forEach(plugin => {
if (plugin.constructor && plugin.constructor.name === 'TerserPlugin') {
plugin.options.parallel = 2
}
})
Walks the list of minimizer plugins CRA already configured, finds the one named TerserPlugin (the JS minifier react-scripts uses by default), and overwrites its parallel option to 2. Left alone, TerserPlugin defaults parallel to os.cpus().length — 32 on the sandbox build host — spawning 32 worker processes, each holding its own copy of the bundle's abstract syntax tree while minifying.
Optimization 2 — drop the TypeScript checker plugin
webpackConfig.plugins = webpackConfig.plugins.filter(plugin =>
!(plugin.constructor && plugin.constructor.name === 'ForkTsCheckerWebpackPlugin')
)
Filters ForkTsCheckerWebpackPlugin out of the webpack plugin list entirely. This plugin normally runs a full TypeScript project type-check in a forked sidecar process alongside the build — useful in CI or a production build where you want to fail on type errors, costly (~500–800 MB) when you just want a working preview bundle fast.
Optimization 3 — persistent filesystem cache
webpackConfig.cache = {
type: 'filesystem',
cacheDirectory: '/tmp/webpack-cache',
compression: 'gzip'
}
Switches webpack from its default in-memory cache (which starts cold on every build) to a filesystem cache at a fixed path. That path lines up with a Docker BuildKit cache mount already present in the sandbox Dockerfile:
RUN --mount=type=cache,target=/tmp/webpack-cache,id=cra-webpack-dentolize \
yarn workspace @dentolize/clinic-web run build
(Dockerfile:298-299). BuildKit persists that mount's contents between separate docker build invocations, so a warm rebuild — of the same branch, or a different one that shares most of the same source, since webpack keys cache entries by content hash — can skip re-processing files it already compiled.
What a build operator would actually observe
With a working sandbox, the way to confirm this PR is doing what it claims is operational, not visual:
docker statsduring a clinic-web sandbox build, watching peak memory drop from
the ~5 GB baseline toward the PR's ~1.5–2 GB target.
- Two builds of the same branch back-to-back — the second should be visibly faster
once /tmp/webpack-cache is warm.
- A production build (
yarn clinic:web:build:prod:test) run withoutSANDBOX_BUILD
set, to confirm it takes the exact same code path it always has.
See For Quality for the fuller test checklist.