npx webpack --stats=verbose (Webpack) or
vite build --debug (Vite) -- verbose output reveals the exact file, loader, or plugin
causing the failure. [src3, src4]Buffer, process, crypto, path). Code that worked
in Webpack 4 will fail at runtime without explicit polyfill configuration. [src2]node_modules and reinstall without first reading the error message --
this wastes time and may mask the real issue. [src4, src6]
webpack.config.js (CJS by default); Vite uses vite.config.js (ESM by
default). Mismatched "type": "module" in package.json causes silent failures.
[src1, src2]crypto-browserify, buffer, stream-browserify) adds
50-200 KB. Prefer browser-native APIs instead. [src2]| # | Error Pattern | Bundler | Likelihood | Signature | Fix |
|---|---|---|---|---|---|
| 1 | Module not found (import path) | Both | ~30% | Module not found: Can't resolve './Foo' |
Fix import path casing; verify file exists [src4, src6] |
| 2 | Module not found (package) | Both | ~20% | Cannot find module 'lodash' |
npm install lodash or check package.json [src6]
|
| 3 | Node.js polyfill missing | Webpack 5 | ~15% | Module not found: Can't resolve 'crypto' |
Add resolve.fallback in webpack config [src2] |
| 4 | Loader not found / misconfigured | Webpack | ~10% | Module build failed: Unknown word |
Install loader: npm i -D babel-loader; check module.rules [src4] |
| 5 | ESM/CJS mismatch | Both | ~8% | ERR_REQUIRE_ESM |
Add "type": "module" to package.json or rename config to
.mjs [src1, src2] |
| 6 | Platform-specific binary missing | Vite | ~5% | Cannot find module '@rollup/rollup-linux-x64-musl' |
Delete lockfile + node_modules, reinstall on target platform [src1, src7]
|
| 7 | JSON named import (Webpack 5) | Webpack 5 | ~3% | export 'version' was not found in './package.json' |
Use default import: import pkg from './pkg.json' [src2] |
| 8 | Strict mode violation | Vite | ~3% | SyntaxError: With statements cannot be used in strict mode |
Patch dependency via pnpm patch or patch-package [src1] |
| 9 | Chunk load failure (deploy) | Vite | ~3% | Failed to fetch dynamically imported module |
Add vite:preloadError handler; keep old chunks during rollover [src1, src5] |
| 10 | Out of memory | Both | ~3% | FATAL ERROR: Allocation failed - JavaScript heap out of memory |
NODE_OPTIONS=--max-old-space-size=8192 [src3] |
START — Build fails
├── Error contains "Module not found" or "Can't resolve"?
│ ├── Points to a local file (./src/foo)?
│ │ └── Check file exists, verify casing (Linux is case-sensitive) [src4, src6]
│ ├── Points to a package?
│ │ ├── In node_modules? → npm install / check package.json [src6]
│ │ ├── Node.js core module (crypto, path, fs)?
│ │ │ ├── Webpack 5 → Add resolve.fallback config [src2]
│ │ │ └── Vite → Module externalized; avoid in browser code [src1]
│ │ └── Platform binary (@rollup/rollup-*)?
│ │ └── Delete lockfile + node_modules; reinstall on target platform [src7]
│
├── Error contains "Module build failed" or "Module parse failed"?
│ ├── "Unknown word" → Missing loader for file type [src4]
│ ├── Loader wrong version → npm update loader [src4]
│ └── Syntax error → Check Babel/TS config [src3]
│
├── Error contains "ERR_REQUIRE_ESM"?
│ ├── Config file → Rename to .mjs/.mts or add "type": "module" [src1]
│ └── Dependency → Check exports field in dependency package.json [src2]
│
├── Build succeeds but runtime error?
│ ├── "process is not defined" → Add DefinePlugin for process.env [src2]
│ ├── "Buffer is not defined" → Install buffer polyfill [src2]
│ └── 404 on chunks → Check publicPath / base config [src2, src5]
│
├── Build hangs or OOM?
│ ├── Increase memory: NODE_OPTIONS=--max-old-space-size=8192 [src3]
│ ├── Webpack → cache.type = 'filesystem' [src3]
│ └── Reduce scope: check resolve.modules, loader include paths [src3]
│
└── DEFAULT → Enable verbose output:
├── Webpack: npx webpack --stats=verbose [src3, src4]
└── Vite: npx vite build --debug [src1]
Most build errors include a clear description. Enable verbose/debug output for complete context. [src3, src4]
# Webpack — enable detailed error info
npx webpack --stats=verbose
# Vite — enable debug logging
npx vite build --debug
# Trace Node.js deprecation warnings
node --trace-deprecation node_modules/.bin/webpack --mode production
Verify: Error output shows file paths, loader chain, and resolution attempts.
Version mismatches are a common hidden cause. [src2, src1]
node --version # Webpack 5 >= 10.13.0; Vite 6 >= 18
npx webpack --version
npx vite --version
npm outdated # check for outdated dependencies
Verify: Versions match the minimum requirements for your config.
For "Module not found" errors, trace how the bundler resolves imports. [src4, src6]
# Check if module is installed
npm list module-name
# Verify file exists with correct casing (critical on Linux)
ls -la src/components/MyComponent.js
# Clear caches
rm -rf node_modules/.cache node_modules/.vite
Verify: npm list module-name shows the package at the expected version.
When migrating from Webpack 4, add explicit polyfill configuration. [src2]
// webpack.config.js — Webpack 5 polyfill fallbacks
module.exports = {
resolve: {
fallback: {
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"buffer": require.resolve("buffer/"),
"fs": false, // set to false if not needed in browser
"net": false,
"tls": false,
}
},
plugins: [
new (require('webpack')).ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser',
}),
]
};
Verify: npx webpack completes without "Can't resolve 'crypto'" errors.
Resolve common Vite-specific build failures. [src1, src7]
// vite.config.js — common fixes
import { defineConfig } from 'vite';
export default defineConfig({
build: {
target: 'es2015',
chunkSizeWarningLimit: 1000,
},
optimizeDeps: {
force: true, // re-optimize after linking
include: ['problematic-cjs-package'],
},
});
# Force re-optimize dependencies
npx vite --force
# Fix platform-specific binary issues (CI/Docker)
rm -rf node_modules package-lock.json && npm install
Verify: npx vite build completes without errors.
Validate the loader config structure. [src3, src4]
// webpack.config.js — correct loader configuration
const path = require('path');
module.exports = {
module: {
rules: [{
test: /\.jsx?$/,
include: path.resolve(__dirname, 'src'), // CRITICAL: scope loaders
use: {
loader: 'babel-loader', // use full name, NOT 'babel'
options: { cacheDirectory: true },
},
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader'], // order: right-to-left
}, {
test: /\.(png|jpg|gif|svg)$/,
type: 'asset/resource', // Webpack 5 Asset Modules (replaces file-loader)
}],
},
cache: { type: 'filesystem' }, // persistent cache
};
Verify: npx webpack --stats=errors-only returns zero errors.
// Input: webpack.config.js — production-ready config
// Output: Bundle with polyfill fallbacks, optimized loaders, filesystem cache
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js', // contenthash, NOT hash
clean: true,
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
fallback: { "fs": false, "path": false, "crypto": false },
},
module: {
rules: [{
test: /\.[jt]sx?$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
options: { cacheDirectory: true },
}],
},
cache: { type: 'filesystem' },
stats: { errorDetails: true },
};
// Input: vite.config.js — production-ready config
// Output: Optimized build with CJS compatibility and error handling
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
build: {
target: 'es2015',
sourcemap: true,
rollupOptions: {
output: {
chunkFileNames: 'assets/[name]-[hash].js',
entryFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash].[ext]',
},
},
},
optimizeDeps: { include: ['axios', 'lodash'] },
server: { watch: { usePolling: true } }, // fix WSL2
});
#!/bin/bash
# Input: Run in project root with package.json
# Output: Diagnostic report for Webpack/Vite build failures
echo "=== Build Failure Diagnostic ==="
echo "Node: $(node --version) | npm: $(npm --version)"
# Detect bundler
[ -f "webpack.config.js" ] && echo "Webpack: $(npx webpack --version 2>/dev/null)"
[ -f "vite.config.js" ] && echo "Vite: $(npx vite --version 2>/dev/null)"
# Check module type
TYPE=$(node -e "try{console.log(require('./package.json').type||'commonjs')}catch(e){console.log('missing')}")
echo "Module type: $TYPE"
# Check node_modules health
if [ -d "node_modules" ]; then
echo "node_modules: $(du -sh node_modules 2>/dev/null | cut -f1)"
[ -d "node_modules/.cache" ] && echo "Cache: $(du -sh node_modules/.cache 2>/dev/null | cut -f1)"
else
echo "WARNING: node_modules missing"
fi
echo "--- Outdated packages ---"
npm outdated 2>/dev/null | head -11
// BAD — polyfilling everything adds 500KB+ to your bundle [src2]
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
module.exports = {
plugins: [new NodePolyfillPlugin()],
};
// GOOD — explicit fallbacks, unused modules set to false [src2]
module.exports = {
resolve: {
fallback: {
"crypto": false,
"stream": require.resolve("stream-browserify"),
"fs": false,
}
}
};
// BAD — processes ALL .js files including node_modules [src3]
module.exports = {
module: {
rules: [{ test: /\.js$/, loader: 'babel-loader' }],
},
};
// GOOD — only transpile your own code [src3]
const path = require('path');
module.exports = {
module: {
rules: [{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
options: { cacheDirectory: true },
}],
},
};
// BAD — ESM-only packages cannot be require()'d [src1]
const somePlugin = require('some-esm-only-plugin');
// Error: ERR_REQUIRE_ESM
// GOOD — use ESM imports (rename to .mjs or set "type": "module") [src1]
import somePlugin from 'some-esm-only-plugin';
import { defineConfig } from 'vite';
export default defineConfig({ plugins: [somePlugin()] });
// BAD — works on macOS/Windows, fails on Linux CI [src1, src6]
import MyComponent from './components/mycomponent'; // file is MyComponent.js
// GOOD — consistent casing matches filesystem [src1, src6]
import MyComponent from './components/MyComponent';
[hash] deprecation: Use [contenthash] instead --
produces stable hashes that only change when content changes. Fix: Replace [hash] with
[contenthash] in all output configs. [src2]npm link breaks pre-bundling: Linked packages are not detected by
Vite's optimizer. Fix: Run vite --force or prefer npm overrides / pnpm workspaces. [src1]Module parse failed on CSS: Webpack does not natively understand
CSS. Fix: npm i -D css-loader style-loader and add the loader rule. [src4]vite:preloadError listener to trigger page reload; keep old files during rollover. [src1, src5]vendors renamed: Webpack 5 renamed to
defaultVendors. Old configs silently create unintended chunk groups. Fix: Rename
cacheGroups.vendors to cacheGroups.defaultVendors. [src2]npm install in Docker. [src7]
"postinstall": "rm -rf node_modules/.cache" to package.json. [src3]# === Webpack Diagnostics ===
npx webpack --stats=verbose # verbose build output
npx webpack --stats=errors-only # only errors
node --trace-deprecation node_modules/.bin/webpack --mode production
npx webpack --version # check version
npx webpack --profile --json > stats.json # bundle analysis
node --inspect-brk node_modules/.bin/webpack # Chrome DevTools debug
NODE_OPTIONS=--max-old-space-size=8192 npx webpack # increase memory
# === Vite Diagnostics ===
npx vite build --debug # debug build output
npx vite --force # force re-optimize dependencies
npx vite build --profile # performance profile
npx vite --version # check version
# === General ===
node --version # check Node.js version
npm list package-name # verify installation
npm outdated # list outdated packages
rm -rf node_modules/.cache node_modules/.vite # clear caches
rm -rf node_modules package-lock.json && npm install # full reinstall
| Version | Status | Key Changes | Migration Notes |
|---|---|---|---|
| Webpack 5.x | Current (since 2020-10) | Removed Node.js polyfills; Asset Modules; persistent filesystem cache; library.type replaces libraryTarget | Run npx codemod@latest webpack/v5/migration-recipe; add
resolve.fallback [src2] |
| Webpack 4.x | Maintenance | Last version with automatic Node.js polyfills | Upgrade to 5.x; update all loaders/plugins first [src2] |
| Vite 6.x | Current (since 2024-11) | Rolldown bundler; Environment API | Check plugin compatibility with Rolldown [src1] |
| Vite 5.x | Previous stable | Rollup 4; Node.js 18+ required | Update vite.config.js for new defaults [src1] |
| Vite 4.x | EOL | SWC support; improved ESM handling | Straightforward upgrade to 5.x [src1] |
| Use This Guide When | Don't Use When | Use Instead |
|---|---|---|
npm run build or vite build fails with errors |
Dev server works but HMR is slow | Vite HMR troubleshooting or server.watch config |
| Migrating from Webpack 4 to 5 | Migrating from Webpack to Vite entirely | Vite migration guide |
| "Module not found" errors during build | Package install fails (npm install errors) |
npm/yarn/pnpm dependency resolution guides |
Runtime process is not defined after Webpack 5 upgrade |
TypeScript type errors (not build errors) | TypeScript compilation error guides |
| CI build fails but local build works | Bundle too large (no errors, just size) | Webpack Bundle Analyzer or vite-plugin-inspect |
vite dev may fail in
vite build. [src1, src5]resolve.fallback only applies to browser targets: If target is
Node.js (target: 'node'), webpack resolves built-in modules natively. [src2]node_modules/.cache can mask config changes: Both Webpack filesystem cache
and Vite pre-bundling cache may serve stale results. Clear caches when debugging unexpected behavior. [src3, src1]src/ directory. [src4]