After upgrading a project from webpack 4 to webpack 5 (webpack@^5.64.4, webpack-dev-server@^4.6.0), running npm start results in the terminal hanging at Starting the development server..., and the browser shows a blank page at localhost:3000.
Diagnosing Common Causes
Port Conflict
The default port for webpack-dev-server is 3000. Check if another process is using it:
lsof -i:3000
If occupied, either terminate the conflicting process or configure a different port in webpack.config.js:
devServer: {
port: 3001,
}
In this case, no conflict was found.
Source Map Generation
Disabling source maps can sometimes resolve startup hangs during development:
Create .env in the project root:
GENERATE_SOURCEMAP=false
This helps reduce initial build overhead but didn’t fully solve the blank screan issue here.
Incorrect Entry Point Configuration
The project uses separate entry files for development (src/index2.js) and production (src/index.js). The webpack config must conditionally select the correct one:
// paths.js
const appDevEntry = resolveModule(resolveApp, 'src/index2');
const appProdEntry = resolveModule(resolveApp, 'src/index');
// webpack.config.js
entry: isEnvDevelopment ? appDevEntry : appProdEntry,
Without this, Reeact fails to mount to the DOM root, causing a blank page despite successful server startup.
Circular Dependencies
Circular module references can silently break execution in complex dependency graphs. To detect them, use circular-dependency-plugin:
const CircularDependencyPlugin = require('circular-dependency-plugin');
plugins: [
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /src/,
failOnError: false,
cwd: process.cwd(),
}),
],
Refactoring to eliminate circular imports improved stability and testability.
SplitChunks Misconfiguration in Development
The original config applied code splitting in all environments:
optimization: {
splitChunks: { chunks: 'all', name: false },
runtimeChunk: { name: entrypoint => `runtime-${entrypoint.name}` }
}
However, aggressive chunking during development slows down builds and can interfere with hot reloading. Restrict it to production:
optimization: {
splitChunks: isEnvProduction
? { chunks: 'all', name: false }
: false,
runtimeChunk: isEnvProduction
? { name: (entrypoint) => `runtime-${entrypoint.name}` }
: false,
},
After this change, npm start launched successfully, and the app rendered correctly in the browser.