Webpack hot reloading middleware that can be attached to your own server
npx @tessl/cli install tessl/npm-webpack-hot-middleware@2.26.0Webpack Hot Middleware provides webpack hot module replacement (HMR) for custom server setups without requiring webpack-dev-server. It acts as a bridge between webpack's compilation process and browser clients using Server-Sent Events to communicate build updates and coordinate hot module replacement through webpack's HMR API.
npm install --save-dev webpack-hot-middlewareconst webpackHotMiddleware = require("webpack-hot-middleware");For client-side integration:
// In webpack entry configuration
entry: {
main: ['webpack-hot-middleware/client', './src/main.js']
}const webpack = require('webpack');
const express = require('express');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// Add webpack-dev-middleware
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Add webpack-hot-middleware
app.use(webpackHotMiddleware(compiler));
app.listen(3000);Webpack Hot Middleware operates through several key components:
The main middleware factory function that creates HMR middleware for a webpack compiler.
/**
* Creates webpack hot middleware for a compiler instance
* @param {Object} compiler - webpack compiler instance
* @param {Object} opts - Configuration options
* @returns {Function} Express/Connect-compatible middleware with additional methods
*/
function webpackHotMiddleware(compiler, opts);
interface MiddlewareOptions {
/** Function for logging or false to disable (default: console.log) */
log?: Function | false;
/** Path for event stream endpoint (default: '/__webpack_hmr') */
path?: string;
/** Heartbeat interval in milliseconds (default: 10000) */
heartbeat?: number;
/** Stats configuration object (default: {}) */
statsOptions?: Object;
}The middleware function includes additional methods:
interface MiddlewareInstance {
/** Manually publish events to connected clients */
publish(payload: Object): void;
/** Close the middleware and clean up resources */
close(): void;
}Usage Example:
const webpackHotMiddleware = require('webpack-hot-middleware');
// Basic usage
const hotMiddleware = webpackHotMiddleware(compiler);
app.use(hotMiddleware);
// With options
const hotMiddleware = webpackHotMiddleware(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
});
app.use(hotMiddleware);
// Manual event publishing
hotMiddleware.publish({
action: 'reload'
});
// Cleanup
hotMiddleware.close();Client-side module that connects to the HMR server and handles module updates.
/**
* Client module exports when used as CommonJS module
*/
interface ClientExports {
/** Subscribe to all HMR events */
subscribeAll(handler: Function): void;
/** Subscribe to custom HMR events */
subscribe(handler: Function): void;
/** Replace default error overlay with custom implementation */
useCustomOverlay(customOverlay: Object): void;
/** Set client options and establish connection */
setOptionsAndConnect(overrides: Object): void;
}Usage Examples:
// As webpack entry (automatic connection)
entry: {
main: ['webpack-hot-middleware/client', './src/main.js']
}
// As module for custom handling
const client = require('webpack-hot-middleware/client');
client.subscribe(function(obj) {
if (obj.action === 'reload') {
window.location.reload();
}
});
client.subscribeAll(function(obj) {
console.log('HMR event:', obj);
});Client behavior can be configured via query parameters when including in webpack entry.
interface ClientOptions {
/** Event stream endpoint path (default: '/__webpack_hmr') */
path?: string;
/** Bundle name for multi-compiler mode */
name?: string;
/** Reconnection timeout in milliseconds (default: 20000) */
timeout?: number;
/** Enable/disable error overlay (default: true) */
overlay?: boolean;
/** Enable auto-reload on webpack stuck (default: false) */
reload?: boolean;
/** Disable informational logging (default: false) */
noInfo?: boolean;
/** Disable all console logging (default: false) */
quiet?: boolean;
/** Use webpack publicPath as path prefix (default: false) */
dynamicPublicPath?: boolean;
/** Auto-connect to server (default: true) */
autoConnect?: boolean;
/** Custom ANSI colors for overlay */
ansiColors?: Object;
/** Custom styles for error overlay */
overlayStyles?: Object;
/** Show overlay for warnings (default: false) */
overlayWarnings?: boolean;
}Configuration Examples:
// Basic client configuration
entry: {
main: [
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true',
'./src/main.js'
]
}
// Multi-compiler configuration
module.exports = [
{
name: 'mobile',
entry: {
main: ['webpack-hot-middleware/client?name=mobile', 'mobile.js']
}
},
{
name: 'desktop',
entry: {
main: ['webpack-hot-middleware/client?name=desktop', 'desktop.js']
}
}
];
// Custom overlay colors and styles
const ansiColors = { red: '00FF00' };
const overlayStyles = { color: '#FF0000' };
const clientScript = 'webpack-hot-middleware/client?ansiColors=' +
encodeURIComponent(JSON.stringify(ansiColors)) +
'&overlayStyles=' + encodeURIComponent(JSON.stringify(overlayStyles));Browser overlay system for displaying compilation errors and warnings.
/**
* Creates customizable error overlay for browser
* @param {Object} options - Configuration with ansiColors and overlayStyles
* @returns {Object} Overlay instance with control methods
*/
function createOverlay(options: OverlayOptions): OverlayInstance;
interface OverlayOptions {
/** Custom ANSI color mappings */
ansiColors?: Object;
/** Custom CSS styles for overlay element */
overlayStyles?: Object;
}
interface OverlayInstance {
/** Display compilation problems in overlay */
showProblems(type: 'errors' | 'warnings', lines: string[]): void;
/** Remove overlay from DOM */
clear(): void;
}Usage Example:
const createOverlay = require('webpack-hot-middleware/client-overlay');
const overlay = createOverlay({
ansiColors: {
red: 'ff0000',
yellow: 'ffff00'
},
overlayStyles: {
fontSize: '14px',
fontFamily: 'Monaco, monospace'
}
});
// Show errors
overlay.showProblems('errors', [
'Module not found: Error: Cannot resolve module "missing-module"'
]);
// Clear overlay
overlay.clear();Utility functions used internally by the middleware.
/**
* URL path matching utility
* @param {string} url - URL string to test
* @param {string} path - Path string to match against
* @returns {boolean} True if paths match
*/
function pathMatch(url: string, path: string): boolean;The middleware communicates with clients using a defined event protocol over Server-Sent Events.
interface HMREvent {
/** Event action type */
action: 'building' | 'built' | 'sync';
/** Bundle name (for multi-compiler) */
name?: string;
/** Build completion time in milliseconds */
time?: number;
/** Build hash string */
hash?: string;
/** Compilation warnings */
warnings?: string[];
/** Compilation errors */
errors?: string[];
/** Module ID to name mapping */
modules?: Object;
}Webpack Hot Middleware supports webpack's multi-compiler mode for handling multiple webpack configurations simultaneously.
Configuration:
// webpack.config.js
module.exports = [
{
name: 'client',
entry: {
main: ['webpack-hot-middleware/client?name=client', './src/client.js']
},
// ... other client config
},
{
name: 'server',
entry: {
main: ['webpack-hot-middleware/client?name=server', './src/server.js']
},
// ... other server config
}
];
// Server setup
const compiler = webpack(configs);
app.use(webpackHotMiddleware(compiler));The middleware handles various error conditions and provides fallback mechanisms:
Required webpack configuration for hot module replacement:
// webpack.config.js
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.HotModuleReplacementPlugin()
],
entry: {
main: ['webpack-hot-middleware/client', './src/main.js']
}
};