Dev

This section describes some dev configurations in Rsbuild.

dev.assetPrefix

  • Type: boolean | string
  • Default: '/'

Set the URL prefix of static assets in the development environment.

assetPrefix will affect the URLs of most of the static assets, including JavaScript files, CSS files, images, videos, etc. If an incorrect value is specified, you'll receive 404 errors while loading these resources.

This config is only used in the development environment. In the production environment, please use the output.assetPrefix to set the URL prefix.

Boolean Type

If assetPrefix is set to true, the URL prefix will be http://localhost:port/:

export default {
  dev: {
    assetPrefix: true,
  },
};

The script URL will be:

<script defer src="http://localhost:8080/static/js/main.js"></script>

If assetPrefix is set to false or not set, / is used as the default value.

String type

When the value of assetPrefix is string type, the string will be used as the URL prefix:

export default {
  dev: {
    assetPrefix: 'http://example.com/assets/',
  },
};

The script URL will be:

<script defer src="http://example.com/assets/static/js/main.js"></script>

Differences from Native Configuration

dev.assetPrefix corresponds to the following native configurations:

The differences from the native configuration are as follows:

  • dev.assetPrefix only takes effect in the development environment.
  • dev.assetPrefix automatically appends a trailing / by default.
  • The value of dev.assetPrefix is written to the process.env.ASSET_PREFIX environment variable.

dev.beforeStartUrl

  • Type: () => Promise<void> | void
  • Default: undefined

dev.beforeStartUrl is used to execute a callback function before opening the startUrl, this config needs to be used together with dev.startUrl.

export default {
  dev: {
    startUrl: true,
    beforeStartUrl: async () => {
      await doSomeThing();
    },
  },
};

dev.client

  • Type:
{
    /** Specify a protocol to use */
    protocol?: string;
    /** The path which the middleware is serving the event stream on */
    path?: string;
    /** Specify a port number to listen for requests on */
    port?: string;
    /** Specify a host to use */
    host?: string;
}
  • Default:
const defaultConfig = {
  path: '/rsbuild-hmr',
  // By default it is set to the port number of the dev server
  port: '',
  // By default it is set to "location.hostname"
  host: '',
  // By default it is set to "location.protocol === 'https:' ? 'wss' : 'ws'""
  protocol: '',
};

The config of HMR client, which are usually used to set the WebSocket URL of HMR.

dev.compress

  • Type: boolean
  • Default: true

Whether to enable gzip compression for served static assets.

If you want to disable the gzip compression, you can set compress to false:

export default {
  dev: {
    compress: false,
  },
};

dev.devMiddleware

  • Type:
{
  writeToDisk: boolean | ((filename: string) => boolean);
}
  • Default:
{
  writeToDisk: (file: string) => !file.includes('.hot-update.'),
}

The config of devMiddleware. Current options is the subset of webpack-dev-middleware.

dev.headers

  • Type: Record<string, string>
  • Default: undefined

Adds headers to all responses.

export default {
  dev: {
    headers: {
      'X-Custom-Foo': 'bar',
    },
  },
};

dev.historyApiFallback

  • Type: boolean | ConnectHistoryApiFallbackOptions
  • Default: false

The index.html page will likely have to be served in place of any 404 responses. Enable dev.historyApiFallback by setting it to true:

export default {
  dev: {
    historyApiFallback: true,
  },
};

For example, if you use client-side routing and want all page requests to fallback to index.html, you can configure it as follows:

export default {
  dev: {
    historyApiFallback: {
      rewrites: [{ from: /.*\.html/, to: '/index.html' }],
    },
  },
};

For more options and information, see the connect-history-api-fallback documentation.

dev.hmr

  • Type: boolean
  • Default: true

Whether to enable Hot Module Replacement.

If hmr is set to false, the HMR and react-refresh will no longer work.

export default {
  dev: {
    hmr: false,
  },
};

dev.host

  • Type: string
  • Default: 0.0.0.0

Specify the host that the dev server listens to.

By default, the dev server will listen to 0.0.0.0, which means listening to all network interfaces, including localhost and public network addresses.

If you want the dev server to listen only on localhost, you can set it to:

export default {
  dev: {
    host: 'localhost',
  },
};

dev.https

  • Type: boolean | { key: string; cert: string }
  • Default: false

After configuring this option, you can enable HTTPS Dev Server, and disabling the HTTP Dev Server.

HTTP:

  > Local: http://localhost:8080/
  > Network: http://192.168.0.1:8080/

HTTPS:

  > Local: https://localhost:8080/
  > Network: https://192.168.0.1:8080/

Automatically generate certificates

You can directly set https to true, Rsbuild will automatically generate the HTTPS certificate based on devcert.

When using this method, you need to manually install the devcert dependency in your project:

# npm
npm install devcert@1.2.2 -D

# yarn
yarn add devcert@1.2.2 -D

# pnpm
pnpm add devcert@1.2.2 -D

Then configure dev.https to true:

export default {
  dev: {
    https: true,
  },
};

The devcert has some limitations, it does not currently support IP addresses yet.

TIP

The https proxy automatically installs the certificate and needs root authority, please enter the password according to the prompt.The password is only used to trust the certificate, and will not be leaked or be used elsewhere.

Manually set the certificate

You can also manually pass in the certificate and the private key required in the dev.https option. This parameter will be directly passed to the createServer method of the https module in Node.js.

For details, please refer to https.createServer.

import fs from 'fs';

export default {
  dev: {
    https: {
      key: fs.readFileSync('certificates/private.pem'),
      cert: fs.readFileSync('certificates/public.pem'),
    },
  },
};

dev.port

  • Type: number
  • Default: 8080

Specify a port number for Dev Server to listen.

By default, Dev Server listens on port 8080 and automatically increments the port number when the port is occupied.

Example

Set the port to 3000:

export default {
  dev: {
    port: 3000,
  },
};

dev.progressBar

  • Type:
type ProgressBar =
  | boolean
  | {
      id?: string;
    };
  • Default: process.env.NODE_ENV === 'production'

Whether to display progress bar during compilation.

By default, Rsbuild only enables the progress bar when production building.

  • Example: Enable the progress bar.
export default {
  dev: {
    progressBar: true,
  },
};
  • Example: Disable the progress bar.
export default {
  dev: {
    progressBar: false,
  },
};
  • Example: Modify the progress bar id

If you need to modify the text displayed on the left side of the progress bar, you can set the id option:

export default {
  dev: {
    progressBar: {
      id: 'Some Text',
    },
  },
};

dev.proxy

  • Type: Record<string, string> | Record<string, ProxyDetail>
  • Default: undefined

Proxying some URLs.

export default {
  dev: {
    proxy: {
      '/api': 'http://localhost:3000',
    },
  },
};

A request to /api/users will now proxy the request to http://localhost:3000/api/users.

If you don't want /api to be passed along, we need to rewrite the path:

export default {
  dev: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: { '^/api': '' },
      },
    },
  },
};

The DevServer Proxy makes use of the http-proxy-middleware package. Check out its documentation for more advanced usages.

The full type definition of DevServer Proxy is:

import type { Options as HttpProxyOptions } from 'http-proxy-middleware';

type ProxyDetail = HttpProxyOptions & {
  bypass?: (
    req: IncomingMessage,
    res: ServerResponse,
    proxyOptions: ProxyOptions,
  ) => string | undefined | null | false;
  context?: string | string[];
};

type ProxyOptions =
  | Record<string, string>
  | Record<string, ProxyDetail>
  | ProxyDetail[]
  | ProxyDetail;

In addition to the http-proxy-middleware option, we also support the bypass and context configuration:

  • bypass: bypass the proxy based on the return value of a function.
    • Return null or undefined to continue processing the request with proxy.
    • Return false to produce a 404 error for the request.
    • Return a path to serve from, instead of continuing to proxy the request.
  • context: If you want to proxy multiple, specific paths to the same target, you can use an array of one or more objects with a context property.
// custom bypass
export default {
  dev: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        bypass: function (req, res, proxyOptions) {
          if (req.headers.accept.indexOf('html') !== -1) {
            console.log('Skipping proxy for browser request.');
            return '/index.html';
          }
        },
      },
    },
  },
};
// proxy multiple
export default {
  dev: {
    proxy: [
      {
        context: ['/auth', '/api'],
        target: 'http://localhost:3000',
      },
    ],
  },
};

dev.setupMiddlewares

  • Type:
Array<
  (
    middlewares: {
      unshift: (...handlers: RequestHandler[]) => void;
      push: (...handlers: RequestHandler[]) => void;
    },
    server: {
      sockWrite: (
        type: string,
        data?: string | boolean | Record<string, any>,
      ) => void;
    },
  ) => void
>;
  • Default: undefined

Provides the ability to execute a custom function and apply custom middlewares.

The order among several different types of middleware is: unshift => internal middlewares => push.

export default {
  dev: {
    setupMiddlewares: [
      (middlewares, server) => {
        middlewares.unshift((req, res, next) => {
          next();
        });

        middlewares.push((req, res, next) => {
          next();
        });
      },
    ],
  },
};

It is possible to use some server api to meet special scenario requirements:

  • sockWrite. Allow send some message to hmr client, and then the hmr client will take different actions depending on the message type. If you send a "content changed" message, the page will reload.
export default {
  dev: {
    setupMiddlewares: [
      (middlewares, server) => {
        // add custom watch & trigger page reload when change
        watcher.on('change', (changed) => {
          server.sockWrite('content-changed');
        });
      },
    ],
  },
};

dev.startUrl

  • Type: boolean | string | string[] | undefined
  • Default: undefined

dev.startUrl is used to set the URL of the page that automatically opens in the browser when Dev Server starts.

By default, no page will be opened.

You can set it to the following values:

export default {
  dev: {
    // Open the project's default preview page, equivalent to `http://localhost:<port>`
    startUrl: true,
    // Open the specified page
    startUrl: 'http://localhost:8080',
    // Open multiple pages
    startUrl: ['http://localhost:8080', 'http://localhost:8080/about'],
  },
};

Port placeholder

Since the port number may change, you can use the <port> placeholder to refer to the current port number, and Rsbuild will automatically replace the placeholder with the actual listening port number.

export default {
  dev: {
    startUrl: 'http://localhost:<port>/home',
  },
};

Open the specified browser

On MacOS, you can open the specified browser when Dev Server starts, by set environment variable BROWSER, support values:

  • Google Chrome Canary
  • Google Chrome Dev
  • Google Chrome Beta
  • Google Chrome
  • Microsoft Edge
  • Brave Browser
  • Vivaldi
  • Chromium