Dev server API
Rsbuild provides a set of dev server APIs and allows you to access them through plugin hooks or JavaScript API.
How to use
const myPlugin = () => ({
setup(api) {
api.onBeforeStartDevServer(({ server }) => {
console.log('the server is ', server);
});
},
});
- If you are using the JavaScript API of Rsbuild, you can create a dev server instance through the rsbuild.createDevServer method.
const server = await rsbuild.createDevServer();
console.log('the server is ', server);
Example
Integrate with custom server
Here is an example of integrating express with Rsbuild dev server:
import { createRsbuild } from '@rsbuild/core';
import express from 'express';
async function startDevServer() {
// Init Rsbuild
const rsbuild = await createRsbuild({
rsbuildConfig: {
server: {
middlewareMode: true,
},
},
});
const app = express();
// Create Rsbuild dev server instance
const rsbuildServer = await rsbuild.createDevServer();
// Apply Rsbuild's built-in middleware
app.use(rsbuildServer.middlewares);
const server = app.listen(rsbuildServer.port, async () => {
// Notify Rsbuild that the custom server has started
await rsbuildServer.afterListen();
});
// Activate WebSocket connection
rsbuildServer.connectWebSocket({ server });
}
For detailed usage, please refer to:
API
Type definitions
type EnvironmentAPI = {
[name: string]: {
/**
* Get stats info about current environment.
*/
getStats: () => Promise<Stats>;
/**
* Load and execute stats bundle in server.
*
* @param entryName - relate to Rsbuild's `source.entry`
* @returns the return value of entry module.
*/
loadBundle: <T = unknown>(entryName: string) => Promise<T>;
/**
* Get the compiled HTML template.
*/
getTransformedHtml: (entryName: string) => Promise<string>;
};
};
type RsbuildDevServer = {
/**
* The `connect` app instance.
* Can be used to attach custom middleware to the dev server.
*/
middlewares: Connect.Server;
/**
* The Node.js HTTP server instance.
* - Will be `Http2SecureServer` if `server.https` config is used.
* - Will be `null` if `server.middlewareMode` is enabled.
*/
httpServer:
| import('node:http').Server
| import('node:http2').Http2SecureServer
| null;
/**
* Start listening on the Rsbuild dev server.
* Do not call this method if you are using a custom server.
*/
listen: () => Promise<{
port: number;
urls: string[];
server: {
close: () => Promise<void>;
};
}>;
/**
* Environment API of Rsbuild server.
*/
environments: EnvironmentAPI;
/**
* The resolved port.
* By default, Rsbuild server listens on port `3000` and automatically increments the port number if the port is occupied.
*/
port: number;
/**
* Notifies Rsbuild that the custom server has successfully started.
* Rsbuild will trigger the `onAfterStartDevServer` hook at this stage.
*/
afterListen: () => Promise<void>;
/**
* Activates the WebSocket connection.
* This ensures that HMR works properly.
*/
connectWebSocket: (options: {
server: import('node:http').Server | import('node:http2').Http2SecureServer;
}) => void;
/**
* Close the Rsbuild server.
*/
close: () => Promise<void>;
/**
* Print the server URLs.
*/
printUrls: () => void;
/**
* Open URL in the browser after starting the server.
*/
open: () => Promise<void>;
/**
* Allows middleware to send some message to HMR client, and then the HMR
* client will take different actions depending on the message type.
* - `static-changed`: The page will reload.
*/
sockWrite: SockWrite;
};
type CreateDevServerOptions = {
/**
* Using a custom Rspack Compiler object.
*/
compiler?: Compiler | MultiCompiler;
/**
* Whether to get port silently and not print any logs.
* @default false
*/
getPortSilently?: boolean;
/**
* Whether to trigger Rsbuild compilation
* @default true
*/
runCompile?: boolean;
};
function CreateDevServer(
options?: CreateDevServerOptions,
): Promise<RsbuildDevServer>;
afterListen
- Type:
() => Promise<void>
Notifies Rsbuild that the custom server has successfully started. Rsbuild will trigger the onAfterStartDevServer hook at this stage.
For example:
import express from 'express';
import { createRsbuild } from '@rsbuild/core';
const rsbuild = await createRsbuild();
const rsbuildServer = await rsbuild.createDevServer();
const app = express();
const server = app.listen(rsbuildServer.port, async () => {
await rsbuildServer.afterListen();
});
close
- Type:
() => Promise<void>
Calling the close()
method to trigger the onCloseDevServer hook and perform necessary cleanup operations.
import { createRsbuild } from '@rsbuild/core';
const rsbuild = await createRsbuild();
const rsbuildServer = await rsbuild.createDevServer();
await rsbuildServer.close();
connectWebSocket
type ConnectWebSocket = (options: {
server: import('node:http').Server | import('node:http2').Http2SecureServer;
}) => void;
Activates the WebSocket connection. This ensures that HMR works properly.
Rsbuild has a builtin WebSocket handler to support HMR:
- When a user accesses a page through browser, a WebSocket connection request is automatically initiated to the server.
- After the Rsbuild dev server detects the connection request, it instructs the builtin WebSocket handler to process it.
- After the browser successfully establishes a connection with the Rsbuild WebSocket handler, real-time communication is possible.
- The Rsbuild WebSocket handler notifies the browser after each recompilation is complete. The browser then sends a
hot-update.(js|json)
request to the dev server to load the new compiled module.
When you use custom server, you may encounter HMR connection error problems. This is because the custom server does not forward WebSocket connection requests to Rsbuild's WebSocket handler.
At this time, you need to use the connectWebSocket
method to enable Rsbuild to sense and process the WebSocket connection request from the browser.
import express from 'express';
import { createRsbuild } from '@rsbuild/core';
const rsbuild = await createRsbuild();
const rsbuildServer = await rsbuild.createDevServer();
const app = express();
const httpServer = app.listen(rsbuildServer.port);
rsbuildServer.connectWebSocket({ server: httpServer });
environments
Provides Rsbuild's environment API, which allows you to get the build outputs information for a specific environment in the server side.
rsbuild.config.ts
const rsbuildServer = await rsbuild.createDevServer();
const webStats = await rsbuildServer.environments.web.getStats();
console.log(webStats.toJson({ all: false }));
sockWrite
- Type:
(type: 'static-changed') => void
Sends some message to HMR client, and then the HMR client will take different actions depending on the message type.
For example, if you send a 'static-changed'
message, the page will reload.
const rsbuildServer = await rsbuild.createDevServer();
if (someCondition) {
rsbuildServer.sockWrite('static-changed');
}
Sending content-changed
and static-changed
have the same effect. Since content-changed
has been deprecated, please use static-changed
instead.