# Configure for development

To configure Rsbuild for a development environment, execute the following steps 👇

# Install the packages

Open a terminal at the root of the project and install the following packages:

pnpm add -D @workleap/rsbuild-configs @workleap/browserslist-config @rsbuild/core @rspack/core browserslist nodemon
yarn add -D @workleap/rsbuild-configs @workleap/browserslist-config @rsbuild/core @rspack/core browserslist nodemon
npm install -D @workleap/rsbuild-configs @workleap/browserslist-config @rsbuild/core @rspack/core browserslist nodemon

# Configure Rsbuild

# HTML template

First, create a public folder with an index.html file at the root of the project:

web-project
├── public
├──── index.html
├── src
├──── ...
├── package.json

Then, open the newly created index.html file and copy/paste the following content:

public/index.html
<!DOCTYPE html>
<html>
    <head>
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>

The content of the public/index.html file will be the template used by Rsbuild HTML template feature.

# Reference local assets

To reference local assets such as a favicon.png in the default HTML template, it is recommended to preprend the relative path of every asset with the assetPrefix option of the Rsbuild config.

First, add the asset to the public folder at the root of the project:

web-project
├── public
├──── index.html
├──── favicon.png
├── src
├──── ...
├── package.json

Then, add the assets to the index.html file:

public/index.html
<!DOCTYPE html>
<html>
    <head>
        <link href="<%=assetPrefix%>/favicon.png" rel="icon">
    </head>
    <body>
        <div id="root"></div>
    </body>
</html>

# Browserslist

Next, let's set up Browserlist to define the minimum browser versions supported by the application. Rsbuild will automatically detect and load the browser versions from the nearest .browserslistrc configuration file.

First, create a browserslistrc file at the root of the project:

web-project
├── public
├──── index.html
├── src
├──── ...
├── .browserslistrc
├── package.json

Then, open the newly created file and extend the default configuration with the shared configuration provided by @workleap/browserslist-config:

.browserslistrc
extends @workleap/browserslist-config

# rsbuild.dev.ts

Next, create a configuration file named rsbuild.dev.ts at the root of the project:

web-project
├── public
├──── index.html
├── src
├──── ...
├── .browserslistrc
├── package.json
├── rsbuild.dev.ts

Then, open the newly created file and export the Rsbuild configuration by using the defineDevConfig(options) function:

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig();

# Use predefined options

The defineDevConfig(options) function can be used as shown in the previous example, however, if you wish to customize the default configuration, the function also accept a few predefined options to help with that 👇

# entry

  • Type: An object literal accepting any source.entry options.
  • Default: { index: "./src/index.tsx" }

Set Rsbuild source.entry option.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    entry: {
        index: "./src/another-entry.tsx"
    }
});

# https

  • Type: boolean or an object literal accepting any server.https options.
  • Default: false

Set Rsbuild server.https option and format Rsbuild dev.assetPrefix option accordingly.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    https: true
});

When true, a self-signed certificate will be generated with rsbuild-plugin-basic-ssl. To manually set a certificate, follow Rsbuild instructions.

# host

  • Type: string
  • Default: localhost

Set Rsbuild server.host option and format Rsbuild dev.assetPrefix option accordingly.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    host: "my-custom-host"
});

# port

  • Type: number
  • Default: 8080

Set Rsbuild server.port option and format Rsbuild dev.assetPrefix option accordingly.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    port: 1234
});

# assetPrefix

This option is the Rsbuild equivalent of webpack publicPath option.

  • Type: string
  • Default: ${https ? "https" : "http"}://${host}:${port}

Set Rsbuild dev.assetPrefix option.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    assetPrefix: "http://dev-host:8080"
});

If you're unsure of the asset prefix in advance, set the option to auto. Rsbuild will automatically determine the asset prefix using import.meta.url or document.currentScript.

rsbuild.build.ts
import { defineDevConfig  } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    assetPrefix: "auto"
});

# plugins

Append the provided Rsbuild plugins to the configuration.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";
import { pluginAssetsRetry } from "@rsbuild/plugin-assets-retry";

export default defineDevConfig({
    plugins: [pluginAssetsRetry()]
});

# html

  • Type: false or (defaultOptions: HtmlConfig) => HtmlConfig
  • Default: defaultOptions => defaultOptions

By default, Rsbuild will attempt to load an HTML template from the public/index.html file. To use Rsbuild's built-in HTML template instead, set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    html: false
});

To customize the default HTML template configuration, provide a function extending the default options.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";
import path from "path";

export default defineDevConfig({
    html: defaultOptions => {
        return {
            ...defaultOptions,
            template: path.resolve("./my-custom-index.html"),
        };
    }
});

# lazyCompilation

  • Type: boolean
  • Default: true

Whether or not to use lazy compilation. To disable lazy compilation, set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    lazyCompilation: false
});

# hmr

  • Type: boolean
  • Default: true

Whether or not to use HMR. To disable HMR set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    hmr: false
});

# fastRefresh

  • Type: boolean
  • Default: true

Whether or not to use Fast Refresh instead of use HMR. To disable fast refresh set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    fastRefresh: false
});

To customize the Fast Refresh configuration, provide a react function extending the default options.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    react: defaultOptions => {
        return {
            ...defaultOptions,
            reactRefreshOptions: {
                overlay: false
            }
        };
    }
});

# sourceMap

  • Type: false or an object literal accepting any output.sourceMap options.
  • Default: { js: "cheap-module-source-map", css: true }

Whether or not to generate source map. To disable source map, set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    sourceMap: false
});

To customize the source map configuration, provide an object literal.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    sourceMap: {
        css: false
    }
});

# overlay

  • Type: false
  • Default: undefined

Whether or not a full-screen overlay should be in the browser when there are compiler errors or warnings.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    overlay: false
});

# react

  • Type: false or (defaultOptions: PluginReactOptions) => PluginReactOptions
  • Default: defaultOptions => defaultOptions

Whether or not to transform React code. To disable React code transformation, set the option to false.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    react: false
});

To customize plugin-react, provide a function to extend the default options.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    react: defaultOptions => {
        return {
            ...defaultOptions,
            swcReactOptions: {
                ...(defaultOptions.swcReactOptions ?? {}),
                runtime: "classic"
            }
        };
    }
});

# svgr

  • Type: false or (defaultOptions: PluginSvgrOptions) => PluginSvgrOptions
  • Default: defaultOptions => defaultOptions

Whether or not to handle .svg files with plugin-svgr. When the option is set to false, the .svg files will be handled by the asset/resource rule.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    svgr: false
});

To customize the plugin-svgr, provide a function extending the default options.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    svgr: defaultOptions => {
        return {
            svgrOptions: {
                ...(defaultOptions.svgrOptions ?? {}),
                ref: true
            }
            ...defaultOptions,

        }
    }
});

# Typings

When you reference an SVG asset in TypeScript code, TypeScript may prompt that the module is missing a type definition:

TS2307: Cannot find module './logo.svg' or its corresponding type declarations.

To fix this, you need to add type declaration for the SVG assets, create a src/env.d.ts file, and add the type declaration.

src/env.d.ts
declare module '*.svg' {
  export const ReactComponent: React.FunctionComponent<
    React.SVGProps<SVGSVGElement>
  >;
}
declare module '*.svg?react' {
  const ReactComponent: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;
  export default ReactComponent;
}

For additional information, refer to the plugin documentation.

# Import images

By default, plugin-svgr is configured to support named import for ReactComponent:

import { ReactComponent as Logo } from "./logo.svg";

export const App = () => <Logo />;

# verbose

  • Type: boolean
  • Default: false

Start the Rsbuild process with verbose logging turned on.

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    verbose: true
});

# Configuration transformers

The predefined options are useful to quickly customize the default development configuration of @workleap/rsbuild-configs, but only covers a subset of an Rsbuild configuration. If you need full control over the configuration, you can provide configuration transformer functions through the transformers option of the defineDevConfig function. Remember, no locked in ❤️✌️.

To view the default development configuration of @workleap/rsbuild-configs, have a look at the dev.ts configuration file on GitHub.

# transformers

  • Type: ((config: RsbuildConfig, context: RsbuildConfigTransformerContext) => RsbuildConfig)[]
  • Default: []
transformer(config: RsbuildConfig, context: RsbuildConfigTransformerContext) => RsbuildConfig
rsbuild.dev.ts
import { defineDevConfig, type RsbuildConfig, type RsbuildConfigTransformer } from "@workleap/rsbuild-configs";

const forceNamedChunkIdsTransformer: RsbuildConfigTransformer = (config: RsbuildConfig) => {
    config.tools = config.tools ?? {};
    config.tools.rspack = config.tools.rspack ?? {};

    config.tools.rspack.optimization = {
        ...(config.tools.rspack.optimization ?? {}),
        chunkIds: "named"
    };

    return config;
};

export default defineDevConfig({
    transformers: [forceNamedChunkIdsTransformer]
});

# Execution context

Generic transformers can use the context parameter to gather additional information about their execution context, like the environment they are operating in.

transformer.ts
export const transformer: RsbuildConfigTransformer = (config: RsbuildConfig) => {
    if (context.environment === "dev") {
        config.tools = config.tools ?? {};
        config.tools.rspack = config.tools.rspack ?? {};

        config.tools.rspack.optimization = {
            ...(config.tools.rspack.optimization ?? {}),
            chunkIds: "named"
        };
    }

    return config;
}
  • environment: "dev" | "build" | "storybook"
  • verbose: boolean

# Setup nodemon

Nodemon is a utility that will monitor for any changes in the rsbuild.dev.dev.ts file and restart the Rsbuild development server whenever a change occurs.

First, add a nodemon.json file at the root of the project:

web-project
├── public
├──── index.html
├── src
├──── ...
├── package.json
├── rsbuild.dev.ts
├── nodemon.json

Then, open the nodemon.json file and copy/paste the following content:

nodemon.json
{
    "watch": ["rsbuild.dev.ts"],
    "exec": "rsbuild dev --config rsbuild.dev.ts"
}

Finally, add a CLI script at the next step of this guide.

# Add a CLI script

To initiate the development server, add the following script to your project package.json file:

package.json
{
    "dev": "nodemon"
}

# Define environment variables

# cross-env

We recommend to define environment variables using cross-env. With cross-env, the environment variables will be made available to any Node.js files that are executed by the script process (dev in the example below 👇):

package.json
{
    "dev": "cross-env DEBUG=true nodemon"
}
tsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

if (process.env.DEBUG) {
    console.log("Configuring Rsbuild in debug mode!");
}

export default defineDevConfig();

However, there's a catch. When using cross-env, the variables will not be available in the application files because cross-env only makes them available to files that are executed by the process at build time while the application files are executed at runtime by a browser.

To make them accessible to the application files, Rsbuild must be aware of those environment variables and render them into the compiled application files. This is the purpose of the environmentVariables option.

# environmentVariables

  • Type: Record<string, unknown>
  • Default: {}

First, define the variables with environmentVariables:

rsbuild.dev.ts
import { defineDevConfig } from "@workleap/rsbuild-configs";

export default defineDevConfig({
    environmentVariables: {
        "DEBUG": process.env.DEBUG === "true"
    }
});

Then, use the variables in any application files:

src/App.tsx
export function App() {
    if (process.env.DEBUG) {
        console.log("The application has been bootstrapped in debug!");
    }

    return null;
}

# CSS modules typings

When you import CSS Modules in TypeScript code, TypeScript may prompt that the module is missing a type definition:

TS2307: Cannot find module './index.module.css' or its corresponding type declarations.

To fix this, you need to add a type declaration file for the CSS Modules, please create a src/env.d.ts file, and add the corresponding type declaration.

env.d.ts
/// <reference types="@rsbuild/core/types" />

# Monorepo

If your solution is a monorepo, ensure that projects referencing your packages that include CSS Modules, also include the necessary type definitions

For example, given the following structure:

workspace
├── app
├──── tsconfig.ts
├── packages
├──── components
├────── src
├───────── Button.tsx
├───────── Button.module.css
├───────── env.d.ts
├───────── tsconfig.ts
├── package.json

Copy the CSS Modules typings into the app web application own env.d.ts file, or include the components package's typings into the apps web application tsconfig.ts configuration file:

app/tsconfig.ts
{
    "extends": "@workleap/typescript-configs/web-application.json",
    "include": [
        ".",
        "../**/src/env.d.ts"
    ],
    "exclude": ["public", "dist", "node_modules"]
}

# Try it 🚀

To test your new Rsbuild configuration, open a terminal at the root of the project and execute the CLI script added earlier. A development server should start without outputting any error in the terminal.