This guide covers breaking changes you need to handle when upgrading @rspack/dev-server from v1 to v2.
Node.js 18 is no longer supported in v2.
The minimum supported Node.js version is now ^20.19.0 || >=22.12.0.
@rspack/dev-server v2 is designed to work with Rspack v2. Rspack v1 is no longer supported in v2.
@rspack/dev-server is now published as pure ESM package.
http-proxy-middleware has been updated from v2 to v4, with several breaking changes introduced since v3:
proxy[].pathis removed. UsepathFilter(orcontext) instead.
{
- path: '/api',
+ pathFilter: '/api',
}logLevel/logProviderare replaced bylogger.
- logLevel: 'warn',
+ logger: console,onProxyReq/onProxyRes/onProxyReqWsare moved toon: { ... }.
- onProxyReq(proxyReq) {
- proxyReq.setHeader('x-from', 'dev-server');
- },
+ on: {
+ proxyReq(proxyReq) {
+ proxyReq.setHeader('x-from', 'dev-server');
+ },
+ },proxy[].bypassis removed, usepathFilterorrouterinstead.- When
bypasswas used and that function returned a boolean, it would automatically result in a 404 request. This can’t be achieved in a similar way now, or, if it returned a string, you can do what was done in the example above. bypassalso allowed sending data; this can no longer be done. If you really need to do it, you’d have to create a new route in the proxy that sends the same data, or alternatively create a new route on the main server and, following the example above, send the data you wanted.
- When
Refer to the http-proxy-middleware v3 migration guide for details.
When devServer.app is omitted, @rspack/dev-server now creates a
connect-next app instead of an Express app.
The dev server only needs a minimal middleware pipeline. connect-next is an actively maintained fork of Connect that keeps the same (req, res, next) middleware interface while staying smaller than Express and having fewer dependencies.
If you relied on Express-only APIs on devServer.app, such as app.get(),
app.post(), or res.send(), provide your own Express app explicitly:
import express from 'express';
export default {
devServer: {
app: async () => express(),
},
};@rspack/dev-server v2 upgrades the underlying file watcher chokidar from v3 to v5.
One important breaking change in chokidar v4+ is that glob patterns are no longer supported.
If you previously passed glob patterns such as **/*.js or ./directory/**/* to devServer.watchFiles, you can watch a directory and filter with ignored:
// Before
export default {
devServer: {
watchFiles: '**/*.js',
},
};
// After
export default {
devServer: {
watchFiles: {
paths: '.',
options: {
ignored: (path, stats) =>
stats?.isFile() && !path.endsWith('.js'),
},
},
},
};Or use node:fs/promises to expand the glob first:
import { glob } from 'node:fs/promises';
export default async () => ({
devServer: {
watchFiles: await Array.fromAsync(glob('**/*.js')),
},
});server.type: "spdy"is no longer supported.server.options.spdyis no longer supported.
You can switch to server.type: "http2" or "https" instead.
// Before
export default {
devServer: {
server: {
type: 'spdy',
options: {
spdy: { protocols: ['h2', 'http/1.1'] },
},
},
},
};
// After
export default {
devServer: {
server: {
type: 'http2', // or 'https'
options: {},
},
},
};
Array.fromAsync()requires Node.js 22+.
selfsigned is no longer bundled as a direct dependency of @rspack/dev-server.
If you use server.type: "https" or "http2" without providing your own
server.options.key and server.options.cert, the dev server needs
selfsigned to generate a local certificate.
Install it in your project when needed:
npm i -D selfsigned@^5.0.0
# or pnpm add -D selfsigned@^5.0.0
# or yarn add -D selfsigned@^5.0.0
# or bun add -D selfsigned@^5.0.0devServer.static.serveIndex is removed in v2 to reduce third-party dependencies.
If you still need directory listings for a static directory, install serve-index and register it with setupMiddlewares:
npm i -D serve-index
# or pnpm add -D serve-index
# or yarn add -D serve-index
# or bun add -D serve-indeximport path from 'node:path';
import serveIndex from 'serve-index';
const publicDirectory = path.join(import.meta.dirname, 'public');
export default {
devServer: {
static: {
directory: publicDirectory,
},
setupMiddlewares: (middlewares) => {
middlewares.push({
name: 'serve-index',
// The same as `static.publicPath`
path: '/',
middleware: serveIndex(publicDirectory, { icons: true }),
});
return middlewares;
},
},
};In v2, the following SockJS options are no longer available:
webSocketServer: "sockjs"webSocketServer: { type: "sockjs" }client.webSocketTransport: "sockjs"webSocketServer.options.prefix(usepath)
Also, SockJS bundle routes were removed.
// Before
export default {
devServer: {
webSocketServer: 'sockjs',
client: {
webSocketTransport: 'sockjs',
},
},
};
// After
export default {
devServer: {
webSocketServer: 'ws',
client: {
webSocketTransport: 'ws',
},
},
};If you need a non-default transport/server, you can provide a custom implementation path instead of 'sockjs'.
Built-in Bonjour support is removed in v2.
If Bonjour/ZeroConf broadcasting is still important for your workflow, consider integrating bonjour-service directly in your app code.
If your setup still uses the legacy names, you can update them as follows:
- Environment variables
WEBPACK_DEV_SERVER_BASE_PORT->RSPACK_DEV_SERVER_BASE_PORTWEBPACK_DEV_SERVER_PORT_RETRY->RSPACK_DEV_SERVER_PORT_RETRYWEBPACK_SERVE->RSPACK_SERVE
- URL query flags
webpack-dev-server-hot=false->rspack-dev-server-hot=falsewebpack-dev-server-live-reload=false->rspack-dev-server-live-reload=false
- Built-in routes
/webpack-dev-server/*->/rspack-dev-server/*
# Before
http://localhost:8080/?webpack-dev-server-hot=false&webpack-dev-server-live-reload=false
GET /webpack-dev-server/invalidate
GET /webpack-dev-server/open-editor?fileName=...
# After
http://localhost:8080/?rspack-dev-server-hot=false&rspack-dev-server-live-reload=false
GET /rspack-dev-server/invalidate
GET /rspack-dev-server/open-editor?fileName=...