What this usually means
Sluggish webpack builds stem from a combination of misconfigurations, excessive module count, inefficient plugins/loaders, or hardware/memory bottlenecks. In CI, slowdowns often reflect subtle differences in environment—like missing cache, misconfigured thread pools, or new third-party dependencies bloating the dependency graph. Unlike local, CI often disables filesystem cache and runs with different NODE_ENV; plus, changes to plugin ordering or source map settings compound the effect.
The first ten minutes — establish facts before touching code.
- 1Run `DEBUG=webpack:* npx webpack --profile --json > stats.json` and inspect stats.json with https://webpack.github.io/analyse/.
- 2Compare recent PR diffs for config changes: `git diff master..HEAD -- webpack.config.js` and `yarn.lock`.
- 3Check CI logs for cache misses: search for 'cache: false' or 'Cache not found'.
- 4Disable source maps by setting `devtool: false` and time the build again.
- 5Profile CPU with `time NODE_OPTIONS='--inspect' npx webpack` and use Chrome DevTools to investigate blocking modules.
- 6Check `/proc/meminfo` and `/proc/cpuinfo` in CI to confirm available resources match local.
The specific files, logs, configs, and dashboards that usually own this bug.
- searchwebpack.config.js (especially `optimization`, `devtool`, plugin and loader sections)
- searchCI/CD YAML config (GitHub Actions, Gitlab CI, etc.) for missing node_modules or cache steps
- searchstats.json (from `webpack --profile --json`)
- searchnode_modules/.cache/ (verify presence and permissions)
- searchyarn.lock or package-lock.json for dependency bloat
- searchbuild logs around `[webpack.Progress]` plugin output
- searchDockerfile or base image for mismatches in Node/npm versions
Practical causes, not theory. These are the things you will actually find.
- warningAccidental switch from filesystem to memory cache (or no cache) in webpack config
- warningHeavy source-map generation in production mode (e.g., `devtool: 'source-map'`)
- warningIntroduction of expensive plugins (e.g., Terser running single-threaded)
- warningHuge dependency upgrades adding thousands of modules
- warningCI running with too few vCPUs or not enough memory
- warningMisconfigured `thread-loader` or missing worker pool
- warningAccumulation of orphaned files in `node_modules/.cache` causing slow lookups
Concrete fix directions. Pick the one that matches your root cause.
- buildSet `cache: { type: 'filesystem' }` in webpack config for all environments except test
- buildReplace `devtool: 'source-map'` with `devtool: 'cheap-module-source-map'` in prod
- buildConfigure `TerserPlugin` with `parallel: true` and tune `minify` options
- buildTrim dependencies with `yarn why <module>` and remove unused packages
- buildIncrease available CPUs on CI runners (at least 4 vCPUs for large projects)
- buildAdd explicit `build-cache` steps to persistent CI cache between runs
- buildClean `node_modules/.cache` before build if corruption is suspected
A fix you cannot prove is a guess. Close the loop.
- verifiedRe-run `npx webpack --profile --json > stats.json` and compare total build times and bottlenecks before/after
- verifiedCheck CI pipeline history for step duration improvements
- verifiedValidate cache hits in CI logs (look for 'Restored cache')
- verifiedConfirm build output and sourcemaps are functionally identical to pre-fix
- verifiedUse Chrome DevTools profiler on a local build to verify blocking calls are gone
- verifiedEnsure memory and CPU consumption during build are within expected bounds
Things that make this bug worse or harder to find.
- warningBlindly disabling all plugins—often hides root causes but hurts build quality
- warningOverusing heavy source-map types in production
- warningForgetting to persist cache directories between CI runs
- warningIgnoring warnings about Node memory limits; can cause OOM crashes instead of slow builds
- warningNeglecting to profile real production builds as opposed to local development settings
- warningAssuming dependency upgrades are always benign for build time
Webpack Build Time Balloons After Minor Plugin Addition
Timeline
- 10:02PR merged adding 'webpack-bundle-analyzer' plugin in prod config
- 10:05First CI job fails to cache build, runs in 17:03 (was 3:49 previously)
- 10:07Slack alert triggers on >2x build duration threshold
- 10:10Engineer investigates stats.json; sees 95% of time in asset optimization
- 10:13Notices `devtool` set to `source-map` for production
- 10:15Disables bundle analyzer and source maps, reruns build—time drops to 4:10
- 10:20Moves analyzer to a separate analysis script outside production config
We pushed a seemingly harmless upgrade: adding `webpack-bundle-analyzer` to the production plugins so we could monitor bundle sizes in CI. The next build took over 17 minutes, triggering a Slack alert for slow pipelines. At first, we thought it was a CI flake, but multiple reruns showed consistent slowness.
Digging into the stats, I saw the slowdown at 92–98% progress, during asset optimization. Terser and source map generation were critical bottlenecks. The bundle analyzer was running on top of that, consuming even more memory. Meanwhile, our `devtool` was still set to `'source-map'`, the slowest option for production.
We split the analyzer into a post-build script, changed `devtool` to `'cheap-module-source-map'`, and confirmed with stats that minification was now multi-threaded and the build time restored to under 5 minutes. We added a build cache step to avoid this class of regression.
Root cause
Accidentally running heavy analysis plugins and full source map generation in production CI builds.
The fix
Limit heavy plugins to post-build analysis, use a more efficient source map type, and ensure persistent build caching.
The lesson
Always test production builds with real CI settings before merging config changes, and treat source maps and build analysis as explicitly opt-in, not default.
The webpack build progress bar is notoriously misleading: a 10% stall on 'chunk asset optimization' can mask hours lost to Terser, source maps, or post-processing plugins. Always generate a `stats.json` profile and visualize it using the webpack analysis tools. Pay attention to 'asset processing', 'module build', and 'optimize assets' phases—if any stage takes 5x longer than expected, that's where to dig.
For deep dives, run with `NODE_OPTIONS='--inspect' npx webpack` and connect Chrome DevTools. Use the profiler to trace which plugins or loaders dominate CPU cycles, especially in minification and code splitting.
It's common to overlook subtle environment differences—CI might default to 2 vCPUs, while your laptop uses 8. CI often skips persistent node_modules and cache directories between steps, which destroys webpack's cache advantage.
Always check your CI job YAML for missing cache steps. If you use GitHub Actions, verify both `node_modules` and `node_modules/.cache` are restored before build. A single line omission here can double or triple your build times overnight.
Webpack's `devtool` config can cost you minutes per build. `'source-map'` produces full separate files—useful for debugging, but overkill for prod CI. Prefer `'cheap-module-source-map'` or disable entirely unless actively debugging production bundles.
If you must keep source maps, consider generating them in parallel or as a post-build step. This isolates their cost and prevents timeouts in the main build job.
Webpack 5's filesystem cache is a massive win—if you configure it. Add `cache: { type: 'filesystem' }` to your config, and make sure CI actually persists `.cache` between runs.
Watch for path mismatches or root directory issues. Caching works only if the build path, lockfile, and package manager versions match—otherwise webpack invalidates the cache, destroying the benefit.
Frequently asked questions
Why is my webpack build fast locally but slow on CI?
CI often lacks persistent `node_modules/.cache`, runs with fewer CPUs, and may use different Node/npm versions. Always align your local and CI environment variables, and configure persistent caching.
Can source maps really add minutes to my build?
Yes. With `devtool: 'source-map'`, build time can triple—especially for large bundles and many entrypoints. Use lighter source map types or disable for production CI unless strictly needed.
How do I tell which plugin or loader is the slowest?
Generate a `stats.json` profile (`webpack --profile --json`), and analyze with webpack's online tools. Look for plugins/loaders that dominate 'asset optimization' or 'module build' time.
What hardware specs are needed for large webpack builds?
At least 4 vCPUs and 8GB RAM are recommended for big projects with heavy minification. Monitor CPU and memory usage during builds to confirm adequacy.