--- url: /guide/start/index.md --- # Introduction Rsbuild is a high-performance build tool powered by Rspack. It provides a set of thoughtfully designed default build configs, offering an out-of-the-box development experience and can fully unleash the performance advantages of Rspack. Rsbuild provides [rich build features](/guide/start/features.md), including the compilation of TypeScript, JSX, Sass, Less, CSS Modules, Wasm, and others. It also supports Module Federation, image compression, type checking, PostCSS, Lightning CSS, and more. ## 🚀 Performance Powered by Rspack's Rust-based architecture, Rsbuild delivers blazing fast performance that will reshape your development workflow. ⚡️ **Build 1000 React components:** > 📊 Benchmark results from [build-tools-performance](https://github.com/rspack-contrib/build-tools-performance). ## 💡 Comparisons Rsbuild is a build tool that is on par with [Vite](https://vitejs.dev/), [Create React App](https://github.com/facebook/create-react-app), or [Vue CLI](https://github.com/vuejs/vue-cli). They all come with builtin dev servers, command line tools, and sensible build configurations to provide the out-of-the-box experience. ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-1-0-build-tools.png) ### CRA / Vue CLI You can think of Rsbuild as a modernized version of Create React App or Vue CLI, with these main differences: * The underlying bundler is switched from webpack to Rspack, providing 5 to 10 times the build performance. * It is decoupled from frontend UI frameworks and supports all UI frameworks via [plugins](/plugins/list/index.md), including React, Vue, Svelte, Solid, etc. * It offers better extensibility. You can extend Rsbuild flexibly via [Configurations](/config/index.md), [Plugin API](/plugins/dev/index.md), and [JavaScript API](/api/start/index.md). ### Vite Rsbuild shares many similarities with Vite, as they both aim to improve the frontend development experience. The main differences are: * **Production consistency**: Rsbuild uses Rspack for bundling during both the development and production builds, thus ensuring a high level of consistency between the development and production outputs. Vite, on the other hand, uses ESM for module loading during development, which improves the startup speed, but may lead to inconsistencies between the development and production outputs. * **Ecosystem compatibility**: Rsbuild is compatible with most webpack plugins and all Rspack plugins, while Vite is compatible with Rollup plugins. If you're currently using more plugins and loaders from the webpack ecosystem, migrating to Rsbuild would be relatively easy. * **Module Federation**: The Rsbuild team works closely with the [Module Federation](/guide/advanced/module-federation.md) development team, providing first-class support for Module Federation to help you develop large web applications with micro frontend architecture. ## 🔥 Features Rsbuild has the following features: * **Easy to Configure**: One of the goals of Rsbuild is to provide out-of-the-box build capabilities for Rspack users, allowing developers to start a web project with zero configuration. In addition, Rsbuild provides semantic build configuration to reduce the learning curve for Rspack configuration. * **Performance Oriented**: Rsbuild integrates high-performance Rust-based tools from the community, including [Rspack](https://rspack.dev), [SWC](https://swc.rs/) and [Lightning CSS](https://lightningcss.dev/), to deliver first-class build speed and development experience. * **Plugin Ecosystem**: Rsbuild has a lightweight plugin system and includes a range of high-quality official plugins. Furthermore, Rsbuild is compatible with most webpack plugins and all Rspack plugins, allowing users to leverage existing community or in-house plugins in Rsbuild without the need for rewriting code. * **Stable Artifacts**: Rsbuild is designed with a strong focus on the stability of build artifacts. It ensures high consistency between artifacts in the development and production builds, and automatically completes syntax downgrading and polyfill injection. Rsbuild also provides plugins for type checking and artifact syntax validation to prevent quality and compatibility issues in production code. * **Framework Agnostic**: Rsbuild is not coupled with any front-end UI framework. It supports frameworks like React, Vue, Svelte, Solid, and Preact through plugins, and plans to support more UI frameworks from the community in the future. ## 🎯 Ecosystem Rsbuild provides JavaScript API and plugin API for higher-level frameworks and tools. For example, we have implemented [Rspress](https://github.com/web-infra-dev/rspress) and [Rslib](https://github.com/web-infra-dev/rslib) based on Rsbuild, taking full advantage of its capabilities and ecosystem. The following diagram illustrates Rsbuild's position in the Rstack ecosystem: ## 🦀 Links * [Rspack](https://github.com/web-infra-dev/rspack): Fast Rust-based web bundler. * [Rspress](https://github.com/web-infra-dev/rspress): Static site generator based on Rsbuild. * [Rsdoctor](https://github.com/web-infra-dev/rsdoctor): Build analyzer for Rspack. * [Rslib](https://github.com/web-infra-dev/rslib): Library development tool powered by Rsbuild. * [Rstest](https://github.com/web-infra-dev/rstest): Testing framework powered by Rspack. * [Modern.js](https://github.com/web-infra-dev/modern.js): A progressive React framework based on Rsbuild. * [awesome-rspack](https://github.com/web-infra-dev/awesome-rspack): A curated list of awesome things related to Rspack and Rsbuild. * [rstack-examples](https://github.com/rspack-contrib/rstack-examples): Examples showcasing Rstack tools (Rspack, Rsbuild, Rspress, Rsdoctor). * [storybook-rsbuild](https://github.com/rspack-contrib/storybook-rsbuild): Storybook builder powered by Rsbuild. * [rsbuild-plugin-template](https://github.com/rspack-contrib/rsbuild-plugin-template): Use this template to create your own Rsbuild plugin. * [rstack-design-resources](https://github.com/rspack-contrib/rstack-design-resources): Design resources for Rspack, Rsbuild, Rspress and Rsdoctor. ## 🧑‍💻 Community Come and chat with us on [Discord](https://discord.gg/XsaKEEk4mW)! The Rspack / Rsbuild team and users are active there, and we're always looking for contributions. ## ✨ Next step You may want: --- url: /guide/start/quick-start.md --- # Quick start ## Online example We provide an online example based on Rsbuild. The example gives an intuitive feel for the build performance of Rspack and the development experience of Rsbuild: * [Rsbuild CodeSandbox example](https://codesandbox.io/p/github/rspack-contrib/rsbuild-codesandbox-example) ## Setup environment Rsbuild supports using [Node.js](https://nodejs.org/), [Deno](https://deno.com/), or [Bun](https://bun.sh/) as the runtime. ### Node.js For Node.js, you will need to install Node.js >= version 16, it is recommended to use the Node.js LTS version. Check the current Node.js version with the following command: ```bash node -v ``` If you do not have Node.js installed in current environment, or the installed version is too low, you can use [nvm](https://github.com/nvm-sh/nvm) or [fnm](https://github.com/Schniz/fnm) to install. Here is an example of how to install via nvm: ```bash # Install Node.js LTS nvm install --lts # Switch to Node.js LTS nvm use --lts ``` ## Create an Rsbuild application Use `create-rsbuild` to create a new Rsbuild application. Run the following command: Follow the prompts step by step. During the creation process, you can choose whether you need additional tools like TypeScript, ESLint, etc. After the application is created, you can follow these steps: * Run `git init` to initialize the Git repository. * Run `npm install` (or the install command of your package manager) to install npm dependencies. * Run `npm run dev` to start the development server, which runs on `localhost:5173` by default. ### Templates When creating an application, you can choose from the following templates provided by `create-rsbuild`: | Template | Description | Optional Features | | -------- | ------------------------------- | ----------------- | | vanilla | Vanilla JavaScript | TypeScript | | react | [React 19](https://react.dev/) | TypeScript | | react18 | [React 18](https://react.dev/) | TypeScript | | vue | [Vue 3](https://vuejs.org/) | TypeScript | | vue2 | [Vue 2](https://v2.vuejs.org/) | TypeScript | | lit | [Lit](https://lit.dev/) | TypeScript | | preact | [Preact](https://preactjs.com/) | TypeScript | | svelte | [Svelte 5](https://svelte.dev/) | TypeScript | | solid | [Solid](https://solidjs.com/) | TypeScript | `create-rsbuild` provides out-of-the-box basic templates. You can also get more templates through the following ways: * Visit [Rspack - Ecosystem](https://rspack.dev/guide/start/quick-start#ecosystem) to learn about various higher-level tools based on Rsbuild. * Visit [awesome-rspack - Starter](https://github.com/web-infra-dev/awesome-rspack?tab=readme-ov-file#starter) to get more community-maintained templates. ### Optional tools `create-rsbuild` can help you set up some commonly used tools, including [Biome](https://github.com/biomejs/biome), [ESLint](https://github.com/eslint/eslint), and [prettier](https://github.com/prettier/prettier). You can use the arrow keys and the space bar to make your selections. If you don't need these tools, you can simply press Enter to skip. ``` ◆ Select additional tools (Use to select, to continue) │ ◻ Add Biome for code linting and formatting │ ◻ Add ESLint for code linting │ ◻ Add Prettier for code formatting └ ``` :::tip Biome provides similar linting and formatting features to ESLint and Prettier. If you select Biome, you typically won't need to choose ESLint or Prettier as well. ::: ### Current directory To create an application in the current directory, set the target folder to `.`: ``` ◆ Create Rsbuild Project │ ◇ Project name or path │ . │ ◇ "." is not empty, please choose: │ Continue and override files ``` ### Quick creation [create-rsbuild](https://npmjs.com/package/create-rsbuild) provides some CLI flags. By setting these CLI flags, you can skip the interactive selection steps and create the application with one command. For example, to create a React application in the `my-app` directory with one command: ```bash npx create-rsbuild --dir my-app --template react # Using abbreviations npx create-rsbuild -d my-app -t react ``` All the CLI flags of `create-rsbuild`: ``` Usage: create-rsbuild [options] Options: -h, --help display help for command -d, --dir create project in specified directory -t, --template specify the template to use --tools select additional tools (biome, eslint, prettier) --override override files in target directory Templates: react-js, react-ts, vue3-js, vue3-ts, vue2-js, vue2-ts, svelte-js, svelte-ts, solid-js, solid-ts, vanilla-js, vanilla-ts ``` ## Migrate from existing projects To migrate from an existing project to Rsbuild, refer to the following guides: * [Migrate from webpack](/guide/migration/webpack.md) * [Migrate from Create React App](/guide/migration/cra.md) * [Migrate from Vue CLI](/guide/migration/vue-cli.md) * [Migrate from Vite](/guide/migration/vite.md) * [Migrate from Modern.js Builder](/guide/migration/modern-builder.md) * [Migrate from Tsup to Rslib](https://lib.rsbuild.dev/guide/migration/tsup) * [Migrate from Storybook to Storybook Rsbuild](https://rspack.dev/guide/migration/storybook) ### Other projects If your project does not belong to the above migration guides, you can manually install the [@rsbuild/core](https://npmjs.com/package/@rsbuild/core) package: After installation, you can refer to the following documents to configure your project: * See [CLI](/guide/basic/cli.md) to learn about available CLI commands. * See [Plugin List](/plugins/list/index.md) to select Rsbuild plugins. * See [Configure Rsbuild](/guide/configuration/rsbuild.md) to configure Rsbuild. ## CLI Rsbuild comes with a lightweight CLI that includes commands such as `dev` and `build`. ```json title="package.json" { "scripts": { // starting the dev server "dev": "rsbuild dev", // build the app for production "build": "rsbuild build", // preview the production build locally "preview": "rsbuild preview" } } ``` Refer to the [CLI](/guide/basic/cli.md) to learn about all available commands and options. ## Entry module By default, Rsbuild CLI uses `src/index.(js|ts|jsx|tsx)` as the entry module. You can modify the entry module using the [source.entry](/config/source/entry.md) option. ```ts title="rsbuild.config.ts" export default { source: { entry: { foo: './src/pages/foo/index.ts', bar: './src/pages/bar/index.ts', }, }, }; ``` ## Core packages ### @rsbuild/core Rsbuild core package, providing CLI commands and JavaScript API. ### create-rsbuild Create a new Rsbuild project. ## Next step You may want: --- url: /guide/start/features.md --- # Features Here are all the main features supported by Rsbuild. ## JavaScript | Features | Description | Links | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | Rspack | Use Rspack as the bundler by default | [Configure Rspack](/guide/configuration/rspack.md) | | SWC compilation | Transform and minify JavaScript and TypeScript code with SWC by default | [Configure SWC](/guide/configuration/swc.md) | | TS compilation | TS files are compiled by SWC by default | [TypeScript compilation](/guide/basic/typescript.md#typescript-compilation) | | Code minification | Code minification is enabled by default in production mode | [output.minify](/config/output/minify.md) | | Polyfill injection | Optional feature, inject core-js and other polyfills | [Browser compatibility](/guide/advanced/browser-compatibility.md)[output.polyfill](/config/output/polyfill.md) | | SourceMap generation | Source maps are generated in development mode by default | [output.sourceMap](/config/output/source-map.md) | | Alias | Optional feature, set import alias | [resolve.alias](/config/resolve/alias.md) | | Babel compilation | Optional feature, use Babel to transform JavaScript and TypeScript code | [Babel plugin](/plugins/list/plugin-babel.md) | | Node outputs | Optional feature, building bundles that run in Node.js environment | [Node target](/config/output/target.md#node-target) | | Web Workers | Optional feature, use Web Workers | [Web Workers](/guide/basic/web-workers.md) | | Browserslist | Optional feature, using browserslist (opens new window) to specify which browsers should be supported in your web application. | [Browserslist](/guide/advanced/browserslist.md) | | Compatibility check | Optional feature, analyze if there are incompatible advanced syntax in the outputs within the current browser scope | [@rsbuild/plugin-check-syntax](https://github.com/rspack-contrib/rsbuild-plugin-check-syntax) | | Environment variable | Optional feature, inject environment variables or expressions into the code | [Environment variables](/guide/advanced/env-vars.md) | | Node polyfill | Optional feature, inject polyfills for Node core modules on the browser side | [Node polyfill plugin](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) | | Type check | Optional feature, run type checker to check for type issues in code | [Type checking](/guide/basic/typescript.md#type-checking) | | Module Federation | Optional feature, dynamically load modules and share dependencies | [Module Federation](/guide/advanced/module-federation.md) | ## CSS | Features | Description | Links | | ----------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | | Lightning CSS | Use Lightning CSS to downgrade CSS syntax by default | [CSS](/guide/styling/css-usage.md) | | PostCSS transformation | Optional feature, use PostCSS to transform CSS files | [CSS](/guide/styling/css-usage.md)[tools.postcss](/config/tools/postcss.md) | | Tailwind CSS | Optional feature, use Tailwind CSS | [Tailwind CSS](/guide/styling/tailwindcss.md) | | UnoCSS | Optional feature, use UnoCSS | [UnoCSS](/guide/styling/unocss.md) | | Sass preprocessing | Optional feature, compile Sass/Scss files | [CSS](/guide/styling/css-usage.md)[Sass plugin](/plugins/list/plugin-sass.md) | | Less preprocessing | Optional feature, compile Less files | [CSS](/guide/styling/css-usage.md)[Less plugin](/plugins/list/plugin-less.md) | | Stylus preprocessing | Optional feature, compile Stylus files | [CSS](/guide/styling/css-usage.md)[Stylus plugin](/plugins/list/plugin-stylus.md) | | CSS Modules compilation | Support compiling `*.module.*` files by default | [CSS Modules](/guide/styling/css-modules.md)[tools.cssLoader](/config/tools/css-loader.md) | | CSS Modules type | Optional feature, generate type definition for CSS Modules | [Typed CSS Modules plugin](https://github.com/rspack-contrib/rsbuild-plugin-typed-css-modules) | | CSS minification | CSS minification is enabled by default in production build | [CSS](/guide/styling/css-usage.md) | | Inline CSS into JS | Optional feature, inline CSS files to JavaScript files | [CSS](/guide/styling/css-usage.md)[output.injectStyles](/config/output/inject-styles.md) | ## HTML | Features | Description | Links | | ------------------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | Set title | Set HTML `` tag | [Set page title](/guide/basic/html-template.md#set-page-title)[html.title](/config/html/title.md) | | Set meta | Set HTML `<meta>` tag | [Set meta tags](/guide/basic/html-template.md#set-meta-tags)[html.meta](/config/html/meta.md) | | Set favicon | Set favicon | [Set page icon](/guide/basic/html-template.md#set-page-icon)[html.favicon](/config/html/favicon.md) | | Set app icon | Set web application icons | [Set page icon](/guide/basic/html-template.md#set-page-icon)[html.appIcon](/config/html/app-icon.md) | | EJS template engine | Optional feature, use EJS template engine | [HTML template - EJS](/guide/basic/html-template.md#ejs) | | Pug template engine | Optional feature, use pug template engine | [Pug plugin](https://github.com/rspack-contrib/rsbuild-plugin-pug) | | Inline JS files | Optional feature, inline JS files into HTML | [Inline static assets](/guide/optimization/inline-assets.md)[output.inlineScripts](/config/output/inline-scripts.md) | | Inline CSS files | Optional feature, inline CSS files into HTML | [Inline static assets](/guide/optimization/inline-assets.md)[output.inlineStyles](/config/output/inline-styles.md) | ## Server | Features | Description | Links | | ----------------- | ------------------------------------------------------------------------------ | ---------------------------------------------------------------- | | Public dir | Use the public directory as the directory for serving public assets by default | [server.publicDir](/config/server/public-dir.md) | | SSR | Optional feature, implement server-side rendering | [SSR](/guide/advanced/ssr.md) | | Proxy | Optional feature, proxy requests to the specified service | [server.proxy](/config/server/proxy.md) | | Open page | Optional feature, automatically open page in browser when starting server | [server.open](/config/server/open.md) | | HTTPS | Optional feature, enable HTTPS server | [server.https](/config/server/https.md) | | Custom middleware | Optional feature, use custom middlewares | [Middlewares](/guide/basic/server.md#middlewares) | ## UI framework | Features | Description | Links | | ------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | React | Optional feature, enable compilation of React JSX | [React plugin](/plugins/list/plugin-react.md) | | React Refresh | Optional feature, enable React Refresh | [Hot module replacement](/guide/advanced/hmr.md)[dev.hmr](/config/dev/hmr.md) | | SVGR | Optional feature, transform SVG to React component | [SVGR plugin](/plugins/list/plugin-svgr.md) | | Vue 3 SFC | Optional feature, enable compilation of Vue 3 SFC (Single File Components) | [Vue plugin](/plugins/list/plugin-vue.md) | | Vue 3 JSX | Optional feature, enable compilation of Vue 3 JSX syntax | [Vue JSX plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx) | | Vue 2 SFC | Optional feature, enable compilation of Vue 2 SFC (Single File Components) | [Vue 2 plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue2) | | Vue 2 JSX | Optional feature, enable compilation of Vue 2 JSX syntax | [Vue 2 JSX plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue2-jsx) | | Svelte | Optional feature, enable compilation of Svelte component | [Svelte plugin](/plugins/list/plugin-svelte.md) | | Solid | Optional feature, enable compilation of Solid JSX | [Solid plugin](/plugins/list/plugin-solid.md) | ## Static assets | Features | Description | Links | | ---------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Image assets | Support for import image assets in code | [Static assets](/guide/basic/static-assets.md) | | Font assets | Support for import font assets in code | [Static assets](/guide/basic/static-assets.md) | | Video assets | Support for import video assets in code | [Static assets](/guide/basic/static-assets.md) | | Wasm assets | Support for import WebAssembly assets in code | [Static assets](/guide/basic/static-assets.md) | | Node addons | Support for import Node.js addons in code | [Static assets](/guide/basic/static-assets.md) | | Inline static assets | Small assets are inlined into JS by default | [Inline static assets](/guide/optimization/inline-assets.md)[output.dataUriLimit](/config/output/data-uri-limit.md) | | Clean up static assets | Automatically clean up static assets in the dist directory before each build | [output.cleanDistPath](/config/output/clean-dist-path.md) | | Copy static assets | Optional feature, copy static assets to the dist directory | [output.copy](/config/output/copy.md) | | Generate manifest file | Optional feature, generate `manifest.json` file | [output.manifest](/config/output/manifest.md) | ## Performance and debugging | Features | Description | Links | | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | Chunk splitting | A variety of chunk splitting strategies are built into Rsbuild to automatically split the bundle into files of moderate size | [Code splitting](/guide/optimization/code-splitting.md)[performance.chunkSplit](/config/performance/chunk-split.md) | | Print file size | After the production build, All bundle sizes is displayed by default | [performance.printFileSize](/config/performance/print-file-size.md) | | Analyze build process | Optional feature, use Rsdoctor to analyze build process | [使用 Rsdoctor](/guide/debug/rsdoctor.md) | | Analyze bundle size | Optional feature, analyze bundle size through Bundle Analyzer | [performance.bundleAnalyze](/config/performance/bundle-analyze.md) | | Remove console | Optional feature, remove `console.[methodName]` in code | [performance.removeConsole](/config/performance/remove-console.md) | | Optimize moment.js size | Optional feature, remove the redundant locale files of moment.js | [performance.removeMomentLocale](/config/performance/remove-moment-locale.md) | | Dedupe packages | Optional feature, remove duplicate npm packages | [resolve.dedupe](/config/resolve/dedupe.md) | | Component on-demand import | Optional feature, selectively import code and styles from component libraries | [source.transformImport](/config/source/transform-import.md) | | Image compression | Optional feature, compress used image resources | [Image compress plugin](https://github.com/rspack-contrib/rsbuild-plugin-image-compress) | | Preload | Optional feature, preemptively fetch and cache the target resource for current navigation | [performance.preload](/config/performance/preload.md) | | Prefetch | Optional feature, preemptively fetch and cache the target resource for a followup navigation | [performance.prefetch](/config/performance/prefetch.md) | | Preconnect | Optional feature, preemptively connect to the target resource's origin | [performance.preconnect](/config/performance/preconnect.md) | | DNS prefetch | Optional feature, preemptively perform DNS resolution for the target resource's origin | [performance.dnsPrefetch](/config/performance/dns-prefetch.md) | --- url: /guide/start/glossary.md --- # Glossary ## Bundler Refers to module bundlers such as [Rspack](https://rspack.dev/) and [webpack](https://webpack.js.org/). The main goal of bundlers is to bundle JavaScript, CSS and other files together, and the bundled files can be used in the browser, Node.js or other environments. When bundler processes the web application, it builds a dependency graph and then combines every module into one or more bundles. ## CSR CSR stands for "Client-Side Rendering". It means that the page is rendered in the browser using JavaScript, and logic such as data fetching, templates, and routing is completed on the client side rather than the server. In CSR, the server sends an empty HTML shell and some JavaScript scripts to the browser, and the browser fetching data from the server's API and renders dynamic content to the page. ## Environment The runtime environment for build output, see [Multi-environment builds](/guide/advanced/environments.md). ## Micro-frontend Micro-frontend (MFE) is an architecture style similar to microservices. It is a composition of multiple independently delivered frontend applications, forming a cohesive whole. MFE decomposes frontend applications into smaller, simpler applications that can be developed, tested, and deployed independently while still appearing as a cohesive single product to users. It primarily addresses two problems: * Difficulty in maintaining large and complex applications as they evolve over time. * Inefficiency caused by cross-team or cross-department collaboration in project development. ## Modern.js [Modern.js](https://github.com/web-infra-dev/modern.js) is an open source web engineering system from ByteDance, which provides multiple solutions to help developers solve problems in different development scenarios. ## Module Federation Module Federation is an architectural pattern for JavaScript application decomposition (similar to microservices on the server-side), allowing you to share code and resources between multiple JavaScript applications (or micro-frontends). See [Module Federation](/guide/advanced/module-federation.md) for more details. ## Rspack [Rspack](https://rspack.dev/) is a high performance JavaScript bundler written in Rust. It offers strong compatibility with the webpack ecosystem, allowing for seamless replacement of webpack, and provides lightning fast build speeds. ## Rspress [Rspress](https://github.com/web-infra-dev/rspress) is a fast static site generator based on Rsbuild. ## SSR SSR stands for "Server-side rendering". It means that the HTML of the web page is generated by the server and sent to the client, rather than sending only an empty HTML shell and relying on JavaScript to generate the page content. See [Server-side rendering (SSR)](/guide/advanced/ssr.md) for more details. ## SWC SWC (Speedy Web Compiler) is a transformer and minimizer for JavaScript and TypeScript based on Rust. See [Configure SWC](/guide/configuration/swc.md) for more details. ## More See more glossary in [Rspack - Glossary](https://rspack.dev/misc/glossary). --- url: /guide/framework/react.md --- # React In this document, you will learn how to build a React application using Rsbuild. ## Create a React application Use `create-rsbuild` to create a React application with Rsbuild. Run the following command: Then select `React 19` or `React 18` when prompted to "Select framework". ## Use React in an existing project To compile React's JSX syntax, you need to register the Rsbuild [React Plugin](/plugins/list/plugin-react.md). The plugin will automatically add the necessary configuration for building a React application. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [pluginReact()], }); ``` :::tip For projects using Create React App, you can refer to the [CRA Migration Guide](/guide/migration/cra.md). ::: ## Use SVGR Rsbuild supports convert SVG to React components via [SVGR](https://react-svgr.com/). To use SVGR, you also need to register the [SVGR plugin](/plugins/list/plugin-svgr.md). ## React Fast Refresh Rsbuild uses React's official [Fast Refresh](https://npmjs.com/package/react-refresh) capability to perform component hot updates. Note that React Refresh requires components to be written according to the standards. Otherwise HMR may not work. You can use [eslint-plugin-react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh) for validation. For example, if the hot update of the React component cannot take effect, or the state of the React component is lost after the hot update, it is usually because your React component uses an anonymous function. In the official practice of React Fast Refresh, it is required that the component cannot be an anonymous function, otherwise the state of the React component cannot be preserved after hot update. Here are some examples of wrong usage: ```tsx // bad export default function () { return <div>Hello World</div>; } // bad export default () => <div>Hello World</div>; ``` The correct usage is to declare a name for each component function: ```tsx // good export default function MyComponent() { return <div>Hello World</div>; } // good const MyComponent = () => <div>Hello World</div>; export default MyComponent; ``` ## React Compiler React Compiler is an experimental compiler introduced in React 19 that can automatically optimize your React code. Before you start using React Compiler, it's recommended to read the [React Compiler documentation](https://react.dev/learn/react-compiler) to understand the functionality, current state, and usage of the React Compiler. ### How to use The steps to use React Compiler in Rsbuild: 1. Upgrade versions of `react` and `react-dom` to 19. If you are unable to upgrade, you can install the extra [react-compiler-runtime](https://npmjs.com/package/react-compiler-runtime) package which will allow the compiled code to run on versions prior to 19. 2. React Compiler currently only provides a Babel plugin, you need to install [@rsbuild/plugin-babel](/plugins/list/plugin-babel.md) and [babel-plugin-react-compiler](https://npmjs.com/package/babel-plugin-react-compiler). 3. Register the Babel plugin in your Rsbuild config file: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginBabel } from '@rsbuild/plugin-babel'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [ pluginReact(), pluginBabel({ include: /\.(?:jsx|tsx)$/, babelLoaderOptions(opts) { opts.plugins?.unshift('babel-plugin-react-compiler'); }, }), ], }); ``` > You can also refer to the [example project](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/react-compiler-babel). ### Configuration Set the config for React Compiler as follows: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginBabel } from '@rsbuild/plugin-babel'; import { pluginReact } from '@rsbuild/plugin-react'; const ReactCompilerConfig = { /* ... */ }; export default defineConfig({ plugins: [ pluginReact(), pluginBabel({ include: /\.(?:jsx|tsx)$/, babelLoaderOptions(opts) { opts.plugins?.unshift([ 'babel-plugin-react-compiler', ReactCompilerConfig, ]); }, }), ], }); ``` For React 17 and 18 projects, you need to install [react-compiler-runtime](https://npmjs.com/package/react-compiler-runtime) and specify the `target`: ```ts title="rsbuild.config.ts" const ReactCompilerConfig = { target: '18', // '17' | '18' | '19' }; ``` ## Router ### TanStack Router [TanStack Router](https://tanstack.com/router/) is a fully type-safe React router with built-in data fetching, stale-while revalidate caching and first-class search-param APIs. TanStack Router provides `@tanstack/router-plugin` to integrate with Rsbuild, which provides support for file-based routing. See: * [Installation guide](https://tanstack.com/router/latest/docs/framework/react/routing/installation-with-rspack) * [Example project](https://github.com/TanStack/router/tree/main/examples/react/quickstart-rspack-file-based) ### React Router [React Router](https://reactrouter.com/) is a user‑obsessed, standards‑focused, multi‑strategy router for React. * To use React Router as a library, you can just follow the official documentation and no configuration is required. * To use React Router as a framework, the community is working on an experimental Rsbuild plugin, see [rsbuild-plugin-react-router](https://github.com/rspack-contrib/rsbuild-plugin-react-router). ## CSS-in-JS ### Use styled-components Rsbuild supports compiling [styled-components](https://github.com/styled-components/styled-components), improve the debugging experience and add server-side rendering support to styled-components. To use styled-components, we recommend using the [@rsbuild/plugin-styled-components](https://github.com/rsbuild-contrib/rsbuild-plugin-styled-components). > You can refer to this example: [styled-components](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/styled-components). ### Using Emotion Rsbuild supports compiling [Emotion](https://github.com/emotion-js/emotion), you can add the following configuration to use: * [swcReactOptions.importSource](/plugins/list/plugin-react.md#swcreactoptions) * [@swc/plugin-emotion](https://npmjs.com/package/@swc/plugin-emotion) ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [ pluginReact({ swcReactOptions: { importSource: '@emotion/react', }, }), ], tools: { swc: { jsc: { experimental: { plugins: [['@swc/plugin-emotion', {}]], }, }, }, }, }); ``` > You can refer to this example: [emotion](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/emotion). ### Use styled-jsx You can use [styled-jsx](https://github.com/vercel/styled-jsx) through [@swc/plugin-styled-jsx](https://npmjs.com/package/@swc/plugin-styled-jsx): ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [pluginReact()], tools: { swc: { jsc: { experimental: { plugins: [['@swc/plugin-styled-jsx', {}]], }, }, }, }, }); ``` Please note, you must select the SWC plugin that matches the current version of `@swc/core` for SWC to work, see [tools.swc](/config/tools/swc.md). > You can refer to this example: [styled-jsx](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/styled-jsx). ### Use vanilla-extract Rsbuild supports [@vanilla-extract/webpack-plugin](https://npmjs.com/package/@vanilla-extract/webpack-plugin). You can add the following config to use [vanilla-extract](https://github.com/vanilla-extract-css/vanilla-extract): ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin'; export default defineConfig({ plugins: [ pluginReact({ reactRefreshOptions: { exclude: [/\.css\.ts$/], }, }), ], tools: { rspack: { plugins: [new VanillaExtractPlugin()], }, }, }); ``` > You can refer to this example: [vanilla-extract](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/vanilla-extract). ### Use StyleX You can use [StyleX](https://github.com/facebook/stylex) via [unplugin-stylex](https://github.com/eryue0220/unplugin-stylex): ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; import stylexPlugin from 'unplugin-stylex/rspack'; export default defineConfig({ plugins: [pluginReact()], tools: { rspack: { plugins: [stylexPlugin()], }, }, }); ``` > You can refer to this example: [stylex](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/stylex). ## Customize JSX Rsbuild uses SWC to compile JSX, you can customize the functions used by the compiled JSX code: * If the JSX runtime is `automatic`, use [jsxImportSource](/plugins/list/plugin-react.md#swcreactoptionsimportsource) to customize the import path of the JSX runtime, for example, import from Preact or Emotion. * If the JSX runtime is `classic`, use `pragma` and `pragmaFrag` to specify the JSX function and Fragment component. > `@rsbuild/plugin-react` uses `automatic` as the default JSX runtime, see [swcReactOptions.runtime](/plugins/list/plugin-react.md#swcreactoptionsruntime). ### Via configuration Configure through the `@rsbuild/plugin-react`'s [swcReactOptions](/plugins/list/plugin-react.md#swcreactoptions). * If `runtime` is `automatic`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [ pluginReact({ swcReactOptions: { runtime: 'automatic', jsxImportSource: '@emotion/react', }, }), ], }); ``` * If `runtime` is `classic`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [ pluginReact({ swcReactOptions: { runtime: 'classic', pragma: 'h', pragmaFrag: 'Fragment', }, }), ], }); ``` ### Via comments You can also customize the JSX behavior by adding specific comments at the top of a single JSX or TSX file, which will take precedence over the configurations. * If the JSX runtime is `automatic`: ```tsx title="App.tsx" /** @jsxImportSource custom-jsx-library */ const App = () => { return <div>Hello World</div>; }; ``` * If the JSX runtime is `classic`: ```tsx title="App.tsx" /** @jsx Preact.h */ /** @jsxFrag Preact.Fragment */ const App = () => { return <div>Hello World</div>; }; ``` ## Performance profiling ### React Scan React Scan can automatically detect performance issues in your React app. See [React Scan - Rsbuild Guide](https://github.com/aidenybai/react-scan/blob/main/docs/installation/rsbuild.md) to learn how to use React Scan with Rsbuild. --- url: /guide/framework/vue.md --- # Vue In this document, you will learn how to build a Vue 3 or Vue 2 application using Rsbuild. ## Create a Vue application Use `create-rsbuild` to create a Vue application with Rsbuild. Run the following command: Then select `Vue 3` or `Vue 2` when prompted to "Select framework". ## Vue 3 ### Use Vue in an existing project To compile Vue SFC (Single File Components), you need to register the Rsbuild [Vue plugin](/plugins/list/plugin-vue.md). The plugin will automatically add the necessary configuration for Vue builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginVue } from '@rsbuild/plugin-vue'; export default defineConfig({ plugins: [pluginVue()], }); ``` :::tip For projects using Vue CLI, you can refer to the [Vue CLI Migration Guide](/guide/migration/vue-cli.md). ::: ### Use the JSX syntax of Vue To use the JSX syntax of Vue, you also need to register the [@rsbuild/plugin-vue-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx). ### TypeScript support Rsbuild supports compiling TypeScript by default. Please refer to the [TypeScript - IDE Support](https://vuejs.org/guide/typescript/overview.html#ide-support) section of the Vue documentation to learn how to set up Vue TypeScript support in your IDE. ## Vue 2 ### Use Vue 2 in an existing project To compile Vue SFC (Single File Components), you need to register the Rsbuild [Vue 2 plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue2). The plugin will automatically add the necessary configuration for Vue builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginVue2 } from '@rsbuild/plugin-vue2'; export default defineConfig({ plugins: [pluginVue2()], }); ``` :::tip * The Vue 2 plugin only supports Vue >= 2.7.0. * For projects using Vue CLI, you can refer to the [Vue CLI Migration Guide](/guide/migration/vue-cli.md). ::: ### Use the JSX syntax of Vue To use the JSX syntax of Vue, you also need to register the [@rsbuild/plugin-vue2-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue2-jsx). ### Type declarations In a TypeScript project, you need to add type definitions for `*.vue` files so that TypeScript can recognize them correctly. Create `env.d.ts` in the `src` directory and add the following content: ```ts title="src/env.d.ts" declare module '*.vue' { import Vue from 'vue'; export default Vue; } ``` --- url: /guide/framework/preact.md --- # Preact In this document, you will learn how to build a Preact application using Rsbuild. ## Create a Preact application Use `create-rsbuild` to create a Preact application with Rsbuild. Run the following command: Then select `Preact` when prompted to "Select framework". ## Use Preact in an existing project To compile Preact, you need to register the Rsbuild [Preact Plugin](/plugins/list/plugin-preact.md). The plugin will automatically add the necessary configuration for Preact builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginPreact } from '@rsbuild/plugin-preact'; export default defineConfig({ plugins: [pluginPreact()], }); ``` ## Preact Fast Refresh Preact plugin uses [@preact/prefresh](https://github.com/preactjs/prefresh) and [@rspack/plugin-preact-refresh](https://github.com/rspack-contrib/rspack-plugin-preact-refresh) to hot reload Preact components. ### Component recognition Prefresh need to be able to recognize your components, this means that components should start with a capital letter and hook should start with `use` followed by a capital letter. This allows the plugin to effectively recognize these. Do note that a component as seen below is not named: ```jsx export default () => { return <p>Want to refresh</p>; }; ``` Instead do: ```jsx const MyComponent = () => { return <p>Want to refresh</p>; }; export default MyComponent; ``` When you are working with HOC's be sure to lift up the `displayName` so the plugin can recognize it as a component. --- url: /guide/framework/svelte.md --- # Svelte In this document, you will learn how to build a Svelte application using Rsbuild. ## Create a Svelte application Use `create-rsbuild` to create a Svelte application with Rsbuild. Run the following command: Then select `Svelte` when prompted to "Select framework". ## Use Svelte in an existing project To compile Svelte components (`.svelte` files), you need to register the Rsbuild [Svelte plugin](/plugins/list/plugin-svelte.md). The plugin will automatically add the necessary configuration for Svelte builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginSvelte } from '@rsbuild/plugin-svelte'; export default defineConfig({ plugins: [pluginSvelte()], }); ``` --- url: /guide/framework/solid.md --- # Solid In this document, you will learn how to build a Solid application using Rsbuild. ## Create a Solid application Use `create-rsbuild` to create a Solid application with Rsbuild. Run the following command: Then select `Solid` when prompted to "Select framework". ## Use Solid in an existing project To compile Solid components, you need to register the Rsbuild [Solid plugin](/plugins/list/plugin-solid.md). The plugin will automatically add the necessary configuration for Solid builds. For example, register in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginBabel } from '@rsbuild/plugin-babel'; import { pluginSolid } from '@rsbuild/plugin-solid'; export default defineConfig({ plugins: [ pluginBabel({ include: /\.(?:jsx|tsx)$/, }), pluginSolid(), ], }); ``` --- url: /guide/basic/cli.md --- # CLI Rsbuild comes with a lightweight CLI that includes commands such as [rsbuild dev](#rsbuild-dev) and [rsbuild build](#rsbuild-build). ## All commands To view all available CLI commands, run the following command in the project directory: ```bash npx rsbuild -h ``` The output is shown below: ``` Usage: $ rsbuild <command> [options] Commands: dev starting the dev server build build the app for production preview preview the production build locally inspect inspect the Rspack and Rsbuild configs ``` ## Common flags Rsbuild CLI provides several common flags that can be used with all commands: | Flag | Description | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `--base <base>` | Specify the base path of the server, see [server.base](/config/server/base.md) | | `-c, --config <config>` | Specify the configuration file, can be a relative or absolute path, see [Specify config file](/guide/configuration/rsbuild.md#specify-config-file) | | `--config-loader <loader>` | Specify the config loader, can be `jiti` or `native`, see [Specify config loader](/guide/configuration/rsbuild.md#specify-config-loader) | | `--env-mode <mode>` | Specify the env mode to load the `.env.[mode]` file, see [Env mode](/guide/advanced/env-vars.md#env-mode) | | `--env-dir <dir>` | Specify the directory to load `.env` files, see [Env directory](/guide/advanced/env-vars.md#env-directory) | | `--environment <name>` | Specify the name of environment to build, see [Build specified environment](/guide/advanced/environments.md#build-specified-environment) | | `-h, --help` | Display help for command | | `-m, --mode <mode>` | Specify the build mode (`development`, `production` or `none`), see [mode](/config/mode.md) | | `--no-env` | Disable loading `.env` files | | `-r, --root <root>` | Specify the project root directory | ## rsbuild dev The `rsbuild dev` command is used to start a local dev server and compile the source code for development. ```bash Usage: rsbuild dev [options] Options: -o, --open [url] open the page in browser on startup --port <port> specify a port number for Rsbuild server to listen --host <host> specify the host that the Rsbuild server listens to ``` You can also start the dev server by running `rsbuild` directly, which is equivalent to running `rsbuild dev`. ```bash npx rsbuild ``` ### Opening page The `--open` option allows you to automatically open a page when starting the dev server, which is equivalent to setting [server.open](/config/server/open.md) to `true`. ```bash rsbuild dev --open ``` The `--open` option also supports specifying the URL to be opened, for example: ```bash rsbuild dev --open http://localhost:3000/foo ``` The `--open` option can also be abbreviated to `-o`: ```bash rsbuild dev -o ``` :::tip When using [server.open](/config/server/open.md) and `--open` at the same time, `--open` takes precedence. ::: ## rsbuild build The `rsbuild build` command will build the outputs for production in the `dist/` directory by default. ```bash Usage: rsbuild build [options] Options: -w --watch turn on watch mode, watch for changes and rebuild ``` ## rsbuild preview The `rsbuild preview` command is used to preview the production build outputs locally. Note that you need to execute the `rsbuild build` command beforehand to generate the build outputs. ```bash Usage: rsbuild preview [options] Options: -o, --open [url] open the page in browser on startup --port <port> specify a port number for Rsbuild server to listen --host <host> specify the host that the Rsbuild server listens to ``` :::tip The preview command is only used for local preview. Do not use it for production servers, as it is not designed for that. ::: ## rsbuild inspect The `rsbuild inspect` command is used to view the Rsbuild config and Rspack config of the project. ```bash Usage: rsbuild inspect [options] Options: --output <output> specify the path to output in the dist (default: ".rsbuild") --verbose show the full function in the result ``` When you run the command `npx rsbuild inspect` in the project root directory, the following files will be generated in the `dist/.rsbuild` directory of the project: * `rsbuild.config.mjs`: Represents the Rsbuild configuration used during the build. * `rspack.config.web.mjs`: Represents the Rspack configuration used during the build. ```bash ➜ npx rsbuild inspect config inspection completed, generated files: - Rsbuild config: /project/dist/.rsbuild/rsbuild.config.mjs - Rspack config (web): /project/dist/.rsbuild/rspack.config.web.mjs ``` ### Specifying mode By default, the inspect command outputs the configuration for the development mode. You can add the `--env production` option to output the configuration for the production mode: ```bash rsbuild inspect --mode production ``` ### Verbose content By default, the inspect command omits the content of functions in the configuration object. You can add the `--verbose` option to output the complete content of functions: ```bash rsbuild inspect --verbose ``` ### Multiple targets If the current project has multiple build targets, such as building browser artifact and Node.js artifact simultaneously, multiple Rspack configuration files will be generated in the `dist/.rsbuild` directory. ```bash ➜ npx rsbuild inspect config inspection completed, generated files: - Rsbuild config (web): /project/dist/.rsbuild/rsbuild.config.web.mjs - Rsbuild config (node): /project/dist/.rsbuild/rsbuild.config.node.mjs - Rspack config (web): /project/dist/.rsbuild/rspack.config.web.mjs - Rspack config (node): /project/dist/.rsbuild/rspack.config.node.mjs ``` --- url: /guide/basic/server.md --- # Server Rsbuild comes with a built-in dev server designed to improve the development experience. When you run the `rsbuild dev` or `rsbuild preview` commands, the server will start, providing features such as page preview, routing, and hot module reloading. ## Base path By default, the Rsbuild server's base path is `/`. You can access output files like `index.html` and assets in the [public folder](/guide/basic/static-assets.md#public-folder) through `http://localhost:3000/`. Rsbuild supports modifying the base path of the server through [server.base](/config/server/base.md). If you to access these files through `http://localhost:3000/foo/`, you can configure the following: ```ts title="rsbuild.config.ts" export default { server: { base: '/foo', }, }; ``` ## View static assets After starting the dev server, you can access `/rsbuild-dev-server` to view all static assets generated during the current build. For example, open `http://localhost:3000/rsbuild-dev-server` in the browser, you will see: ## Page routing Rsbuild server offers a set of default routing convention, and allows users to customize it through configurations. ### Default behavior Rsbuild server will generate the corresponding page route based on the [server.base](/config/server/base.md) and [source.entry](/config/source/entry.md) configurations. When entry is index, the page can be accessed through `/`; when entry is foo, the page can be accessed through `/foo`. When server.base is `/base`, the index page can be accessed through `/base` and the foo page can be accessed through `/base/foo`. ```ts title="rsbuild.config.ts" export default { source: { entry: { index: './src/index.ts', foo: './src/pages/foo/index.ts', }, }, }; ``` ### Fallback behavior By default, when the request meets the following conditions and the corresponding resource is not found, it will fallback to `index.html`: * The request is a `GET` or `HEAD` request * Which accepts `text/html` (the request header accept type is `text/html` or `*/*`) ```ts title="rsbuild.config.ts" export default { server: { htmlFallback: 'index', }, }; ``` ### Custom fallback behavior When Rsbuild's default [server.htmlFallback](/config/server/html-fallback.md) configuration cannot meet your needs, for example, if you want to be able to access `main.html` when accessing `/`, you can set it up using [server.historyApiFallback](/config/server/history-api-fallback.md). ```ts title="rsbuild.config.ts" export default { source: { entry: { main: './src/index.ts', }, }, server: { htmlFallback: false, historyApiFallback: { index: '/main.html', }, }, }; ``` ### HTML output path Normally, `/` points to the dist root directory, and the HTML file is output to the dist root directory. At this time, the corresponding HTML page can be accessed through `/some-path`. If you output HTML files to other subdirectories by modifying [output.distPath.html](/config/output/dist-path.md), you need to access the corresponding HTML page through `/[htmlPath]/some-path`. For example, if you set the HTML file to be output to the `HTML` directory, index.html will be accessed through `/html/`, and foo.html will be accessed through `/html/foo`. ```ts export default { source: { entry: { index: './src/index.ts', foo: './src/pages/foo/index.ts', }, }, output: { distPath: { html: 'html', }, }, }; ``` ## Rspack dev server Rsbuild has a built-in lightweight dev server, which is different from the dev servers built into Rspack CLI or webpack CLI. There are some differences between them, including different configuration options. ### Comparison Compared with the dev server built into Rspack CLI, Rsbuild's dev server has the following differences: * **Configuration**: Rsbuild provides richer server configuration options. * **Log Format**: The log format of Rspack CLI is basically consistent with webpack CLI, while Rsbuild's logs are clearer and more readable. * **Dependencies**: Rsbuild is implemented based on lightweight libraries like `connect`, which has fewer dependencies and faster startup speed compared to `express` used by `@rspack/dev-server`. ### Configuration Rsbuild does not support using Rspack's [devServer](https://rspack.dev/config/dev-server) config. Instead, you can use Rsbuild's `dev` and `server` configs. In Rsbuild, `dev` contains some configs that are only work in development mode, while the `server` config works for both dev and preview servers. Below are the Rsbuild configs that correspond to the Rspack CLI's `devServer` config: | Rspack CLI | Rsbuild | | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | [devServer.client](https://rspack.dev/config/dev-server#devserverclient) | [dev.client](/config/dev/client.md) | | [devServer.compress](https://rspack.dev/config/dev-server#devservercompress) | [server.compress](/config/server/compress.md) | | [devServer.devMiddleware.writeToDisk](https://rspack.dev/config/dev-server#devserverdevmiddleware) | [dev.writeToDisk](/config/dev/write-to-disk.md) | | [devServer.headers](https://rspack.dev/config/dev-server#devserverheaders) | [server.headers](/config/server/headers.md) | | [devServer.historyApiFallback](https://rspack.dev/config/dev-server#devserverhistoryapifallback) | [server.historyApiFallback](/config/server/history-api-fallback.md) | | [devServer.host](https://rspack.dev/config/dev-server#devserverhost) | [server.host](/config/server/host.md) | | [devServer.hot](https://rspack.dev/config/dev-server#devserverhot) | [dev.hmr](/config/dev/hmr.md) | | [devServer.liveReload](https://rspack.dev/config/dev-server#devserverlivereload) | [dev.liveReload](/config/dev/live-reload.md) | | [devServer.open](https://rspack.dev/config/dev-server#devserveropen) | [server.open](/config/server/open.md) | | [devServer.port](https://rspack.dev/config/dev-server#devserverport) | [server.port](/config/server/port.md) | | [devServer.proxy](https://rspack.dev/config/dev-server#devserverproxy) | [server.proxy](/config/server/proxy.md) | | [devServer.setupMiddlewares](https://rspack.dev/config/dev-server#devserversetupmiddlewares) | [dev.setupMiddlewares](/config/dev/setup-middlewares.md) | | [devServer.static](https://rspack.dev/config/dev-server#devserverstatic) | [server.publicDir](/config/server/public-dir.md) | | [devServer.watchFiles](https://rspack.dev/config/dev-server#devserverwatchfiles) | [dev.watchFiles](/config/dev/watch-files.md) | > For more configurations, please refer to [Config Overview](/config/index.md). ## Middlewares Rsbuild's middlewares implementation is built on [connect](https://github.com/senchalabs/connect), a lightweight HTTP server framework, and uses the standard Node.js `request` and `response` objects for handling HTTP interactions. ### Register middlewares Rsbuild provides three ways to register middlewares: 1. Use the [dev.setupMiddlewares](/config/dev/setup-middlewares.md) configuration. ```ts title="rsbuild.config.ts" export default { dev: { setupMiddlewares: [ (middlewares, server) => { middlewares.push((req, res, next) => { next(); }); }, ], }, }; ``` 2. In the Rsbuild plugin, you can register middlewares through the [onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver) hook. ```ts const myPlugin = () => ({ setup(api) { api.onBeforeStartDevServer(({ server }) => { server.middlewares.use((req, res, next) => { next(); }); }); }, }); ``` 3. When using the Rsbuild JavaScript API, you can create a dev server instance through the [rsbuild.createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver) method and use the `use` method to register middlewares. ```ts const server = await rsbuild.createDevServer(); server.middlewares.use((req, res, next) => { next(); }); ``` ### Integrate third-party server frameworks When migrating from other server frameworks (such as Express), the original middleware may not be used directly in Rsbuild. For example, the `req.params`, `req.path`, `req.search`, `req.query` and other properties provided by Express cannot be accessed in the Rsbuild middleware. If you need to reuse existing middleware in Rsbuild, you can use the following method to introduce the server application as a whole as middleware: ```ts title="rsbuild.config.ts" import express from 'express'; import expressMiddleware from 'my-express-middleware'; // Initialize Express app const app = express(); app.use(expressMiddleware); export default { dev: { setupMiddlewares: [ (middleware) => { middleware.unshift(app); }, ], }, }; ``` ## Custom server If you want to integrate Rsbuild dev server into a custom server, you can get the instance methods of Rsbuild dev server through the `createDevServer` method of Rsbuild and call them on demand. For details, please refer to [Rsbuild - createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver). --- url: /guide/basic/output-files.md --- # Output files This chapter will introduces the directory structure of output files and how to control the output directory of different types of files. If you want to know how to deploy the build outputs of Rsbuild as a static site, please refer to [Deploy Static Site](/guide/basic/static-deploy.md). ## Default directory structure The following is a basic directory for output files. By default, the compiled files will be output in the `dist` directory of current project. ```bash dist ├── static │ ├── css │ │ ├── [name].[hash].css │ │ └── [name].[hash].css.map │ │ │ └── js │ ├── [name].[hash].js │ ├── [name].[hash].js.LICENSE.txt │ └── [name].[hash].js.map │ └── [name].html ``` The most common output files are HTML files, JS files, and CSS files: * HTML files: default output to the root of dist directory. * JS files: default output to `static/js` directory, * CSS files: default output to the `static/css` directory. In addition, JS files and CSS files sometimes generate some related files: * License files: contains open source license, which is output to the same level directory of the JS file, and adds `.LICENSE.txt` suffix. * Source Map files: contains the source code mappings, which is output to the same level directory of JS files and CSS files, and adds a `.map` suffix. In the filename, `[name]` represents the entry name corresponding to this file, such as `index`, `main`. `[hash]` is the hash value generated based on the content of the file. ## Development mode output In development mode, Rsbuild stores the build outputs in memory on the dev server by default, rather than writing then to disk. This can reduce the overhead of fs operations. You can refer to [View Static Assets](/guide/basic/server.md#view-static-assets) to view all static assets generated in the current build. You can choose to write the output files to disk, which is typically used for inspecting the contents of the build artifacts or configuring proxy rules for static assets. Just set the [dev.writeToDisk](/config/dev/write-to-disk.md) configuration to `true`: ```ts export default { dev: { writeToDisk: true, }, }; ``` ## Modify the directory Rsbuild provides some configs to modify the directory or filename, you can: * Modify the filename through [output.filename](/config/output/filename.md). * Modify the output path of through [output.distPath](/config/output/dist-path.md). * Modify the license file through [output.legalComments](/config/output/legal-comments.md). * Modify Source Map file through [output.sourceMap](/config/output/source-map.md). * Modify the output structure of the HTML files through [html.outputStructure](/config/html/output-structure.md). ## Static assets When you import static assets such as images, SVG, fonts, media, etc. in the code, they will also be output to the `dist/static` directory, and automatically assigned to the corresponding subdirectories according to the file type: ```bash dist └── static ├── image │ └── foo.[hash].png │ ├── svg │ └── bar.[hash].svg │ ├── font │ └── baz.[hash].woff2 │ └── media └── qux.[hash].mp4 ``` You can use the [output.distPath](/config/output/dist-path.md) config to uniformly input these static assets into a directory, for example, output to the `assets` directory: ```ts export default { output: { distPath: { image: 'assets', svg: 'assets', font: 'assets', media: 'assets', }, }, }; ``` The above config will generate the following directory structure: ```bash dist └── assets ├── foo.[hash].png ├── bar.[hash].svg ├── baz.[hash].woff2 └── qux.[hash].mp4 ``` ## Node.js output directory When the [output.target](/config/output/target.md) of Rsbuild is `'node'`, Rsbuild will generate output files for Node.js: ```bash dist ├── static └── [name].js ``` Node.js outputs usually only contain JS files, no HTML or CSS. And the JS file names will not contain hash. You can modify the output path of Node.js files via the [environments](/config/environments.md) config. For example, output Node.js files to the `server` directory: ```ts export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', distPath: { root: 'dist/server', }, }, }, }, }; ``` ## Flatten the directory Sometimes you don't want the dist directory to have too many levels, you can set the directory to an empty string to flatten the generated directory. See the example below: ```ts export default { output: { distPath: { js: '', css: '', }, }, }; ``` The above config will generate the following directory structure: ```bash dist ├── [name].[hash].css ├── [name].[hash].css.map ├── [name].[hash].js ├── [name].[hash].js.map └── [name].html ``` --- url: /guide/basic/static-assets.md --- # Static assets Rsbuild supports import static assets, including images, fonts, audio and video. :::tip What is Static Assets Static assets are files that are part of a web application and do not change, even when the application is being used. Examples of static assets include images, fonts, medias, stylesheets, and JavaScript files. These assets are typically stored on a web server or CDN, and delivered to the user's web browser when the web application is accessed. Because they do not change, static assets can be cached by the browser, which helps to improve the performance of the web application. ::: ## Assets format The following are the formats supported by Rsbuild by default: * **images**: png, jpg, jpeg, gif, svg, bmp, webp, ico, apng, avif, tif, tiff, jfif, pjpeg, pjp, cur. * **fonts**: woff, woff2, eot, ttf, otf, ttc. * **audio**: mp3, wav, flac, aac, m4a, opus. * **video**: mp4, webm, ogg, mov. To import assets in other formats, refer to [Extend Asset Types](#extend-asset-types). :::tip SVG images SVG image is a special case. Rsbuild support convert SVG to React components, so SVG is processed separately. For details, see [SVGR Plugin](/plugins/list/plugin-svgr.md). ::: ## Import assets in JS file In JS files, you can import static assets with relative paths: ```tsx // Import the logo.png image in the static directory import logo from './static/logo.png'; console.log(logo); // "/static/logo.[hash].png" export default = () => <img src={logo} />; ``` Import with [alias](/guide/advanced/alias.md) is also available: ```tsx import logo from '@/static/logo.png'; console.log(logo); // "/static/logo.[hash].png" export default = () => <img src={logo} />; ``` ### URL assets Rsbuild supports using JavaScript's native [URL](https://developer.mozilla.org/docs/Web/API/URL) and [import.meta.url](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/import.meta) to import static assets. ```tsx const logo = new URL('./static/logo.png', import.meta.url).href; console.log(logo); // "/static/logo.[hash].png" export default = () => <img src={logo} />; ``` If you use `new URL()` to reference `.js` or `.ts` files, they will be treated as URL assets and will not be processed by Rsbuild's built-in `swc-loader`. ```tsx // foo.ts will remain the original content and be output to the dist directory const fooTs = new URL('./foo.ts', import.meta.url).href; console.log(fooTs); // "/static/foo.[hash].ts" ``` Similarly, when using `new URL()` to reference `.css` or `.scss` files, they will be treated as URL assets and will not be processed by Rsbuild's built-in CSS loaders. ```tsx // foo.css will remain the original content and be output to the dist directory const fooCss = new URL('./foo.css', import.meta.url).href; console.log(fooCss); // "/static/foo.[hash].css" ``` ## Import assets in CSS file In CSS files, you can reference static assets in relative paths: ```css .logo { background-image: url('../static/logo.png'); } ``` Import with [alias](/guide/advanced/alias.md) are also supported: ```css .logo { background-image: url('@/static/logo.png'); } ``` If you want to reference static assets in absolute paths in CSS files: ```css @font-face { font-family: DingTalk; src: url('/image/font/foo.ttf'); } ``` By default, the built-in `css-loader` in Rsbuild will resolve absolute paths in `url()` and look for the specified modules. If you want to skip resolving absolute paths, you can configure [`tools.cssLoader`](/config/tools/css-loader.md#toolscssloader) to filter out the specified paths. The filtered paths are left as they are in the code. ```ts export default { tools: { cssLoader: { url: { filter: (url) => { if (/\/image\/font/.test(url)) { return false; } return true; }, }, }, }, }; ``` ## Inline assets The result of importing static assets depends on the file size: * If the file size is less than 4KiB, it will be converted to a base64 string and inlined in the code. * If the file size is larger than 4KiB, a URL will be returned, and the file will be emitted to the output directory. ```js import largeImage from './static/largeImage.png'; import smallImage from './static/smallImage.png'; console.log(largeImage); // "/static/largeImage.[hash].png" console.log(smallImage); // "data:image/png;base64,iVBORw0KGgo..." ``` Adding the `?url` query ensures that the asset is always loaded as a separate file and returns a URL: ```js import image from './static/image.png?url'; console.log(image); // "/static/image.[hash].png" ``` Adding the `?inline` query ensures that the asset is always inlined in the code, regardless of the file size: ```js import image from './static/image.png?inline'; console.log(image); // "data:image/png;base64,iVBORw0KGgo..." ``` For a more detailed introduction to asset inlining, please refer to the [Static Asset Inlining](/guide/optimization/inline-assets.md) chapter. ## Import as string Rsbuild supports using the `?raw` query parameter to import the raw content of static assets as a string in JavaScript. ```ts import rawSvg from './static/logo.svg?raw'; console.log(rawSvg); // The raw content of the SVG file ``` :::tip Rsbuild >= 1.3.0 supports the `?raw` query parameter. ::: ## Output files When static assets are imported, they will be output to the dist directory. You can: * Modify the output filename through [output.filename](/config/output/filename.md). * Modify the output path through [output.distPath](/config/output/dist-path.md). Please read [Output Files](/guide/basic/output-files.md) for details. ## URL prefix The URL returned after importing a asset will automatically include the path prefix: * In development, using [dev.assetPrefix](/config/dev/asset-prefix.md) to set the path prefix. * In production, using [output.assetPrefix](/config/output/asset-prefix.md) to set the path prefix. For example, you can set `output.assetPrefix` to `https://example.com`: ```js import logo from './static/logo.png'; console.log(logo); // "https://example.com/static/logo.[hash].png" ``` ## Public folder The public folder at the project root can be used to place some static assets. These assets will not be built by Rsbuild and can be directly referenced via URL. * When you start the dev server, these assets will be served under the root [server.base](/config/server/base.md) path, default `/`. * When you perform a production build, these assets will be copied to the [dist directory](/guide/basic/output-files.md). For example, you can place files such as `robots.txt`, `manifest.json`, or `favicon.ico` in the public folder. ### How to reference You can reference files in the `public` directory via a URL. For example, in an HTML template, the `./public/favicon.ico` file can be referenced as `/favicon.ico`, [BASE\_URL](/guide/advanced/env-vars.md#processenvpublic_base_path) is the base path of the server. ```html title="index.html" <link rel="icon" href="<%= process.env.BASE_URL %>/favicon.ico" /> ``` ### Notes Here are some notes on using the `public` folder: * When referencing assets in the public folder via URL, please use absolute paths instead of relative paths to ensure that the assets can be accessed correctly after deployment. ```html title="src/index.html" <!-- Wrong --> <link rel="icon" href="../public/favicon.ico" /> <!-- Correct --> <link rel="icon" href="/favicon.ico" /> ``` * Please avoid importing files from the public directory into the source code. The correct approach is to reference them by URL. You can place static assets imported into the source code in the `/src/assets` directory. ```js title="src/index.js" // Wrong import logo from '../public/logo.png'; // Correct import logo from './assets/logo.png'; ``` * During the production build, the files in public folder will be copied to the output folder (default is `dist`). Please be careful to avoid name conflicts with the output files. When files in the `public` folder have the same name as outputs, the outputs have higher priority and will overwrite the files with the same name in the `public` folder. This feature can be disabled by setting [server.publicDir.copyOnBuild](/config/server/public-dir.md) to `false`. ### Custom behavior Rsbuild provides the [server.publicDir](/config/server/public-dir.md) option which can be used to customize the name and behavior of the public folder, as well as to disable it. ```ts title="rsbuild.config.ts" export default { server: { publicDir: false, }, }; ``` ## Type declaration When you import static assets in TypeScript code, TypeScript may prompt that the module is missing a type definition: ``` TS2307: Cannot find module './logo.png' or its corresponding type declarations. ``` To fix this, you need to add a type declaration file for the static assets, please create a `src/env.d.ts` file, and add the corresponding type declaration. * Method 1: If the `@rsbuild/core` package is installed, you can reference the [preset types](/guide/basic/typescript.md#preset-types) provided by `@rsbuild/core`: ```ts /// <reference types="@rsbuild/core/types" /> ``` * Method 2: Manually add the required type declarations: ```ts title="src/env.d.ts" // Taking png images as an example declare module '*.png' { const content: string; export default content; } ``` After adding the type declaration, if the type error still exists, you can try to restart the current IDE, or adjust the directory where `env.d.ts` is located, making sure the TypeScript can correctly identify the type definition. ## Extend asset types If the built-in asset types in Rsbuild cannot meet your requirements, you can extend additional static asset types in the following ways. ### Use `source.assetsInclude` By using the [source.assetsInclude](/config/source/assets-include.md) config, you can specify additional file types to be treated as static assets. ```ts title="rsbuild.config.ts" export default { source: { assetsInclude: /\.pdf$/, }, }; ``` After adding the above configuration, you can import `*.pdf` files in your code, for example: ```js import myFile from './static/myFile.pdf'; console.log(myFile); // "/static/myFile.[hash].pdf" ``` ### Use `tools.rspack` You can modify the built-in Rspack configuration and add custom static assets handling rules via [tools.rspack](/config/tools/rspack.md). For example, to treat `*.pdf` files as assets and output them to the dist directory, you can add the following configuration: ```ts title="rsbuild.config.ts" export default { tools: { rspack(config, { addRules }) { addRules([ { test: /\.pdf$/, // converts asset to a separate file and exports the URL address. type: 'asset/resource', }, ]); }, }, }; ``` For more information about asset modules, please refer to [Rspack - Asset modules](https://rspack.dev/guide/features/asset-module). ### Related configurations Extended static asset types will be affected by the following configurations: * [output.filename.assets](/config/output/filename.md): Set the name of extended static assets. * [output.distPath.assets](/config/output/dist-path.md): Set the output directory of extended static assets. * [output.dataUriLimit.assets](/config/output/data-uri-limit.md): Set the threshold of inlining for extended static assets. ## Custom rules In some scenarios, you may need to bypass the built-in assets processing rules of Rsbuild and add some custom rules. Taking PNG image as an example, you need to: 1. Modify the built-in Rspack config via [tools.bundlerChain](/config/tools/bundler-chain.md) to exclude `.png` files using the `exclude` method. 2. Add custom asset processing rules via [tools.rspack](/config/tools/rspack.md). ```ts title="rsbuild.config.ts" export default { tools: { bundlerChain(chain, { CHAIN_ID }) { chain.module // Use `CHAIN_ID.RULE.IMAGE` to locate the built-in image rule .rule(CHAIN_ID.RULE.IMAGE) .exclude.add(/\.png$/); }, rspack(config, { addRules }) { addRules([ { test: /\.png$/, // Add a custom loader to handle png images loader: 'custom-png-loader', }, ]); }, }, }; ``` ## Image format When using image assets, you can choose a appropriate image format according to the pros and cons in the table below. | Format | Pros | Cons | Scenarios | | ------ | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | PNG | Lossless compression, no loss of picture details, no distortion, support for translucency | Not suitable for pictures with complex color tables | Suitable for pictures with few colors and well-defined borders, suitable for logos, icons, transparent images and other scenes | | JPG | Rich colors | Lossy compression, which will cause image distortion, does not support transparency | Suitable for pictures with a large number of colors, gradients, and overly complex pictures, suitable for portrait photos, landscapes and other scenes | | WebP | Supports both lossy and lossless compression, supports transparency, and is much smaller than PNG and JPG | iOS compatibility is not good | Pixel images of almost any scene, and the hosting environment that supports WebP, should prefer WebP image format | | SVG | Lossless format, no distortion, supports transparency | Not suitable for complex graphics | Suitable for vector graphics, suitable for icons | --- url: /guide/basic/html-template.md --- # HTML During the build process, Rsbuild will compile based on the HTML template and template parameters to generate several HTML files. Rsbuild provides some configs to set the HTML template. Through this chapter, you can learn the basic usage of these configs. ## Set template In Rsbuild, you can use [html.template](/config/html/template.md) config to define the path to the custom HTML template. ```ts export default { html: { template: './static/index.html', }, }; ``` If `html.template` is not set, Rsbuild will use the built-in HTML template: ```html title="defaultTemplate.html" <!doctype html> <html> <head></head> <body> <div id="<%= mountId %>"></div> </body> </html> ``` ## Set page title You can set the HTML `<title>` tag through the [html.title](/config/html/title.md) config. When there is only one page in your project, just use the `html.title` setting directly: ```ts export default { html: { title: 'example', }, }; ``` When your project has multiple pages, you can set corresponding titles for different pages based on the entry name. ```ts export default { html: { title({ entryName }) { const titles = { foo: 'Foo', bar: 'Bar', }; return titles[entryName]; }, }, }; ``` :::tip For single-page applications (SPA), Rsbuild will include an initial title in the HTML page, but you usually need to dynamically update the page title on route switching, for example using some routing libraries or libraries like [React Helmet](https://github.com/nfl/react-helmet). ::: ## Set page icon Rsbuild supports setting [favicon](https://developer.mozilla.org/en-US/docs/Glossary/Favicon) icon and [apple-touch-icon](https://webhint.io/docs/user-guide/hints/hint-apple-touch-icons/) icon. You can set the favicon through the [html.favicon](/config/html/favicon.md) config. ```ts export default { html: { favicon: './src/assets/icon.png', }, }; ``` You can also set the web application icons to display when added to the home screen of a mobile device through the [html.appIcon](/config/html/app-icon.md) config. ```ts export default { html: { appIcon: { name: 'My Website', icons: [ { src: './src/assets/logo-192.png', size: 192 }, { src: './src/assets/logo-512.png', size: 512 }, ], }, }, }; ``` ## Set meta tags You can set the meta tags through the [html.meta](/config/html/meta.md) config. Rsbuild defaults to setting the charset and viewport meta tags: ```html <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> ``` You can also add custom meta tags, such as setting the description: ```ts export default { html: { meta: { description: 'a description of the page', }, }, }; ``` The generated meta tag in HTML is: ```html <meta name="description" content="a description of the page" /> ``` ## Default template engine Rsbuild comes with a built-in default template engine to handle HTML template files, and its syntax is similar to a subset of EJS, but it has some differences. When the suffix of an HTML template file is `.html`, Rsbuild will use the built-in template engine to parse the HTML template. For example, if a `text` param is defined in the template with the value `'world'`, Rsbuild will automatically replace `<%= text %>` with the specified value during the build process. ```html <!-- Input --> <div>hello <%= text %>!</div> <!-- Output --> <div>hello world!</div> ``` ### Template parameters In HTML templates, you can use a variety of template parameters. The template parameters injected by Rsbuild by default include: ```ts type DefaultParameters = { mountId: string; // the value of `html.mountId` config entryName: string; // entry name assetPrefix: string; // the value of dev.assetPrefix or output.assetPrefix configs compilation: Compilation; // Compilation object of Rspack rspackConfig: Rspack.Configuration; // Rspack config object // generated by html-rspack-plugin htmlPlugin: { tags: { headTags: HtmlTagObject[]; bodyTags: HtmlTagObject[]; }; files: { publicPath: string; js: Array<string>; css: Array<string>; favicon?: string; }; }; }; ``` You can use the [html.templateParameters](/config/html/template-parameters.md) config to pass in custom template parameters. For example: ```ts title="rsbuild.config.ts" export default { html: { templateParameters: { text: 'world', }, }, }; ``` Then you can read parameters in the HTML template with `<%= text %>`: ```html title="index.html" <div>hello <%= text %>!</div> ``` The compiled HTML code will be: ```html title="dist/index.html" <div>hello world!</div> ``` ### Parameter escaping When using `<%= text %>`, the parameters will not be escaped. You can use `<%- text %>` to escape parameters. For example, if the value of the parameter `text` is `'<script>'`, it will be escaped to `<script>`: ```html <!-- Input --> <div>hello <%- text %>!</div> <!-- Output --> <div>hello <script>!</div> ``` :::tip Note that Rsbuild's default escape syntax is different from EJS. In EJS, the default escape syntax is `<%= text %>`, whereas Rsbuild's default escape syntax is `<%- text %>`. ::: ## Other template engines Rsbuild also supports using other template engines via plugins, such as [EJS](https://ejs.co/) and [Pug](https://pugjs.org/). ### EJS Rsbuild's built-in template syntax has some differences from [EJS](https://ejs.co/). To use the full EJS syntax, you can support it through a plugin. See [rsbuild-plugin-ejs](https://github.com/rspack-contrib/rsbuild-plugin-ejs) for more details. ### Pug Rsbuild supports the [Pug](https://pugjs.org/) template engine via a plugin. See [@rsbuild/plugin-pug](https://github.com/rspack-contrib/rsbuild-plugin-pug) for more details. ## Injecting tags You can insert any tags into the HTML files generated by Rsbuild by configuring [html.tags](/config/html/tags.md). In the HTML template, the `htmlPlugin.tags` variable gives you access to all the tags inserted into the HTML: ```html title="index.html" <html> <head> <%= htmlPlugin.tags.headTags %> </head> <body> <div id="root"></div> <%= htmlPlugin.tags.bodyTags %> </body> </html> ``` The purpose of the `html.tags` is to update these tag variables to modify the tags in the HTML. Here is a basic example: ```ts export default { html: { tags: [ { tag: 'script', attrs: { src: 'https://cdn.example.com/my-script.js' } }, ], }, }; ``` * The generated HTML file looks like this: ```html <html> <head> <script src="https://cdn.example.com/my-script.js"></script> <!-- some other headTags... --> </head> <body> <!-- some other bodyTags... --> </body> </html> ``` > For more usage, please refer to: [html.tags](/config/html/tags.md). :::tip Typically, you do not need to manually use the `htmlPlugin.tags.headTags` and `htmlPlugin.tags.bodyTags` template parameters, because Rsbuild will automatically inject these tags. See [html.inject](/config/html/inject.md) for more details on adjusting the injection location. ::: ## HTML plugin Rsbuild internally implements HTML-related features based on [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). It is a fork of [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin), with the same features and options. You can modify the html-rspack-plugin options via [tools.htmlPlugin](/config/tools/html-plugin.md), or disable the default html-rspack-plugin. For example: ```ts title="rsbuild.config.ts" export default { tools: { htmlPlugin(config, { entryName }) { if (process.env.NODE_ENV === 'production') { config.filename = `${entryName}.[contenthash:8].html`; } }, }, }; ``` ## HTML minification Rsbuild currently does not minify HTML files. If you need to minify HTML files, you can use the [rsbuild-plugin-html-minifier-terser plugin](https://github.com/rspack-contrib/rsbuild-plugin-html-minifier-terser). --- url: /guide/basic/json-files.md --- # JSON Rsbuild supports import JSON files in code, and also supports import [YAML](https://yaml.org/) and [Toml](https://toml.io/en/) files and converting them to JSON format. ## JSON file You can import JSON files directly in JavaScript files. ### Example ```json title="example.json" { "name": "foo", "items": [1, 2] } ``` ```js title="index.js" import example from './example.json'; console.log(example.name); // 'foo'; console.log(example.items); // [1, 2]; ``` ### Named import Rsbuild also supports importing JSON files via named import: ```js import { name } from './example.json'; console.log(name); // 'foo'; ``` ## YAML file [YAML](https://yaml.org/) is a data serialization language commonly used for writing configuration files. Rsbuild provides the [@rsbuild/plugin-yaml](https://github.com/rspack-contrib/rsbuild-plugin-yaml). After registering the plugin, you can import `.yaml` or `.yml` files in JavaScript and they will be automatically converted to JavaScript objects. ```ts title="rsbuild.config.ts" import { pluginYaml } from '@rsbuild/plugin-yaml'; export default { plugins: [pluginYaml()], }; ``` ### Example ```yaml title="example.yaml" --- hello: world foo: bar: baz ``` ```js import example from './example.yaml'; console.log(example.hello); // 'world'; console.log(example.foo); // { bar: 'baz' }; ``` ## TOML file [TOML](https://toml.io/) is a semantically explicit, easy-to-read configuration file format. Rsbuild provides the [@rsbuild/plugin-toml](https://github.com/rspack-contrib/rsbuild-plugin-toml). After registering the plugin, you can import `.toml` files in JavaScript and it will be automatically converted to JavaScript objects. ```ts title="rsbuild.config.ts" import { pluginToml } from '@rsbuild/plugin-toml'; export default { plugins: [pluginToml()], }; ``` ### Example ```toml title="example.toml" hello = "world" [foo] bar = "baz" ``` ```js title="src/env.d.ts" import example from './example.toml'; console.log(example.hello); // 'world'; console.log(example.foo); // { bar: 'baz' }; ``` ## Type declaration When you import YAML or Toml files in TypeScript code, please create a `src/env.d.ts` file in your project and add the corresponding type declarations. * Method 1: If the `@rsbuild/core` package is installed, you can reference the [preset types](/guide/basic/typescript.md#preset-types) provided by `@rsbuild/core`: ```ts title="src/env.d.ts" /// <reference types="@rsbuild/core/types" /> ``` * Method 2: Manually add the required type declarations: ```ts title="src/env.d.ts" declare module '*.yaml' { const content: Record<string, any>; export default content; } declare module '*.yml' { const content: Record<string, any>; export default content; } declare module '*.toml' { const content: Record<string, any>; export default content; } ``` --- url: /guide/basic/wasm-assets.md --- # Wasm Rsbuild provides native support for WebAssembly (WASM) modules, allowing you to import and use `.wasm` files directly in your project. :::tip What is WebAssembly WebAssembly (Wasm) is a portable, high-performance binary format designed to execute CPU-intensive computing tasks in modern web browsers, bringing performance and reliability similar to native compiled code to the web platform. ::: ## Import You can import a WebAssembly module directly in a JavaScript file: ```js title="index.js" import { add } from './add.wasm'; console.log(add); // [native code] console.log(add(1, 2)); // 3 ``` WebAssembly modules can also be imported via dynamic import: ```js title="index.js" import('./add.wasm').then(({ add }) => { console.log('---- Async Wasm Module'); console.log(add); // [native code] console.log(add(1, 2)); // 3 }); ``` You can also get the path of a WebAssembly module using the `new URL` syntax: ```js title="index.js" const wasmURL = new URL('./add.wasm', import.meta.url); console.log(wasmURL).pathname; // "/static/wasm/[hash].module.wasm" ``` ## Output directory When a `.wasm` asset is imported, it will be output by Rsbuild to the `dist/static/wasm` directory by default. You can change the output directory of `.wasm` files via [output.distPath](/config/output/dist-path.md) config. ```ts export default { output: { distPath: { wasm: 'resource/wasm', }, }, }; ``` ## Type declaration When you import a Wasm file in TypeScript code, you usually need to add the corresponding type declaration. For example, the `add.wasm` file exports an `add()` method, then you can create an `add.wasm.d.ts` file in the same directory and add the corresponding type declaration: ```ts title="add.wasm.d.ts" export const add = (num1: number, num2: number) => number; ``` --- url: /guide/basic/typescript.md --- # TypeScript Rsbuild supports TypeScript by default, allowing you to directly use `.ts` and `.tsx` files in your projects. ## TypeScript transpilation Rsbuild uses SWC by default for transpiling TypeScript code, and it also supports switching to Babel for transpilation. ### isolatedModules Unlike the native TypeScript compiler, tools like SWC and Babel compile each file separately and cannot determine whether an imported name is a type or a value. Therefore, when using TypeScript in Rsbuild, you need to enable the [isolatedModules](https://typescriptlang.org/tsconfig/#isolatedModules) option in your `tsconfig.json` file: ```json title="tsconfig.json" { "compilerOptions": { "isolatedModules": true } } ``` This option can help you avoid using certain syntax that cannot be correctly compiled by SWC and Babel, such as cross-file type references. It will guide you to correct the corresponding usage: ```ts // Wrong export { SomeType } from './types'; // Correct export type { SomeType } from './types'; ``` > See [SWC - Migrating from tsc](https://swc.rs/docs/migrating-from-tsc) for more details about the differences between SWC and tsc. ## Preset types `@rsbuild/core` provides some preset type definitions, including CSS Modules, static assets, `import.meta` and other types. You can create a `src/env.d.ts` file to reference it: ```ts title="src/env.d.ts" /// <reference types="@rsbuild/core/types" /> ``` ## Type checking When transpiling TypeScript code using tools like SWC and Babel, type checking is not performed. Rsbuild provides the Type Check plugin, which runs TypeScript type checking in a separate process. The plugin internally integrates [ts-checker-rspack-plugin](https://github.com/rspack-contrib/ts-checker-rspack-plugin). Please refer to the [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check) for usage instructions. ## tsconfig.json Path Rsbuild by default reads the `tsconfig.json` file from the root directory. You can use the [source.tsconfigPath](/config/source/tsconfig-path.md) to configure a custom tsconfig.json file path. ```ts export default { source: { tsconfigPath: './tsconfig.custom.json', }, }; ``` ## Path extensions When importing another module in a TypeScript module, TypeScript allows using the `.js` file extension: ```ts title="src/index.ts" // The actual referenced module could be `./some-module.ts` or `./some-module.tsx` import { someFn } from './some-module.js'; ``` Rsbuild supports this feature through Rspack's [extensionAlias](https://rspack.dev/config/resolve#resolveextensionalias) configuration. In TypeScript projects, Rsbuild adds the following configuration by default: ```js const rspackConfig = { resolve: { extensionAlias: { '.js': ['.js', '.ts', '.tsx'], '.jsx': ['.jsx', '.tsx'], }, }, }; ``` This means: * You can use the `.js` extension to import `.ts` or `.tsx` files. * You can use the `.jsx` extension to import `.tsx` files. ## Decorators version Rsbuild does not read the `experimentalDecorators` option in `tsconfig.json`, instead, it provides the [decorators.version](/config/source/decorators.md#decoratorsversion) configuration to specify the decorator version. By default, Rsbuild uses the `2022-03` version of the decorators, you can also set it to `legacy` to use the legacy decorators: ```ts title="rsbuild.config.ts" export default { source: { decorators: { version: 'legacy', }, }, }; ``` --- url: /guide/basic/web-workers.md --- # Web Workers This chapter introduces how to configure and use [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) in Rsbuild project. :::tip Web Workers Web Workers are a type of JavaScript program that runs in the background, independently of other scripts, without affecting the performance of the page. This makes it possible to run long-running scripts, such as ones that handle complex calculations or access remote resources, without blocking the user interface or other scripts. Web workers provide an easy way to run tasks in the background and improve the overall performance of web applications. ::: ## Use Web Workers ### Import with constructors Web Workers are first-class citizens of Rspack, which means you don't need any loader to use web workers directly in Rspack or Rsbuild projects. For example, create a file called `worker.js`: ```js title=worker.js self.onmessage = (event) => { const result = event.data * 2; self.postMessage(result); }; ``` Then use this worker in the main thread: ```js title=index.js const worker = new Worker(new URL('./worker.js', import.meta.url)); worker.onmessage = (event) => { console.log('The results from Workers:', event.data); }; worker.postMessage(10); ``` For more details, please refer to [Rspack - Web Workers](https://rspack.dev/guide/features/web-workers). ### Using worker-loader > `worker-loader` is no longer maintained, it is recommended to use the `new Worker()` syntax. If your project already uses `worker-loader`, or you want to use the `inline` and other features provided by `worker-loader`, you can use [worker-rspack-loader](https://github.com/rspack-contrib/worker-rspack-loader) as an alternative to `worker-loader` in the Rsbuild or Rspack project. ```ts export default { tools: { rspack: { resolveLoader: { alias: { // Modify the resolution of worker-loader in the inline loader, such as `worker-loader!pdfjs-dist/es5/build/pdf.worker.js` 'worker-loader': require.resolve('worker-rspack-loader'), }, }, module: { rules: [ { test: /\.worker\.js$/, loader: 'worker-rspack-loader', }, ], }, }, }, }; ``` ### Loading scripts from remote URLs (cross-origin) By default, the worker script will be emitted as a separate chunk. This script supports uploading to CDN, but must obey the [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy). If you want your worker scripts to be accessible across domains, a common solution is to load via [importScripts](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts) (not subject to CORS), you can refer to the following code: ```js title=index.js {2} // https://github.com/jantimon/remote-web-worker import 'remote-web-worker'; const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'classic', }); worker.onmessage = (event) => { console.log('The results from Workers:', event.data); }; worker.postMessage(10); ``` For detailed discussions on cross-domain issues, please refer to [Discussions - webpack 5 web worker support for CORS?](https://github.com/webpack/webpack/discussions/14648) ## Build Web Workers outputs Rsbuild supports building Web Workers outputs independently, which is helpful when you need to provide Web Workers outputs for use by other applications. You can set Rsbuild's [output.target](/config/output/target.md) configuration to `'web-worker'`, and Rsbuild will generate build outputs suitable for the Web Workers environment. ```ts export default { output: { target: 'web-worker', }, }; ``` --- url: /guide/basic/static-deploy.md --- # Deploy static site This section introduces how to deploy the build outputs of Rsbuild as a static site. ## Background information Before starting the deployment, you need to understand some background information: * The CLI commands used for building and previewing outputs. * The directory structure of the build outputs. * The URL prefix of static assets. ### Build commands The build commands provided by Rsbuild: * [build command](/guide/basic/cli.md#rsbuild-build), used to generate the build outputs for production deployment. * [preview command](/guide/basic/cli.md#rsbuild-preview), used to preview the production build outputs locally. Note that you need to execute the `rsbuild build` command beforehand to generate the build outputs. ```json title="package.json" { "scripts": { "build": "rsbuild build", "preview": "rsbuild preview" } } ``` :::tip The preview command is only used for local preview. Do not use it for production servers, as it is not designed for that. ::: ### Output directory Rsbuild's build outputs typically includes HTML, JS, CSS, and other assets, and is output to the `dist` directory by default. The name and structure of the dist directory can be changed using some configuration options. See the [Output Files](/guide/basic/output-files.md) section for more information. ```bash dist ├── static │ ├── image │ ├── css │ └── js └── [name].html ``` ### Asset prefix We can divide the build output into two parts: **HTML files** and **static assets**. * HTML files refer to files with the `.html` suffix in the output directory, which usually need to be deployed on the server. * Static assets are located in the `static` directory of the output folder, which contains assets such as JavaScript, CSS, and images. They can be deployed either on the server or on a CDN. If the static assets are deployed in a subdirectory of the server, you can configure [output.assetPrefix](/config/output/asset-prefix.md) as the base path: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { assetPrefix: '/some-base-folder/', }, }); ``` If you want to place these static assets on a CDN for better performance, rather than directly on the server like HTML, you will need to configure the [output.assetPrefix](/config/output/asset-prefix.md) to the CDN address to allow the application to properly reference these static assets. ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { assetPrefix: 'https://cdn.com/path/', }, }); ``` In this way, when referencing static assets in HTML, the specified prefix will be automatically added, for example: ```html <script src="https://cdn.com/path/static/js/index.some-hash.js"></script> ``` ## GitHub pages [GitHub Pages](https://pages.github.com/) is a static site hosting service that takes HTML, CSS, and JavaScript files straight from a repository on GitHub The following are step-by-step examples on how to deploy on GitHub Pages. 1. Set the URL prefix for static assets through [output.assetPrefix](/config/output/asset-prefix.md). ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ output: { // Please replace <REPO_NAME> with the repository name. // For example, "/my-project/" assetPrefix: '/<REPO_NAME>/', }, }); ``` 2. Open the "Settings" page of GitHub repository, click "Pages" from the left menu to access the configuration page of GitHub Pages. 3. Select "Source" -> "GitHub Actions" and click "create your own" to create a GitHub Action config file. 4. Paste the following content into the input box and name the file `github-pages.yml` (you can adjust the content and name of the file as needed). ```yaml title="github-pages.yml" # Sample workflow for building and deploying a Rsbuild site to GitHub Pages name: Rsbuild Deployment on: # Runs on pushes targeting the default branch push: branches: ['main'] # Allows you to run this workflow manually from the actions tab workflow_dispatch: # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment concurrency: group: 'pages' cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: node-version: 22 # If you use other package managers like yarn or pnpm, # you will need to install them first - name: Install dependencies run: npm i - name: Build run: npm run build - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: path: './dist' - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 ``` 5. Commit and wait for GitHub Actions to execute. Once it's done, you can visit `https://<USERNAME>.github.io/<REPO_NAME>/` to view the deployed page. ## Netlify [Netlify Core](https://netlify.com/) is a frontend cloud solution for developers to build and deploy future-proof digital solutions with modern, composable tooling. ### Add new site Netlify provides a detailed guide, you can follow the instructions in [Netlify - Add new site](https://docs.netlify.com/welcome/add-new-site/), set up some basic information, and then you can start the deployment. You need to configure the following two fields: * **Build command**: fill in the build command of the project, it is typically `npm run build`. * **Publish directory**: fill in the output directory in the project, the default is `dist`. Then click on the **Deploy site** button to start the deployment. ### Custom domains If you want to make your sites accessible at your own domain names, you can configure it in the "Domain management" section of Netlify. > Detailed guide: [Netlify - Custom domains](https://docs.netlify.com/domains-https/custom-domains/). ## Vercel [Vercel](https://vercel.com/) is a platform for developers that provides the tools, workflows, and infrastructure you need to build and deploy your web apps faster, without the need for additional configuration. ### Add new site Vercel provides a detailed guide that you can follow [Vercel - Projects](https://vercel.com/docs/projects/overview) to create a project in your dashboard and configure some basic information to start deployment. You only need to configure the fields under "Build and Output Settings": * **Output directory**: fill in the output directory in the project, the default is `dist`. Then click the **Deploy** button to start the deployment. ### Configure domains If you want to make your sites accessible at your own domain names, you can configure it in the "Domains" section of Vercel. > Detailed guide: [Vercel - Domains](https://vercel.com/docs/projects/domains). ## Cloudflare Pages [Cloudflare Pages](https://developers.cloudflare.com/pages/) is a static site hosting platform provided by Cloudflare. You can follow the [Cloudflare Pages - Git integration guide](https://developers.cloudflare.com/pages/get-started/git-integration/) to integrate with Git and deploy your site to Cloudflare Pages. When configuring, you need to fill in the following fields in the "Build settings": * **Build command**: fill in the build command of the project, it is typically `npm run build`. * **Build output directory**: fill in the output directory in the project, the default is `dist`. Then click on the **Save and Deploy** button to start the deployment. --- url: /guide/basic/upgrade-rsbuild.md --- # Upgrade Rsbuild This section explains how to upgrade the project's Rsbuild dependencies to the latest version. > Please see [Releases](/community/releases/index.md) to understand the Rsbuild release strategy. ## Using taze We recommend using [Taze](https://github.com/antfu-collective/taze) to upgrade the Rsbuild version. Taze is a CLI tool for updating npm dependencies. ### Usage Run the following command to upgrade all dependencies that include `rsbuild` in their names: ```bash npx taze --include /rsbuild/ -w ``` The result will look similar to: ```bash rsbuild - 3 patch @rsbuild/core dev ~2mo ^0.6.0 → ^0.6.15 @rsbuild/plugin-react dev ~2mo ^0.6.0 → ^0.6.15 @rsbuild/plugin-type-check dev ~2mo ^0.6.0 → ^0.6.15 ℹ changes written to package.json, run npm i to install updates. ``` You can also adjust the `include` pattern to match specific packages, for example, to upgrade only packages under the `@rsbuild` scope: ```bash npx taze --include /@rsbuild/ -w ``` ### Options Here are some examples of using taze options. * In a monorepo, you can add the `-r` option to upgrade recursively: ```bash npx taze --include /rsbuild/ -w -r ``` * Add `-l` to upgrade locked versions: ```bash npx taze --include /rsbuild/ -w -l ``` * To upgrade to a major version: ```bash npx taze major --include /rsbuild/ -w ``` > For more options, please refer to the [taze documentation](https://github.com/antfu-collective/taze). --- url: /guide/configuration/rspack.md --- # Configure Rspack Rsbuild supports directly modifying the Rspack configuration object, and also supports modifying the built-in Rspack configuration of Rsbuild through `rspack-chain`. :::tip The built-in Rspack config in Rsbuild may change with iterations, and these changes won't be reflected in semver. Therefore, your custom config may become invalid when you upgrade Rsbuild. ::: ## View Rspack config Rsbuild provides the [rsbuild inspect](/guide/basic/cli.md#rsbuild-inspect) command to view the final Rspack config generated by Rsbuild. You can also view it through [debug mode](/guide/debug/debug-mode.md). ## Modify config object You can use the [tools.rspack](/config/tools/rspack.md) option of Rsbuild to modify the Rspack config object. For example, register Rspack plugins or webpack plugins: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { plugins: [SomeWebpackPlugin()], }, }, }; ``` Or modify the Rspack config with a function: ```ts title="rsbuild.config.ts" export default { tools: { rspack: (config, { env }) => { if (env === 'development') { config.devtool = 'cheap-module-eval-source-map'; } return config; }, }, }; ``` > Please refer to the [tools.rspack documentation](/config/tools/rspack.md) for detailed usage. ## Access Rspack API If you need to access the API or plugins exported by [@rspack/core](https://npmjs.com/package/@rspack/core), you can directly import the [rspack](/api/javascript-api/core.md#rspack) object from `@rsbuild/core` without installing the `@rspack/core` package separately. ```ts title="rsbuild.config.ts" import { rspack } from '@rsbuild/core'; export default { tools: { rspack: { plugins: [ new rspack.BannerPlugin({ // ... }), ], }, }, }; ``` :::tip * Refer to [Rspack plugins](https://rspack.dev/plugins/) and [Rspack JavaScript API](https://rspack.dev/api/javascript-api/) to learn more about the available Rspack APIs. * It's not recommended to manually install the `@rspack/core` package, as it may conflict with the version that Rsbuild depends on. ::: ## Use bundler chain ### tools.bundlerChain Rsbuild provides the [tools.bundlerChain](/config/tools/bundler-chain.md) config to modify the rspack-chain. Its value is a function that takes two arguments: * The first argument is an `rspack-chain` instance, which you can use to modify the Rspack config. * The second argument is an utils object, including `env`, `isProd`, `CHAIN_ID`, etc. Here's a basic example: ```ts title="rsbuild.config.ts" export default { tools: { bundlerChain: (chain, { env }) => { if (env === 'development') { chain.devtool('cheap-module-eval-source-map'); } }, }, }; ``` `tools.bundlerChain` can also be an async function: ```ts title="rsbuild.config.ts" export default { tools: { bundlerChain: (chain, { env }) => { const value = await fetchValue(); chain.devtool(value); }, }, }; ``` ### Basics Before using the rspack-chain to modify the Rspack configuration, it is recommended to familiarize yourself with some basics. #### About ID In short, the rspack-chain requires users to set a unique ID for each rule, loader, plugin, and minimizer. With this ID, you can easily find the desired object from deeply nested objects. Rsbuild exports all internally defined IDs through the `CHAIN_ID` object, so you can quickly locate the loader or plugin you want to modify using these exported IDs, without the need for complex traversal in the Rspack configuration object. For example, you can remove the built-in HTML plugin using `CHAIN_ID.PLUGIN.HTML`: ```ts title="rsbuild.config.ts" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { // chain.plugins.delete(CHAIN_ID.PLUGIN.HTML); }, }, }; ``` #### ID types The `CHAIN_ID` object contains various IDs, which correspond to the following configurations: | CHAIN\_ID Field | Corresponding Configuration | Description | | ------------------------- | --------------------------- | ----------------------------------------------------------- | | `CHAIN_ID.PLUGIN` | `plugins[i]` | Corresponds to a plugin in the Rspack configuration | | `CHAIN_ID.RULE` | `module.rules[i]` | Corresponds to a rule in the Rspack configuration | | `CHAIN_ID.USE` | `module.rules[i].loader` | Corresponds to a loader in the Rspack configuration | | `CHAIN_ID.MINIMIZER` | `optimization.minimizer` | Corresponds to a minimizer in the Rspack configuration | | `CHAIN_ID.RESOLVE_PLUGIN` | `resolve.plugins[i]` | Corresponds to a resolve plugin in the Rspack configuration | ### Examples #### Configure loader Here are examples of adding, modifying, and removing Rspack loaders. * Add a loader to handle `.md` files: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain) => { chain.module .rule('md') .test(/\.md$/) .use('md-loader') // The package name or module path of the loader .loader('md-loader'); }, }, }; ``` * Modify options of the built-in SWC loader: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { chain.module .rule(CHAIN_ID.RULE.JS) .use(CHAIN_ID.USE.SWC) .tap((options) => { console.log(options); return options; }); }, }, }; ``` * Remove the built-in SWC loader: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { chain.module.rule(CHAIN_ID.RULE.JS).uses.delete(CHAIN_ID.USE.SWC); }, }, }; ``` * Insert a loader after the built-in SWC loader that executes earlier: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { chain.module .rule(CHAIN_ID.RULE.JS) .use('my-loader') .after(CHAIN_ID.USE.SWC) // The package name or module path of the loader .loader('my-loader') .options({ // some options }); }, }, }; ``` > Note: Rspack loaders are executed in reverse order. * Insert a loader before the built-in SWC loader that executes later: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { chain.module .rule(CHAIN_ID.RULE.JS) // Loader ID, not actually meaningful, just for locating .use('my-loader') .before(CHAIN_ID.USE.SWC) // The package name or module path of the loader .loader('my-loader') .options({ // some options }); }, }, }; ``` * Remove the built-in CSS handling rule: ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { CHAIN_ID }) => { chain.module.rules.delete(CHAIN_ID.RULE.CSS); }, }, }; ``` #### Configure plugin Here are examples of adding, modifying, and deleting Rspack plugins. ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { bundler, CHAIN_ID }) => { // Add plugin chain.plugin('custom-define').use(bundler.DefinePlugin, [ { 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV), }, }, ]); // Modify plugin chain.plugin(CHAIN_ID.PLUGIN.HMR).tap((options) => { options[0].fullBuildTimeout = 200; return options; }); // Delete plugin chain.plugins.delete(CHAIN_ID.PLUGIN.HMR); }, }, }; ``` #### Modify based on environment In the `tools.bundlerChain` function, you can access various environment identifiers in the second parameter, such as development/production build, SSR build, Web Worker build, to achieve configuration modifications for different environments. ```js title="rsbuild.config.mjs" export default { tools: { bundlerChain: (chain, { env, isProd, target, isServer, isWebWorker }) => { if (env === 'development' || env === 'test') { // ... } if (isProd) { // ... } if (target === 'node') { // ... } if (isServer) { // ... } if (isWebWorker) { // ... } }, }; ``` The above are some common configuration examples. For the complete rspack-chain API, please refer to the [rspack-chain documentation](https://github.com/rspack-contrib/rspack-chain). ## Configuration modification order Rsbuild supports modifying the Rspack configuration object through `tools.rspack`, `tools.bundlerChain`, `modifyBundlerChain`, etc. The order of execution between them is: * [modifyBundlerChain](/plugins/dev/hooks.md#modifybundlerchain) * [tools.bundleChain](/config/tools/bundler-chain.md) * [modifyRspackConfig](/plugins/dev/hooks.md#modifyrspackconfig) * [tools.rspack](/config/tools/rspack.md) --- url: /guide/configuration/rsbuild.md --- # Configure Rsbuild Rsbuild provides a wide range of configuration options and sets a common default value for each option, which can meet the requirements of most use cases. Therefore, in most cases, you don't need to declare any Rsbuild configurations and can use it out of the box. If you need to customize build behaviors, you can use these configuration options. ## Configuration structure The configuration structure of Rsbuild looks like this: ```js title="rsbuild.config.mjs" export default { plugins: [ // configure Rsbuild plugins ], dev: { // options for local development }, html: { // options for HTML generation }, tools: { // options for the low-level tools }, output: { // options for build outputs }, resolve: { // options for module resolution }, source: { // options for input source code }, server: { // options for the Rsbuild server, // will take effect during local development and preview }, security: { // options for Web security }, performance: { // options for build performance and runtime performance }, moduleFederation: { // options for module federation }, environments: { // define different Rsbuild configurations for each environment }, }; ``` You can find detailed descriptions of all configs on the [Configure Overview](/config/index.md) page. ## Configuration file When you use the CLI of Rsbuild, Rsbuild will automatically read the configuration file in the root directory of the current project and resolve it in the following order: * rsbuild.config.mjs * rsbuild.config.ts * rsbuild.config.js * rsbuild.config.cjs * rsbuild.config.mts * rsbuild.config.cts We recommend using the `.mjs` or `.ts` format for the configuration file and importing the `defineConfig` utility function from `@rsbuild/core`. It provides friendly TypeScript type hints and autocompletion, which can help you avoid errors in the configuration. For example, in `rsbuild.config.ts`, you can define the Rsbuild [resolve.alias](/config/resolve/alias.md) configuration: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ resolve: { alias: { '@common': './src/common', }, }, }); ``` If you are developing a non-TypeScript project, you can use the `.mjs` format for the configuration file: ```js title="rsbuild.config.mjs" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ resolve: { alias: (opts) => { opts['@common'] = './src/common'; }, }, }); ``` ## Specify config file Rsbuild CLI uses the `--config` option to specify the config file, which can be set to a relative path or an absolute path. For example, if you need to use the `rsbuild.prod.config.mjs` file when running `build`, you can add the following scripts to `package.json`: ```json title="package.json" { "scripts": { "build": "rsbuild build --config rsbuild.prod.config.mjs" } } ``` You can also abbreviate the `--config` option to `-c`: ```bash rsbuild build -c rsbuild.prod.config.mjs ``` ## Specify config loader When you use a configuration file with the `.ts`, `.mts`, and `.cts` extensions, Rsbuild will use [jiti](https://github.com/unjs/jiti) to load configuration files, providing interoperability between ESM and CommonJS. The behavior of module resolution differs slightly from the native behavior of Node.js. If your JavaScript runtime already natively supports TypeScript, you can use the `--config-loader native` option to use the Node.js native loader to load the configuration file. This can ensure that the module resolution behavior is consistent with the native behavior of Node.js and has better performance. For example, Node.js v22.6.0+ already natively supports TypeScript, you can use the following command to use the Node.js native loader to load the configuration file: ```bash # Node.js v23.6.0+ # No need to set --experimental-strip-types npx rsbuild build --config-loader native # Node.js v22.6.0 - v23.5.0 # Need to set --experimental-strip-types NODE_OPTIONS="--experimental-strip-types" npx rsbuild build --config-loader native ``` > See [Node.js - Running TypeScript Natively](https://nodejs.org/en/learn/typescript/run-natively#running-typescript-natively) for more details. ## Using environment variables In the configuration file, you can use Node.js environment variables such as `process.env.NODE_ENV` to dynamically set different configurations: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ resolve: { alias: { '@request': process.env.NODE_ENV === 'development' ? './src/request.dev.js' : './src/request.prod.js', }, }, }); ``` ## Export function Rsbuild supports the export of a function in the config file, where you can dynamically compute the config and return it to Rsbuild. ```js title="rsbuild.config.js" import { defineConfig } from '@rsbuild/core'; export default defineConfig(({ env, command, envMode }) => ({ resolve: { alias: { '@foo': env === 'development' ? './src/foo.dev.ts' : './src/foo.prod.ts', }, }, })); ``` :::tip The exported config function must provide a return value. If you do not need to return any config, you can return an empty object. ::: The function accepts the following parameters: ### env * **Type:** `string` * **Default:** `process.env.NODE_ENV` The current running environment. * When running `rsbuild dev`, the default value of env is `development`. * When running `rsbuild build` or `rsbuild preview`, the default value of env is `production`. ### envMode * **Type:** `string` * **Default:** `process.env.NODE_ENV` The current value of the CLI parameter `--env-mode`. For example, when running `rsbuild build --env-mode test`, the value of `envMode` is `test`. ### command * **Type:** `string` The current running CLI command, such as `dev`, `build`, `preview`. ## Export async function Rsbuild also supports the export of an async function in the config file, where you can perform some async operations: ```js title="rsbuild.config.js" import { defineConfig } from '@rsbuild/core'; export default defineConfig(async ({ env, command }) => { const result = await someAsyncFunction(); return { html: { title: result, }, }; }); ``` ## Merge configurations You can use the [mergeRsbuildConfig](/api/javascript-api/core.md#mergersbuildconfig) function exported by `@rsbuild/core` to merge multiple configurations. ```ts title="rsbuild.config.ts" import { defineConfig, mergeRsbuildConfig } from '@rsbuild/core'; const config1 = defineConfig({ dev: { port: '3000' }, }); const config2 = defineConfig({ dev: { port: '3001' }, }); // { dev: { port: '3001' } export default mergeRsbuildConfig(config1, config2); ``` ## Debug the config You can enable Rsbuild's debug mode by adding the `DEBUG=rsbuild` environment variable when executing a build. ```bash DEBUG=rsbuild pnpm dev ``` In debug mode, Rsbuild will write the Rsbuild config to the dist directory, which is convenient for developers to view and debug. ``` config inspection completed, open the following files to view the content: - Rsbuild config: /Project/demo/dist/.rsbuild/rsbuild.config.mjs - Rspack config (web): /Project/demo/dist/.rsbuild/rspack.config.web.mjs ``` Open the generated `/dist/.rsbuild/rsbuild.config.mjs` file to see the complete content of the Rsbuild config. For a complete introduction to debug mode, see the [Debug Mode](/guide/debug/debug-mode.md) chapter. --- url: /guide/configuration/swc.md --- # Configure SWC [SWC](https://github.com/swc-project/swc) (Speedy Web Compiler) is a transformer and minimizer for JavaScript and TypeScript based on Rust. SWC provides similar functionality to Babel and Terser, and it is 20x faster than Babel on a single thread and 70x faster on four cores. Rsbuild enables the following SWC features by default: * Transform JavaScript and TypeScript code using Rspack's [builtin:swc-loader](https://rspack.dev/guide/features/builtin-swc-loader), which is the Rust version of [swc-loader](https://github.com/swc-project/pkgs/tree/main/packages/swc-loader). * Minify JavaScript code using Rspack's [SwcJsMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin). ## Loader options The options for `builtin:swc-loader` are the same as those for the JS version of `swc-loader`. Rsbuild exposes some options to configure `builtin:swc-loader`: * [tools.swc](/config/tools/swc.md):to configure the options for `builtin:swc-loader`. * [source.include](/config/source/include.md):to specify files that need to be compiled by SWC. * [source.exclude](/config/source/exclude.md):to exclude files that do not need to be compiled by SWC. Here are some examples: ### Register SWC plugin `tools.swc` can be used to register SWC's Wasm plugins, for example, registering [@swc/plugin-styled-components](https://npmjs.com/package/@swc/plugin-styled-components): ```js export default { tools: { swc: { jsc: { experimental: { plugins: [['@swc/plugin-styled-components', {}]], }, }, }, }, }; ``` > You can check out the [awesome-swc](https://github.com/swc-contrib/awesome-swc) repository to see the SWC plugins available in the community. ### SWC plugin version Please note that the SWC plugin is still an experimental feature, and the SWC Wasm plugin is currently not backward compatible. The version of the SWC plugin is closely tied to the version of `swc_core` that Rspack depends on. This means that you must to choose an SWC plugin that matches the current version of `swc_core` to ensure that it works properly. If the version of the SWC plugin you are using does not match the version of `swc_core` that Rspack depends on, Rspack will throw an error during the build process. Please refer to [Rspack FAQ - SWC Plugin Version Unmatched](https://rspack.dev/errors/swc-plugin-version) for more information. ### Enable Emotion support Example of enabling the Emotion support using the `builtin:swc-loader`: ```js export default { tools: { swc: { jsc: { experimental: { plugins: [['@swc/plugin-emotion', {}]], }, }, }, }, }; ``` For more options, please refer to [@swc/plugin-emotion](https://npmjs.com/package/@swc/plugin-emotion). ### Enable Relay support Example of enabling the Relay support using the `builtin:swc-loader`: ```js export default { tools: { swc: { jsc: { experimental: { plugins: [['@swc/plugin-relay', {}]], }, }, }, }, }; ``` For more options, please refer to [@swc/plugin-relay](https://npmjs.com/package/@swc/plugin-relay). ## Minimizer options Rsbuild provides the [output.minify.js](/config/output/minify.md) option to configure the SwcJsMinimizerRspackPlugin. Here are some examples: ### Exclude files You can exclude certain files from being minified using the `exclude` option: ```ts export default { output: { minify: { jsOptions: { exclude: /foo\/bar/, }, }, }, }; ``` ## Switching minifier See [output.minify - Switching minifier](/config/output/minify.md#switching-minifier) to learn how to switch to other JavaScript minifier. --- url: /guide/styling/css-usage.md --- # CSS Rsbuild provides out-of-the-box support for CSS, including PostCSS, CSS Modules, CSS preprocessors, CSS inlining, and CSS compression. Rsbuild also provides several configurations that allow customization of the processing rules for CSS files. ## Lightning CSS :::tip [Lightning CSS](https://lightningcss.dev) is a high performance CSS parser, transformer and minifier written in Rust. It supports parsing and transforming many modern CSS features into syntax supported by target browsers, and also provides a better compression ratio. ::: Rsbuild uses Rspack's built-in [lightningcss-loader](https://rspack.dev/guide/features/builtin-lightningcss-loader) to transform CSS code. It automatically reads the project's [browserslist](/guide/advanced/browserslist.md) config and converts the CSS code to syntax supported by target browsers. ### Features * Lightning CSS automatically adds vendor prefixes like `-webkit-`, `-moz-`, `-ms-`, etc., so you don't need to manually add prefixes or use the [autoprefixer](https://github.com/postcss/autoprefixer) plugin. * Lightning CSS automatically downgrades CSS syntax, allowing you to use modern CSS features such as CSS nesting and custom media queries in your code without worrying about browser compatibility issues. * You can use [tools.lightningcssLoader](/config/tools/lightningcss-loader.md) to customize the options for `lightningcss-loader`. ### Disabling Lightning CSS If Lightning CSS does not meet your needs, you can disable Lightning CSS and use [PostCSS](#using-postcss) to transform your CSS code. Steps: 1. Set [tools.lightningcssLoader](/config/tools/lightningcss-loader.md) to `false` to disable the Lightning CSS loader. 2. Use [@rsbuild/plugin-css-minimizer](https://github.com/rspack-contrib/rsbuild-plugin-css-minimizer) to switch the CSS minifier from Lightning CSS to cssnano or another CSS minifier. ```ts title="rsbuild.config.ts" import { pluginCssMinimizer } from '@rsbuild/plugin-css-minimizer'; export default { plugins: [pluginCssMinimizer()], tools: { lightningcssLoader: false, }, }; ``` 3. Refer to [PostCSS](#postcss) to configure the PostCSS plugins you need. Here are some commonly used PostCSS plugins: * [autoprefixer](https://github.com/postcss/autoprefixer): Adds vendor prefixes. * [postcss-preset-env](https://github.com/csstools/postcss-plugins/tree/main/plugin-packs/postcss-preset-env): Converts modern CSS into something most browsers can understand. * [postcss-nesting](https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-nesting): Supports CSS nesting. ## CSS minification When building for production, Rsbuild enables Rspack's built-in [LightningCssMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/lightning-css-minimizer-rspack-plugin) plugin to minify CSS assets for better transmission efficiency. * You can disable CSS minification through the [output.minify](/config/output/minify.md) option or customize the options for `LightningCssMinimizerRspackPlugin`. * You can use [@rsbuild/plugin-css-minimizer](https://github.com/rspack-contrib/rsbuild-plugin-css-minimizer) to customize the CSS minimizer, switching to [cssnano](https://github.com/cssnano/cssnano) or other CSS minimizer. ## PostCSS Rsbuild supports transforming CSS code through [PostCSS](https://postcss.org/). You can configure PostCSS in the following ways: ### Configuration file Rsbuild uses [postcss-load-config](https://github.com/postcss/postcss-load-config) to load the PostCSS configuration file in the root directory of the current project, such as `postcss.config.js`: ```js title="postcss.config.cjs" module.exports = { 'postcss-px-to-viewport': { viewportWidth: 375, }, }; ``` `postcss-load-config` supports multiple file formats, including but not limited to the following file names: * postcss.config.js * postcss.config.mjs * postcss.config.cjs * postcss.config.ts * ... ### tools.postcss You can also configure the postcss-loader through Rsbuild's [tools.postcss](/config/tools/postcss.md) option, which supports modifying the built-in configuration through a function, for example: ```ts title="rsbuild.config.ts" export default { tools: { postcss: (opts) => { const viewportPlugin = require('postcss-px-to-viewport')({ viewportWidth: 375, }); opts.postcssOptions.plugins.push(viewportPlugin); }, }, }; ``` ### Configuration priority * When you configure both the `postcss.config.js` file and the `tools.postcss` option, both will take effect, and the `tools.postcss` option will take precedence. * If there is no `postcss.config.js` file in the project and the `tools.postcss` option is not configured, Rsbuild will not register `postcss-loader`. ## CSS Modules Rsbuild supports CSS Modules by default, please read the [CSS Modules](/guide/styling/css-modules.md) chapter for the complete usage of CSS Modules. ## CSS preprocessors Rsbuild supports popular CSS preprocessors through plugins, including Sass, Less and Stylus. See how to use them: * [Sass Plugin](/plugins/list/plugin-sass.md) * [Less Plugin](/plugins/list/plugin-less.md) * [Stylus Plugin](/plugins/list/plugin-stylus.md) ## CSS-in-JS Please read the [React - CSS-in-JS](/guide/framework/react.md#css-in-js) section to learn how to use common CSS-in-JS libraries in Rsbuild. ## Inline CSS files By default, Rsbuild will extract CSS into a separate `.css` file and output it to the dist directory. To inline styles into your JS file, set [output.injectStyles](/config/output/inject-styles.md) to true to disable CSS extraction logic. When the JS file is requested by the browser, JS dynamically inserts the `<style>` tag into the Html to load the CSS styles. ```ts export default { output: { injectStyles: true, }, }; ``` This will increase the size of your JS Bundle, so it is usually not recommended to disable the CSS extraction. ## Import from node\_modules Rsbuild supports importing CSS files in `node_modules`. * Import in a JS file: ```ts title="src/index.js" /* reference normalize.css */ /* https://github.com/necolas/normalize.css */ import 'normalize.css'; ``` * Import in a CSS file: ```css title="src/index.css" @import 'normalize.css'; body { /* */ } ``` In Sass and Less files, it is also allowed to add the `~` prefix to resolve style files in `node_modules`. However, this is a **deprecated feature** and it is recommended to remove the `~` prefix from the code. ```scss title="src/index.scss" @import 'normalize.css'; ``` ## Query parameters ### inline Rsbuild supports importing compiled CSS files as strings in JavaScript by using the `?inline` query parameter. ```js import inlineCss from './style.css?inline'; console.log(inlineCss); // Output the compiled CSS file content ``` Using `import "*.css?inline"` has the following behaviors: * Get the compiled text content of the CSS file, processed by Lightning CSS, PostCSS and CSS preprocessors * The content will be inlined into the final JavaScript bundle * No separate CSS file will be generated :::tip * Rsbuild's Sass, Less, and Stylus plugins also support the `?inline` query parameter. * Rsbuild >= 1.3.0 supports the `?inline` query parameter. ::: ### raw Rsbuild supports importing raw CSS files as strings in JavaScript by using the `?raw` query parameter. ```ts title="src/index.js" import rawCss from './style.css?raw'; console.log(rawCss); // Output the raw content of the CSS file ``` Using `import "*.css?raw"` has the following behaviors: * Get the raw text content of the CSS file, without any preprocessing or compilation * The content of the CSS file will be inlined into the final JavaScript bundle * No separate CSS file will be generated :::tip * Rsbuild's Sass, Less, and Stylus plugins also support the `?raw` query parameter. * Rsbuild >= 1.3.0 supports the `?raw` query parameter. ::: --- url: /guide/styling/css-modules.md --- # CSS Modules [CSS Modules](https://github.com/css-modules/css-modules) allows us to write CSS code in a modular way, and these styles can be imported and used in JavaScript files. Using CSS Modules can automatically generate unique class names, isolate styles between different modules, and avoid class name conflicts. Rsbuild supports CSS Modules by default, you don't need to add additional configuration. Our convention is to use the `[name].module.css` filename to enable CSS Modules. The following style files are considered CSS Modules: * `*.module.css` * `*.module.less` * `*.module.sass` * `*.module.scss` * `*.module.styl` * `*.module.stylus` ## Usage example * Write style: ```css title="button.module.css" .red { background: red; } ``` * Using styles: ```tsx title="Button.tsx" import styles from './button.module.css'; export default () => { return <button className={styles.red}>Button</button>; }; ``` ## Named import If you prefer to use named imports in CSS Modules, you can enable it through the [output.cssModules.namedExport](/config/output/css-modules.md#cssmodulesnamedexport) config. ```ts title="rsbuild.config.ts" export default { output: { cssModules: { namedExport: true, }, }, }; ``` If enabled, you can reference class names using named imports: ```tsx title="Button.tsx" import { red } from './button.module.css'; export default () => { return <button className={red}>Button</button>; }; ``` ## CSS Modules recognition rules By default, only files ending with `*.module.css` are recognized as CSS Modules. If you want to treat other CSS files as CSS Modules as well, you can achieve this by configuring [output.cssModules.auto](/config/output/css-modules.md#cssmodulesauto). For example: ```ts export default { output: { cssModules: { auto: (resource) => { return resource.includes('.module.') || resource.includes('shared/'); }, }, }, }; ``` After this configuration, the following two files will be recognized as CSS Modules: ```ts import styles1 from './foo.module.css'; import styles2 from './shared/bar.css'; ``` ## Custom class names Customizing the class names generated by CSS Modules is also a commonly used function, you can use [output.cssModules.localIdentName](/config/output/css-modules.md#cssmoduleslocalidentname) to configure it. ```ts export default { output: { cssModules: { localIdentName: '[hash:base64:4]', }, }, }; ``` If you need to customize other configs of CSS Modules, you can set them via [output.cssModules](/config/output/css-modules.md). ## Type declaration 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. * Method 1: If the `@rsbuild/core` package is installed, you can reference the [preset types](/guide/basic/typescript.md#preset-types) provided by `@rsbuild/core`: ```ts /// <reference types="@rsbuild/core/types" /> ``` * Method 2: Manually add the required type declarations: ```ts title="src/env.d.ts" declare module '*.module.css' { const classes: { readonly [key: string]: string }; export default classes; } declare module '*.module.scss' { const classes: { readonly [key: string]: string }; export default classes; } declare module '*.module.sass' { const classes: { readonly [key: string]: string }; export default classes; } declare module '*.module.less' { const classes: { readonly [key: string]: string }; export default classes; } declare module '*.module.styl' { const classes: { readonly [key: string]: string }; export default classes; } declare module '*.module.stylus' { const classes: { readonly [key: string]: string }; export default classes; } ``` * Method 3: If you need to use **named imports** to reference class names, you can use a looser type declaration: ```ts title="src/env.d.ts" declare module '*.module.css'; declare module '*.module.scss'; declare module '*.module.sass'; declare module '*.module.less'; declare module '*.module.styl'; declare module '*.module.stylus'; ``` After adding the type declaration, if the type error still exists, you can try to restart the current IDE, or adjust the directory where `env.d.ts` is located, making sure the TypeScript can correctly identify the type definition. ## Type generation Although the above method can provide the type of CSS Modules, it cannot accurately prompt which classNames are exported by a certain CSS file. Rsbuild supports generating accurate type declarations for CSS Modules, you only need to register the [@rsbuild/plugin-typed-css-modules](https://github.com/rspack-contrib/rsbuild-plugin-typed-css-modules), and then execute the build, Rsbuild will generate type declaration files for all CSS Modules. ```ts file=rsbuild.config.ts import { pluginTypedCSSModules } from '@rsbuild/plugin-typed-css-modules'; export default { plugins: [pluginTypedCSSModules()], }; ``` ### Example For example, create two files named `src/index.ts` and `src/index.module.css`: ```tsx title="src/index.ts" import styles from './index.module.css'; console.log(styles.pageHeader); ``` ```css title="src/index.module.css" .page-header { color: black; } ``` After building, Rsbuild will generate a `src/index.module.css.d.ts` type declaration file: ```ts title="src/index.module.css.d.ts" interface CssExports { 'page-header': string; pageHeader: string; } declare const cssExports: CssExports; export default cssExports; ``` Now when you open the `src/index.ts` file, you can see that the `styles` object already has an accurate type. --- url: /guide/styling/tailwindcss.md --- # Tailwind CSS v4 [Tailwind CSS](https://tailwindcss.com/) is a CSS framework and design system based on utility class, which can quickly add common styles to components, and support flexible extension of theme styles. You can integrate Tailwind CSS in Rsbuild via PostCSS plugins. ## Choosing Tailwind CSS version This document introduces the integration of Tailwind CSS v4. Please note that Tailwind CSS v4 uses many modern CSS features, such as [Cascade Layers](https://developer.mozilla.org/zh-CN/docs/Learn_web_development/Core/Styling_basics/Cascade_layers), if your target browser does not support these features, please use Tailwind CSS v3 first, see [Using Tailwind CSS v3](/guide/styling/tailwindcss-v3.md) for more details. More information can be found in [Tailwind CSS - Compatibility](https://tailwindcss.com/docs/compatibility). ## Installing Tailwind CSS Rsbuild has built-in support for PostCSS, you can install `tailwindcss` and `@tailwindcss/postcss` packages to integrate Tailwind CSS: ## Configuring PostCSS You can register the Tailwind CSS PostCSS plugin through [postcss.config.cjs](https://npmjs.com/package/postcss-loader#config) or [tools.postcss](/config/tools/postcss.md). ```js title="postcss.config.mjs" export default { plugins: { '@tailwindcss/postcss': {}, }, }; ``` ## Importing CSS Add an `@import` to your CSS entry file that imports Tailwind CSS. ```css title="src/index.css" @import 'tailwindcss'; ``` :::tip Tailwind CSS v4 cannot be used with CSS preprocessors like Sass, Less, or Stylus. You need to place the `@tailwind` directive at the beginning of your `.css` file, see [Tailwind CSS - Compatibility](https://tailwindcss.com/docs/compatibility#sass-less-and-stylus) for more details. ::: ## Done You have now completed all the steps to integrate Tailwind CSS in Rsbuild! You can use Tailwind's utility classes in any component or HTML, such as: ```html <h1 class="text-3xl font-bold underline">Hello world!</h1> ``` For more usage details, refer to the [Tailwind CSS documentation](https://tailwindcss.com/). ## VS Code extension Tailwind CSS provides a [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code to automatically complete Tailwind CSS class names, CSS functions, and directives. You can install this plugin in VS Code to enable the autocompletion feature. --- url: /guide/styling/tailwindcss-v3.md --- # Tailwind CSS v3 [Tailwind CSS](https://v3.tailwindcss.com/) is a CSS framework and design system based on utility class, which can quickly add common styles to components, and support flexible extension of theme styles. You can integrate Tailwind CSS in Rsbuild via PostCSS plugins. ## Installing Tailwind CSS Rsbuild has built-in support for PostCSS, you can install `tailwindcss` package to integrate Tailwind CSS: ## Configuring PostCSS You can register the `tailwindcss` PostCSS plugin through [postcss.config.cjs](https://npmjs.com/package/postcss-loader#config) or [tools.postcss](/config/tools/postcss.md). ```js title="postcss.config.cjs" module.exports = { plugins: { tailwindcss: {}, }, }; ``` ## Configuring Tailwind CSS Create a `tailwind.config.js` file in the root directory of your project and add the following content: ```js title="tailwind.config.js" /** @type {import('tailwindcss').Config} */ module.exports = { content: ['./src/**/*.{html,js,ts,jsx,tsx}'], theme: { extend: {}, }, plugins: [], }; ``` :::tip The above configuration is for reference only and can be modified to suit the needs of your project. For example, non-TypeScript projects do not need to include ts and tsx files. ::: It should be noted that the `content` option should include the paths to all source files that contain Tailwind class names. For details, please refer to [tailwindcss - Content Configuration](https://v3.tailwindcss.com/docs/content-configuration). ```js title="tailwind.config.js" /** @type {import('tailwindcss').Config} */ module.exports = { content: [ './src/**/*.{html,js,ts,jsx,tsx}', '../../lib1/src/**/*.{js,ts,jsx,tsx}', ], theme: { extend: {}, }, plugins: [], }; ``` ### Other configuration methods * You can directly pass the Tailwind CSS configuration to `postcss.config.cjs`: ```js title="postcss.config.cjs" module.exports = { plugins: { tailwindcss: { content: ['./src/**/*.{html,js,ts,jsx,tsx}'], // ...other options }, }, }; ``` * You can also set the Tailwind CSS configuration through [tools.postcss](/config/tools/postcss.md): ```js title="rsbuild.config.js" import tailwindcss from 'tailwindcss'; export default { tools: { postcss: { postcssOptions: { plugins: [ tailwindcss({ content: ['./src/**/*.{html,js,ts,jsx,tsx}'], // ...other options }), ], }, }, }, }; ``` But we recommend placing the Tailwind CSS configuration in `tailwind.config.*` because other methods may cause the Tailwind CSS build performance to degrade, refer to [tailwindcss/issues/14229](https://github.com/tailwindlabs/tailwindcss/issues/14229). ## Importing CSS Add the `@tailwind` directives in your CSS entry file: ```css title="main.css" @tailwind base; @tailwind components; @tailwind utilities; ``` Depending on your needs, you can selectively import the CSS styles provided by Tailwind CSS. Please refer to the [@tailwind documentation](https://v3.tailwindcss.com/docs/functions-and-directives#tailwind) for detailed usage of the `@tailwind` directives. ## Done You have now completed all the steps to integrate Tailwind CSS in Rsbuild! You can use Tailwind's utility classes in any component or HTML, such as: ```html <h1 class="text-3xl font-bold underline">Hello world!</h1> ``` For more usage details, refer to the [Tailwind CSS documentation](https://v3.tailwindcss.com/). ## VS Code extension Tailwind CSS provides a [Tailwind CSS IntelliSense](https://github.com/tailwindlabs/tailwindcss-intellisense) plugin for VS Code to automatically complete Tailwind CSS class names, CSS functions, and directives. You can install this plugin in VS Code to enable the autocompletion feature. ## Optimize build performance When using Tailwind CSS, if the `content` field in `tailwind.config.js` is not correctly configured, this can lead to poor build performance and HMR performance. This is because Tailwind CSS internally matches files based on the glob defined in `content`. The more files it matches, the greater the performance overhead. Therefore, we recommend that you specify the paths to be scanned accurately to avoid unnecessary performance overhead. For example, only include HTML or JS files in the project source code that actually contain Tailwind class names, and avoid including irrelevant files or directories, especially the `node_modules` directory. Here is an bad example of scanning the `node_modules`: ```js title="tailwind.config.js" /** @type {import('tailwindcss').Config} */ module.exports = { content: [ './src/**/*.{html,js,ts,jsx,tsx}', // Scanning a large number of files, leading to performance degradation './node_modules/**/*.js', ], }; ``` Sometimes, you may accidentally scan the `node_modules` directory, for example, when scanning files in a monorepo: ```js title="tailwind.config.js" module.exports = { content: [ './src/**/*.{html,js,ts,jsx,tsx}', // Incorrectly includes the `packages/ui/node_modules` directory // Should be '../../packages/ui/src/**/*.{html,js,ts,jsx,tsx}' '../../packages/ui/**/*.{html,js,ts,jsx,tsx}', ], }; ``` ## Optimize CSS size To optimize the size of Tailwind CSS styles, you can try [rsbuild-plugin-tailwindcss](https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss). This plugin reads the module graph information of Rspack, automatically sets the accurate `content` configuration to generate minimal Tailwind CSS styles. ```ts title="rsbuild.config.ts" import { pluginTailwindCSS } from 'rsbuild-plugin-tailwindcss'; export default { plugins: [pluginTailwindCSS()], }; ``` > See [rsbuild-plugin-tailwindcss](https://github.com/rspack-contrib/rsbuild-plugin-tailwindcss) for more information. --- url: /guide/styling/unocss.md --- # UnoCSS [UnoCSS](https://unocss.dev/) is the instant atomic CSS engine, that is designed to be flexible and extensible. The core is un-opinionated, and all the CSS utilities are provided via presets. You can integrate UnoCSS in Rsbuild via [@unocss/webpack](https://npmjs.com/package/@unocss/webpack). ## Installing UnoCSS You need to install `@unocss/webpack` first. ## Configuring plugin Register the `UnoCSSRspackPlugin` plugin in [tools.rspack](/config/tools/rspack.md): ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { UnoCSSRspackPlugin } from '@unocss/webpack/rspack'; export default defineConfig({ tools: { rspack: { plugins: [ UnoCSSRspackPlugin({ // options }), ], }, }, }); ``` You can add UnoCSS Presets via the options of `UnoCSSRspackPlugin`, for example: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; import { UnoCSSRspackPlugin } from '@unocss/webpack/rspack'; import { presetAttributify } from '@unocss/preset-attributify'; import { presetUno } from '@unocss/preset-uno'; export default defineConfig({ plugins: [pluginReact()], tools: { rspack: { plugins: [ UnoCSSRspackPlugin({ presets: [presetUno(), presetAttributify()], }), ], }, }, }); ``` :::tip The above configuration is for reference only and can be modified to suit the needs of your project. ::: ## Importing CSS In the JavaScript entry file, import `uno.css`: ```js title="main.js" import 'uno.css'; ``` ## Done You have now completed all the steps to integrate UnoCSS in Rsbuild! You can use UnoCSS's utility classes in any component or HTML, such as: ```html <h1 class="px-2 items-center justify-between">Hello world!</h1> ``` For more usage details, refer to the [UnoCSS documentation](https://unocss.dev/). ## VS Code extension UnoCSS provides a [VS Code Extension](https://unocss.dev/integrations/vscode) plugin for VS Code to decoration and tooltip for matched utilities. You can install this plugin in VS Code to enable more intelligent features. --- url: /guide/advanced/alias.md --- # Path aliases Path aliases allow developers to define aliases for modules, making it easier to reference them in code. This can be useful when you want to use a short, easy-to-remember name for a module instead of a long, complex path. For example, if you frequently reference the `src/common/request.ts` module in your project, you can define an alias for it as `@request` and then use `import request from '@request'` in your code instead of writing the full relative path every time. This also allows you to move the module to a different location without needing to update all the import statements in your code. ```ts title="src/index.ts" import request from '@request'; // resolve to `src/common/request.ts` ``` In Rsbuild, there are two ways to set up path aliases: * Use the `paths` configuration in [tsconfig.json](https://typescriptlang.org/docs/handbook/tsconfig-json.html). * Use the [resolve.alias](/config/resolve/alias.md) configuration. ## `paths` in tsconfig.json You can configure aliases through the `paths` configuration in `tsconfig.json`, which is the recommended approach in TypeScript projects as it also resolves the TS type issues related to path aliases. For example: ```json title="tsconfig.json" { "compilerOptions": { "paths": { "@common/*": ["./src/common/*"] } } } ``` After configuring, if you reference `@common/Foo.tsx` in your code, it will be mapped to the `<project>/src/common/Foo.tsx` path. :::tip You can refer to the [TypeScript - paths](https://typescriptlang.org/tsconfig#paths) documentation for more details. ::: ## jsconfig.json In non-TypeScript projects, if you need to set path aliases through the `paths` field in [jsconfig.json](https://code.visualstudio.com/docs/languages/jsconfig), you can use the [source.tsconfigPath](/config/source/tsconfig-path.md) option to set it. After adding the following configuration, Rsbuild will recognize the `paths` field in `jsconfig.json`. ```js title="rsbuild.config.mjs" export default { source: { tsconfigPath: './jsconfig.json', }, }; ``` ## `resolve.alias` Configuration Rsbuild provides the [resolve.alias](/config/resolve/alias.md) configuration option, which corresponds to the webpack/Rspack native [resolve.alias](https://rspack.dev/config/resolve#resolvealias) configuration. You can configure this option using an object or a function. ### Use cases Since the `paths` configuration in `tsconfig.json` is written in a static JSON file, it lacks dynamism. The `resolve.alias` configuration can address this limitation by allowing you to dynamically set the `resolve.alias` using JavaScript code, such as based on environment variables. ### Object usage You can configure `resolve.alias` using an object, where the relative paths will be automatically resolved to absolute paths. For example: ```js export default { resolve: { alias: { '@common': './src/common', }, }, }; ``` After configuring, if you reference `@common/Foo.tsx` in your code, it will be mapped to the `<project>/src/common/Foo.tsx` path. ### Function usage You can also configure `resolve.alias` as a function, which receives the built-in `alias` object and allows you to modify it. For example: ```js export default { resolve: { alias: (alias) => { alias['@common'] = './src/common'; return alias; }, }, }; ``` ### Priority The `paths` configuration in `tsconfig.json` takes precedence over the `resolve.alias` configuration. When a path matches the rules defined in both `paths` and `resolve.alias`, the value defined in `paths` will be used. You can adjust the priority of these two options using [resolve.aliasStrategy](/config/resolve/alias-strategy.md). --- url: /guide/advanced/env-vars.md --- # Environment variables Rsbuild supports injecting env variables or expressions into the code during build, which is helpful for distinguishing the running environment or replacing constants. This chapter introduces how to use env variables in Rsbuild. ## Default variables Rsbuild by default injects the some env variables into the code using [source.define](#using-define). These will be replaced with specified values during the build: `import.meta.env` contains these env variables: * [import.meta.env.MODE](#importmetaenvmode) * [import.meta.env.DEV](#importmetaenvdev) * [import.meta.env.PROD](#importmetaenvprod) * [import.meta.env.BASE\_URL](#importmetaenvbase_url) * [import.meta.env.ASSET\_PREFIX](#importmetaenvasset_prefix) `process.env` contains these env variables: * [process.env.BASE\_URL](#processenvbase_url) * [process.env.ASSET\_PREFIX](#processenvasset_prefix) * [process.env.NODE\_ENV](#processenvnode_env) ### import.meta.env.MODE You can use `import.meta.env.MODE` in the client code to read the value of the [mode](/config/mode.md) configuration. ```ts if (import.meta.env.MODE === 'development') { console.log('this is development mode'); } ``` In development mode, the above code will be compiled to: ```js if (true) { console.log('this is development mode'); } ``` In production mode, the above code will be compiled to: ```js if (false) { console.log('this is development mode'); } ``` During code minification, `if (false) { ... }` will be recognized as invalid code and removed automatically. ### import.meta.env.DEV If [mode](/config/mode.md) is `'development'`, the value is `true`; otherwise, it is `false`. ```ts if (import.meta.env.DEV) { console.log('this is development mode'); } ``` ### import.meta.env.PROD If [mode](/config/mode.md) is `'production'`, the value is `true`; otherwise, it is `false`. ```ts if (import.meta.env.PROD) { console.log('this is production mode'); } ``` ### import.meta.env.BASE\_URL You can use `import.meta.env.BASE_URL` in the client code to access the server's [base path](/guide/basic/server.md#base-path), which is determined by the [server.base](/config/server/base.md) configuration, which is helpful for referencing [public folder](/guide/basic/static-assets.md#public-folder) assets in the code. For example, we set the base path of the server to `/foo` through [server.base](/config/server/base.md) configuration: ```ts export default { server: { base: '/foo', }, }; ``` Then, the access URL to the `favicon.ico` file in the public directory is `http://localhost:3000/foo/favicon.ico`. You can use `import.meta.env.BASE_URL` to concatenate the URL in JS files: ```js title="index.js" const image = new Image(); // Equivalent to "/foo/favicon.ico" image.src = `${import.meta.env.BASE_URL}/favicon.ico`; ``` ### import.meta.env.ASSET\_PREFIX You can use `import.meta.env.ASSET_PREFIX` in the client code to access the URL prefix of static assets. * In development, it is equivalent to the value set by [dev.assetPrefix](/config/dev/asset-prefix.md). * In production, it is equivalent to the value set by [output.assetPrefix](/config/output/asset-prefix.md). * Rsbuild will automatically remove the trailing slash from `assetPrefix` to make string concatenation easier. For example, we copy the `static/icon.png` image to the `dist` directory through [output.copy](/config/output/copy.md) configuration: ```ts export default { dev: { assetPrefix: '/', }, output: { copy: [{ from: './static', to: 'static' }], assetPrefix: 'https://example.com', }, }; ``` Then we can access the image URL in the client code: ```jsx const Image = <img src={`${import.meta.env.ASSET_PREFIX}/static/icon.png`} />; ``` In development mode, the above code will be compiled to: ```jsx const Image = <img src={`/static/icon.png`} />; ``` In production mode, the above code will be compiled to: ```jsx const Image = <img src={`https://example.com/static/icon.png`} />; ``` ### process.env.BASE\_URL Rsbuild also allows using `process.env.BASE_URL`, which is an alias of [import.meta.env.BASE\_URL](#importmetaenvbase_url). For example, in the HTML template, you can use `process.env.BASE_URL` to concatenate the URL: ```html title="index.html" <!-- Equivalent to "/foo/favicon.ico" --> <link rel="icon" href="<%= process.env.BASE_URL %>/favicon.ico" /> ``` ### process.env.ASSET\_PREFIX Rsbuild also allows using `process.env.ASSET_PREFIX`, which is an alias of [import.meta.env.ASSET\_PREFIX](#importmetaenvasset_prefix). For example, in the HTML template, you can use `process.env.ASSET_PREFIX` to concatenate the URL: ```html title="index.html" <!-- Equivalent to "https://example.com/static/icon.png" --> <link rel="icon" href="<%= process.env.ASSET_PREFIX %>/static/icon.png" /> ``` ### process.env.NODE\_ENV By default, Rsbuild will automatically set the `process.env.NODE_ENV` environment variable to `'development'` in development mode and `'production'` in production mode. You can use `process.env.NODE_ENV` directly in Node.js and in the client code. ```ts if (process.env.NODE_ENV === 'development') { console.log('this is a development log'); } ``` In development mode, the above code will be compiled to: ```js if (true) { console.log('this is a development log'); } ``` In production mode, the above code will be compiled to: ```js if (false) { console.log('this is a development log'); } ``` During code minification, `if (false) { ... }` will be recognized as invalid code and removed automatically. #### Custom NODE\_ENV `process.env.NODE_ENV` is injected by Rspack by default. If you need to disable the injection or custom the value, use the [optimization.nodeEnv](https://rspack.dev/config/optimization#optimizationnodeenv) option of Rspack: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { optimization: { nodeEnv: false } }, }, }; ``` ## `.env` File When a `.env` file exists in the project root directory, Rsbuild CLI will automatically use [dotenv](https://npmjs.com/package/dotenv) to load these env variables and add them to the current Node.js process. The [Public Variables](#public-variables) will be exposed in the client code. You can access these env variables through `import.meta.env.[name]` or `process.env.[name]`. ### File types Rsbuild supports reading the following types of env files: | File Name | Description | | ------------------------ | -------------------------------------------------------------------------- | | `.env` | Loaded by default in all scenarios. | | `.env.local` | Local usage of the `.env` file, should be added to .gitignore. | | `.env.development` | Read when `process.env.NODE_ENV` is `'development'`. | | `.env.production` | Read when `process.env.NODE_ENV` is `'production'`. | | `.env.development.local` | Local usage of the `.env.development` file, should be added to .gitignore. | | `.env.production.local` | Local usage of the `.env.production` file, should be added to .gitignore. | If several of the above files exist at the same time, they will all be loaded, with the files listed at the bottom of the table having higher priority. ### Env mode Rsbuild also supports reading `.env.[mode]` and `.env.[mode].local` files. You can specify the env mode using the `--env-mode <mode>` flag. For example, set the env mode as `test`: ```bash npx rsbuild dev --env-mode test ``` Rsbuild will read these files in the following order and merge their contents. If the same environment variable is defined in multiple files, values from files loaded later will override those from files loaded earlier: * .env * .env.local * .env.test * .env.test.local :::tip The `--env-mode` option takes precedence over `process.env.NODE_ENV`. It is recommended to use `--env-mode` to set the env mode, and not to modify `process.env.NODE_ENV`. ::: ### Env directory By default, the `.env` file is located in the root directory of the project. You can specify the env directory by using the `--env-dir <dir>` option in the CLI. For example, to specify the env directory as `config`: ```bash npx rsbuild dev --env-dir config ``` In this case, Rsbuild will read the `./config/.env` and other env files. ### Example For example, create a `.env` file and add the following contents: ```shell title=".env" FOO=hello BAR=1 ``` Then in the `rsbuild.config.ts` file, you can access the above env variables using `import.meta.env.[name]` or `process.env.[name]`: ```ts title="rsbuild.config.ts" console.log(import.meta.env.FOO); // 'hello' console.log(import.meta.env.BAR); // '1' console.log(process.env.FOO); // 'hello' console.log(process.env.BAR); // '1' ``` Now, create a `.env.local` file and add the following contents: ```shell title=".env.local" BAR=2 ``` The value of `BAR` is overwritten to `'2'`: ```ts title="rsbuild.config.ts" console.log(import.meta.env.BAR); // '2' console.log(process.env.BAR); // '2' ``` ### Manually load env If you are not using the Rsbuild CLI and are using the Rsbuild [JavaScript API](/api/start/index.md) instead, you will need to manually call the [loadEnv](/api/javascript-api/core.md#loadenv) method to read env variables and inject them into the code via the [source.define](/config/source/define.md) config. ```ts import { loadEnv, mergeRsbuildConfig } from '@rsbuild/core'; // By default, `publicVars` are variables prefixed with `PUBLIC_` const { parsed, publicVars } = loadEnv(); const mergedConfig = mergeRsbuildConfig( { source: { define: publicVars, }, }, userConfig, ); ``` ### Disable loading You can disable loading `.env` files by using the `--no-env` flag in the CLI. ```bash npx rsbuild dev --no-env ``` When using the `--no-env` flag, Rsbuild CLI will not read any `.env` files, and you can manage environment variables using other tools like [dotenvx](https://dotenvx.com/). ## Public variables All env variables starting with `PUBLIC_` can be accessed in client code. For example, if the following variables are defined: ```bash title=".env" PUBLIC_NAME=jack PASSWORD=123 ``` In the client code, you can access these env variables through `import.meta.env.PUBLIC_*` or `process.env.PUBLIC_*`. Rsbuild will match the identifiers and replace them with the corresponding values. ```ts title="src/index.ts" console.log(import.meta.env.PUBLIC_NAME); // -> 'jack' console.log(import.meta.env.PASSWORD); // -> undefined console.log(process.env.PUBLIC_NAME); // -> 'jack' console.log(process.env.PASSWORD); // -> undefined ``` :::tip * The content of public variables will be exposed to your client code, so please avoid including sensitive information in public variables. * Public variables are replaced through [source.define](/config/source/define.md). Please read ["Using define"](#using-define) to understand the principles and notes of define. ::: ### Replacement scope Public variables will replace identifiers in the client code, with the replacement scope including: * JavaScript files, and files that can be converted into JavaScript code, such as `.js`, `.ts`, `.tsx`, etc. * HTML template files, for example: ```xml title="template.html" <div><%= process.env.PUBLIC_NAME %></div> ``` Note that public variables will not replace identifiers in the following files: * CSS files, such as `.css`, `.scss`, `.less`, etc. ### Custom prefix Rsbuild provides the [loadEnv](/api/javascript-api/core.md#loadenv) method, which can inject env variables with any prefix into client code. For example, when migrating a Create React App project to Rsbuild, you can read env variables starting with `REACT_APP_` and inject them through the [source.define](/config/source/define.md) config as follows: ```ts title="rsbuild.config.ts" import { defineConfig, loadEnv } from '@rsbuild/core'; const { publicVars } = loadEnv({ prefixes: ['REACT_APP_'] }); export default defineConfig({ source: { define: publicVars, }, }); ``` ## Using define By using [source.define](/config/source/define.md), you can replace global identifiers with some expressions or values in compile time. `define` is similar to the macro definition capabilities provided by other languages. It is often used to inject env variables and other information to the code during build time. ### Replace identifiers The most basic use case for `define` is to replace global identifiers in compile time. The value of the environment variable `NODE_ENV` will change the behavior of many vendor packages. Usually, we need to set it to `production`. ```js export default { source: { define: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), }, }, }; ``` Note that the value provided here must be a JSON string, e.g. `process.env.NODE_ENV` with a value of `"production"` should be passed in as `"\"production\""` to be processed correctly. Similarly `{ foo: "bar" }` should be converted to `"{\"foo\":\"bar\"}"`, which if passed directly into the original object would mean replacing the identifier `process.env.NODE_ENV.foo` with the identifier `bar`. For more about `source.define`, just refer to [API References](/config/source/define.md). :::tip The environment variable `NODE_ENV` shown in the example above is already injected by the Rsbuild, and you usually do not need to configure it manually. ::: ### Identifiers matching Note that `source.define` can only match complete global identifiers. You can think of it as a text replacement process. If the identifier in the code does not exactly match the key defined in `define`, Rsbuild will not be able to replace it. ```js // Good console.log(process.env.NODE_ENV); // 'production' // Bad console.log(process.env['NODE_ENV']); // process is not defined! // Bad console.log(process.env?.NODE_ENV); // process is not defined! // Bad const { NODE_ENV } = process.env; console.log(NODE_ENV); // process is not defined! // Bad const env = process.env; console.log(env.NODE_ENV); // process is not defined! ``` ### process.env Replacement When using `source.define`, please avoid replacing the entire `process.env` object, e.g. the following usage is not recommended: ```js export default { source: { define: { 'process.env': JSON.stringify(process.env), }, }, }; ``` If the above usage is adopted, the following problems will be caused: 1. Some unused env variables are additionally injected, causing the env variables of the dev server to be leaked into the front-end code. 2. As each `process.env` code will be replaced by a complete environment variable object, the bundle size of the front-end code will increase and the performance will decrease. Therefore, please inject the env variables on `process.env` according to actual needs and avoid replacing them in its entirety. ## Type declarations When you access an environment variable in a TypeScript file, TypeScript may prompt that the variable lacks a type definition, and you need to add the corresponding type declaration. For example, if you reference a `PUBLIC_FOO` variable, the following prompt will appear in the TypeScript file: ``` TS2304: Cannot find name 'PUBLIC_FOO'. ``` To fix this, you can create a `src/env.d.ts` file in your project and add the following content: ```ts title="src/env.d.ts" declare const PUBLIC_FOO: string; ``` ### import.meta.env You can extend the type of `import.meta.env` like this: ```ts title="src/env.d.ts" interface ImportMetaEnv { // import.meta.env.PUBLIC_FOO readonly PUBLIC_FOO: string; } interface ImportMeta { readonly env: ImportMetaEnv; } ``` ### process.env If the type for `process.env` is missing, please install the dependency [@types/node](https://npmjs.com/package/@types/node): Then extend the type of `process.env`: ```ts title="src/env.d.ts" declare namespace NodeJS { interface ProcessEnv { // process.env.PUBLIC_FOO PUBLIC_FOO: string; } } ``` ## Tree shaking `define` can also be used to mark dead code to assist the Rspack with tree shaking optimization. Build artifacts for different languages is achieved by replacing `import.meta.env.LANGUAGE` with a specific value, for example. ```ts title="rsbuild.config.ts" export default { source: { define: { 'import.meta.env.LANGUAGE': JSON.stringify(import.meta.env.LANGUAGE), }, }, }; ``` For an internationalized code: ```js const App = () => { if (import.meta.env.LANGUAGE === 'en') { return <EntryFoo />; } else if (import.meta.env.LANGUAGE === 'zh') { return <EntryBar />; } }; ``` Specifying the environment variable `LANGUAGE=zh` and then running build will eliminate the dead code. ```js const App = () => { if (false) { } else if (true) { return <EntryBar />; } }; ``` Unused components will not be bundled, and their dependencies will be removed accordingly, resulting in smaller build outputs. --- url: /guide/advanced/hmr.md --- # Hot module replacement Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways: * Retain application state which is lost during a full reload. * Save valuable development time by only updating what's changed. * Instantly update the browser when modifications are made to CSS / JS in the source code, which is almost comparable to changing styles directly in the browser's dev tools. ## HMR toggle Rsbuild has built-in support for HMR, which is enabled by default in development mode. If you do not need to use HMR, set [dev.hmr](/config/dev/hmr.md) to `false`. This will disable HMR and react-refresh will, and Rsbuild will automatically fallback to [dev.liveReload](/config/dev/live-reload.md). ```ts title="rsbuild.config.ts" export default { dev: { hmr: false, }, }; ``` To disable both HMR and liveReload, set both [dev.hmr](/config/dev/hmr.md) and [dev.liveReload](/config/dev/live-reload.md) to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when files change. ```ts title="rsbuild.config.ts" export default { dev: { hmr: false, liveReload: false, }, }; ``` ## Specify HMR URL By default, Rsbuild uses the host and port number of the current page to splice the WebSocket URL for HMR. When the HMR connection fails, you can specify the WebSocket URL by customizing [dev.client](/config/dev/client.md) config. ```ts title="rsbuild.config.ts" export default { dev: { client: { host: 'localhost', protocol: 'ws', }, }, }; ``` ## File watching By default, Rsbuild does not watch files in the `.git/` and `node_modules/` directories. When files in these directories changed, Rsbuild will not trigger a rebuild. This helps to reduce memory usage and improve build performance. If you want to watch these directories, you can manually configure Rspack's [watchOptions.ignored](https://rspack.dev/config/watch#watchoptionsignored) to override the default behavior. For example, to watch the `node_modules/` directory and ignore the `.git/` directory, you can configure it as follows: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { watchOptions: { ignored: /\.git/, }, }, }, }; ``` ## FAQ Please refer to [HMR FAQ](/guide/faq/hmr.md). --- url: /guide/advanced/browserslist.md --- # Browserslist Rsbuild supports using [Browserslist](https://browsersl.ist/) to specify which browsers should be supported in your web application. ## What is browserslist Since different browsers support ECMAScript and CSS differently, developers need to set the correct browser range for web applications. [Browserslist](https://browsersl.ist/) can specify which browsers your web application can run in, it provides a configuration for specifying browsers range. Browserslist has become a standard in the industry, it is used by libraries such as SWC, Lightning CSS, Babel, ESLint, PostCSS and webpack. When you specify a browser range through Browserslist, Rsbuild will compile JavaScript and CSS code to the specified syntax. ## Polyfill injection If you enabled [output.polyfill](/config/output/polyfill.md), Rsbuild will also inject the corresponding polyfill code based on browserslist. **When you only need to support more modern browsers, the build process will introduce less compatibility code and polyfills, which will reduce the bundle size.** ```ts title="rsbuild.config.ts" export default { output: { polyfill: 'usage', }, }; ``` For example, when you need to be compatible with IE11 browser, Rsbuild will compile the code to ES5 and inject the polyfill required by IE11 through [core-js](https://github.com/zloirock/core-js). > Please refer to [Browser compatibility](/guide/advanced/browser-compatibility.md) for more information. ## Default values Rsbuild will set different default values of Browserslist according to [output.target](/config/output/target.md), you can also explicitly set Browserslist in your project, which will make the compatible scope of the project more clear. ### Web target If `output.target` is `web`, Rsbuild will use the following Browserslist by default: ```yaml title=".browserslistrc" chrome >= 87 edge >= 88 firefox >= 78 safari >= 14 ``` With this browser range, the build output will be compatible with browsers that support [native ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules). ### Node target If `output.target` is `node`, Rsbuild will default to outputting bundles that run on Node.js 16.0 or later. ```yaml title=".browserslistrc" node >= 16 ``` ### Web Workers target If `output.target` is `web-worker`, Rsbuild will default to using the following Browserslist (consistent with the `web` target): ```yaml title=".browserslistrc" chrome >= 87 edge >= 88 firefox >= 78 safari >= 14 ``` ## Set browserslist You can set the Browserslist value in the `package.json` or `.browserslistrc` file in the root directory of the current project. ### Example Set via `browserslist` in `package.json`: ```json title="package.json" { "browserslist": [ "iOS >= 9", "Android >= 4.4", "last 2 versions", "> 0.2%", "not dead" ] } ``` Set via a separate `.browserslistrc` file: ```yaml title=".browserslistrc" iOS >= 9 Android >= 4.4 last 2 versions > 0.2% not dead ``` ### Effective scope By default, the `.browserslistrc` file only takes effect for browser-side bundles, including the `web` and `web-worker` target types. When you are building multiple targets at the same time, for example if the targets contains both `web` and `node`, only the `web` bundles will be affected by the `.browserslistrc` file. If you want to make changes to the `node` bundles, you can use the `output.overrideBrowserslist` configuration below. ### Set by env You can set different browserslist based on `NODE_ENV` to specify different browser ranges for development and production. For example, set values based on keys in the `package.json`: ```json title="package.json" { "browserslist": { "production": [ "chrome >= 87", "edge >= 88", "firefox >= 78", "safari >= 14" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } } ``` Or in `.browserslistrc`: ```yaml title=".browserslistrc" [production] chrome >= 87 edge >= 88 firefox >= 78 safari >= 14 [development] last 1 chrome version last 1 firefox version last 1 safari version ``` ### Override via config In addition to the above standard usage, Rsbuild also provides [output.overrideBrowserslist](/config/output/override-browserslist.md) config, which can also set the value of Browserslist. `overrideBrowserslist` can be set to an array, which is written in the same way as the `browserslistrc` configuration, but has a higher priority than `browserslistrc`. ```ts title="rsbuild.config.ts" export default { output: { overrideBrowserslist: [ 'iOS >= 9', 'Android >= 4.4', 'last 2 versions', '> 0.2%', 'not dead', ], }, }; ``` In most cases, it is recommended to use the `.browserslistrc` file rather than the `overrideBrowserslist` config. Because the `.browserslistrc` file is the standard config file, it is more general and can be recognized by other libraries in the community. ## Commonly used browserslist The following are some commonly used Browserslist, you can choose according to your project type. ### Desktop web application For desktop web applications, if you need to be compatible with IE 11 browsers, you can set Browserslist to: ```yaml title=".browserslistrc" > 0.5% not dead Internet Explorer 11 ``` The above Browserslist will compile the code to the ES5. For the specific browser list, please check [browserslist.dev](https://browserslist.dev/?q=PiAwLjUlLCBub3QgZGVhZCwgSUUgMTE%3D). If you don't need to be compatible with IE 11 browsers, you can adjust Browserslist to get a more performant output, such as: * Set to browsers that supports native ES Modules (recommended): ```yaml title=".browserslistrc" chrome >= 87 edge >= 88 firefox >= 78 safari >= 14 ``` * Set to browsers that support ES6: ```yaml title=".browserslistrc" chrome >= 51 edge >= 15 firefox >= 54 safari >= 10 ios_saf >= 10 ``` ### Mobile web application For mobile web applications, mainly compatible with `iOS` and `Android` systems, usually we set Browserslist as: ```yaml title=".browserslistrc" iOS >= 9 Android >= 4.4 last 2 versions > 0.2% not dead ``` The above Browserslist will compile the code to the ES5, which is compatible with most mobile scenarios on the market. For the detailed browsers list, please check [browserslist.dev](https://browserslist.dev/?q=aU9TID49IDksIEFuZHJvaWQgPj0gNC40LCBsYXN0IDIgdmVyc2lvbnMsID4gMC4yJSwgbm90IGRlYWQ%3D). ![](https://assets.rspack.dev/rsbuild/assets/browserslist-dev-example.png) You can also choose to use the ES6 or higher, which will make the performance of the page better. The corresponding Browserslist is as follows: ```yaml title=".browserslistrc" iOS >= 10 Chrome >= 51 > 0.5% not dead not op_mini all ``` ## Query browser support When developing, we need to know the browser support of certain features or APIs. At this time, we can check on the [caniuse](https://caniuse.com/) website. For example, we need to know the browser support of `Promise`, just enter `Promise` in [caniuse](https://caniuse.com/), and you can see the following results: ![](https://assets.rspack.dev/rsbuild/assets/caniuse-promise-example.png) As can be seen from the above table, `Promise` is natively supported in Chrome 33 and iOS 8, but not in IE 11. --- url: /guide/advanced/browser-compatibility.md --- # Browser compatibility Rsbuild supports [modern browsers](/guide/advanced/browserslist.md#default-browserslist) by default, and provides syntax and API downgrade capabilities to ensure compatibility with legacy browsers that support ES5 (such as IE11). This chapter introduces how to use the capabilities provided by Rsbuild to deal with browser compatibility issues. ## Set browserslist Before dealing with compatibility issues, you first need to clarify which browsers your project needs to support, and add the corresponding browserslist config. * If you haven't set browserslist yet, please read the [Browserslist](/guide/advanced/browserslist.md) chapter first. * If you have set a browserslist, Rsbuild will automatically compile according to that scope, downgrade JavaScript syntax and CSS syntax, and inject the required polyfill. In most cases, you can safely use modern ECMAScript features without worrying about compatibility issues. After setting the browserslist, if you still encountered some compatibility issues, please continue reading below contents to find some solutions. :::tip What is polyfill A polyfill is a piece of code that provides the functionality of a newer feature to older browsers that do not support that feature natively. It is used to fill in the gaps in older browsers' implementations of web standards, allowing developers to use newer features safely without having to worry about whether or not they will work in older browsers. For example, if a browser does not support the Array.map() method, a polyfill can be used to provide that functionality, allowing code that uses `Array.prototype.flat()` to work in that browser. Polyfills are commonly used to ensure that web applications can work on a wide range of browsers, including older ones. ::: ## Background knowledge Before dealing with compatibility issues, it is recommended that you understand the following background knowledge to better handle related issues. ### Syntax downgrade and API downgrade When you use higher-version syntax and API in your project, in order to make the compiled code run stably in lower-version browsers, we need to downgrade two parts: syntax downgrade and API downgrade. **Rsbuild downgrades syntax through syntax transpilation, and downgrades API through inject polyfill.** > Grammar and API are not strongly bound. When browser manufacturers implement the engine, they will support some syntax or implement some APIs in advance according to the specification or their own needs. Therefore, browsers from different manufacturers in the same period are not necessarily compatible with syntax and API. So in general practice, syntax and API are handled in two parts. ### Syntax transpilation **Syntax is a series of rules for how a programming language organizes code**, and code that does not follow these rules cannot be correctly recognized by the programming language's engine and therefore cannot be run. In JavaScript, the following examples are syntax rules: * In `const foo = 1`, `const` means to declare an immutable constant. * In `foo?.bar?.baz`, `?.` indicates optional chaining of access properties. * In `async function () {}`, `async` means to declare an asynchronous function. Because the parsers of different browsers can support different syntax, especially the old version of the browser engine can support less grammar, so when some syntax are run in the lower version of the browser engine, an error will be reported at the stage of parsing the AST . For example, the following code will report an error in IE browser or a lower version of Node.js: ```js const foo = {}; foo?.bar(); ``` When we run this code in a low version of Node.js, the following error message will appear: ```bash SyntaxError: Unexpected token. at Object.exports.runInThisContext (vm.js:73:16) at Object.<anonymous> ([eval]-wrapper:6:22) at Module._compile (module.js:460:26) at evalScript (node.js:431:25) at startup (node.js:90:7) at node.js:814:3 ``` It is obvious from the error message that this is a syntax error. This means that this syntax is not supported in lower versions of the engine. **Syntax can not be supported by polyfill or shim**. If you want to run some syntax that it does not originally support in a low-version browser, you need to transpile the code into a syntax that the low-version engine can support. Transpile the above code into the following code to run in lower version engines: ```js var foo = {}; foo === null || foo === void 0 ? void 0 : foo.bar(); ``` After transpilation, the syntax of the code has changed, and some syntax that the engine of the lower version cannot understand has been replaced with the syntax it can understand, **but the meaning of the code itself has not changed**. If the engine encounters an unrecognized syntax when converting to AST, it will report a syntax error and abort the code execution process. In this case, if your project does not use capabilities such as SSR or SSG, the page will be blank, making the page unavailable. If the code is successfully converted to AST, the engine will convert the AST into executable code and execute it normally inside the engine. ### API polyfill JavaScript is an interpreted scripting language, unlike compiled languages like Rust. Rust will check the calls in the code during the compilation phase, and JavaScript does not know whether the function called by this line of code exists before it actually runs to a certain line of code, so some errors will only appear at runtime. For example: ```js var str = 'Hello world!'; console.log(str.notExistedMethod()); ``` The above code has correct syntax and can be converted to AST correctly in the first stage of the engine runtime, but when it is actually running, because the method `notExistedMethod` does not exist on `String.prototype`, an error will be reported: ```bash Uncaught TypeError: str.notExistedMethod is not a function at <anonymous>:2:17 ``` With the iteration of ECMAScript, some new methods will be added to be built-in objects. For example, `String.prototype.replaceAll` was introduced in ES2021, then the `replaceAll` method does not exist in the built-in object `String.prototype` of most browser engines before 2021, so the following code works in the latest Chrome, but not in earlier versions: ```js 'abc'.replaceAll('abc', 'xyz'); ``` In order to solve the problem that `String.prototype` lacks `replaceAll` in older browsers, we can extend the `String.prototype` object in older browsers and add the `replaceAll` method to it, for example: ```js // The implementation of this polyfill does not necessarily conform to the standard, it is only used as an example. if (!String.prototype.replaceAll) { String.prototype.replaceAll = function (str, newStr) { // If a regex pattern if ( Object.prototype.toString.call(str).toLowerCase() === '[object regexp]' ) { return this.replace(str, newStr); } // If a string return this.replace(new RegExp(str, 'g'), newStr); }; } ``` > This technique of providing implementations for legacy environments to align new APIs is called polyfill. ## Downgrade method In Rsbuild, we divide code into three categories: * The first category is the source code in the current project. * The second category is third-party dependencies installed through npm. * The third category is the code out of the current project, such as the code in other directories in the monorepo. By default, Rsbuild will only compile and downgrade the first category, other categories will not be downgraded by default. There are several considerations for this approach: * Downgrading all third-party party dependencies will **significantly reduce build performance**. * Most third-party dependencies have been downgraded before release, and the second downgrade may introduce new problems. * The code out of the current project may have been compiled, or the compilation config may be different. ### Downgrade the current project code The code of the current project will be downgraded by default, so you don't need to add additional config, just make sure that the browserslist config is set correctly. ### Downgrade third-party dependencies When you find that a third-party dependencies causes compatibility issues, you can add this dependency to Rsbuild's [source.include](/config/source/include.md) config, Make Rsbuild do extra compilation for this dependency. Taking the npm package `query-string` as an example, you can add the following config: ```ts import path from 'node:path'; export default { source: { include: [/node_modules[\\/]query-string[\\/]/], }, }; ``` Please refer to [source.include](/config/source/include.md) document for detailed usage guide. ### Downgrade the code out of the current project When you import the code out of the current project, if the code has not been compiled, then you also need to configure [source.include](/config/source/include.md) to it to compile. For example, if you need to reference a module under the `packages` directory in the monorepo, you can add the following config: ```ts import path from 'node:path'; export default { source: { include: [ // method one: // Compile all files in the package directory of Monorepo path.resolve(__dirname, '../../packages'), // Method Two: // Compile the source code of a package in the Monorepo's package directory // The matching range of this writing method is more precise, and has less impact on the overall compilation performance path.resolve(__dirname, '../../packages/abc/src'), ], }, }; ``` ## Polyfill mode Rsbuild compiles JavaScript code using SWC and supports injecting polyfills such as [core-js](https://github.com/zloirock/core-js) and [@swc/helpers](https://npmjs.com/package/@swc/helpers). In different usage scenarios, you may need different polyfill solutions. Rsbuild provides [output.polyfill](/config/output/polyfill.md) config to switch between different polyfill modes. ### Default behavior Rsbuild does not inject any polyfills by default: ```ts export default { output: { polyfill: 'off', }, }; ``` ### Usage mode When you enable the usage mode, Rsbuild will analyze the source code in the project and determine which polyfills need to be injected. For example, the code uses the `Map` object: ```js var b = new Map(); ``` After compilation, only the polyfills for `Map` will be injected into this file: ```js import 'core-js/modules/es.map'; var b = new Map(); ``` The advantage of this method is that the size of the injected polyfill is smaller, which is suitable for projects with higher requirements on bundle size. The disadvantage is that polyfill may not be fully injected, because third-party dependencies will not be compiled and downgraded by default, so the polyfill required by third-party dependencies will not be analyzed. If you need to analyze a third-party dependency, you also need to add it to [source.include](/config/source/include.md) config. The config of usage mode is: ```ts export default { output: { polyfill: 'usage', }, }; ``` ### Entry mode When using the entry mode, Rsbuild will analyze which `core-js` methods need to be injected according to the browserslist set by the current project, and inject them to the entry file of each page. The polyfill injected in this way is more comprehensive, and there is no need to worry about the project source code and third-party dependencies polyfill issues. However, because some unused polyfill codes are included, the bundle size may increase. The config of entry mode is: ```ts export default { output: { polyfill: 'entry', }, }; ``` ### UA polyfill Cloudflare provides a [polyfill service](https://cdnjs.cloudflare.com/polyfill/) that can automatically generate polyfill bundle based on the user's browser User-Agent. You can use the [html.tags](/config/html/tags.md) config of Rsbuild to inject scripts. For example, injecting a `<script>` tag at the beginning of the `<head>` tag: ```ts export default { html: { tags: [ { tag: 'script', attrs: { defer: true, src: 'https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=default', }, append: false, }, ], }, }; ``` --- url: /guide/advanced/module-federation.md --- # Module Federation Module Federation is an architectural pattern for JavaScript application decomposition (similar to microservices on the server-side), allowing you to share code and resources between multiple JavaScript applications (or micro-frontends). The Rspack team works closely with the Module Federation development team and provides first-class support for Module Federation. ## Use cases Module Federation has several typical use cases, including: * Allowing independent applications (called "micro-frontends" in micro-frontend architecture) to share modules without recompiling the entire application. * Different teams working on different parts of the same application without needing to recompile the entire application. * Dynamic code loading and sharing between applications at runtime. Module Federation can help you: * Reduce code duplication * Improve code maintainability * Reduce the overall size of applications * Improve application performance ## How to use Module Federation (MF) currently has multiple major versions, and you can choose one based on your needs. Here are the characteristics of several versions: | Version | Description | Features | Use Cases | | ------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | MF v2.0 | Enhanced version of Module Federation, implemented based on Module Federation v1.5 | - Provides additional out-of-the-box features such as dynamic TS type hints, Chrome DevTools, preloading, etc.- More suitable for micro-frontend architecture supporting large-scale web applications - Includes all features of Module Federation 1.5 | Projects that need to use advanced capabilities of MF 2.0 | | MF v1.5 | Version built into Rspack | - Supports module export, module loading, dependency sharing capabilities of Module Federation v1.0- Added runtime plugin functionality, allowing users to extend the behavior and functionality of module federation | Projects that don't need to use the extra capabilities of MF 2.0 | ### Module Federation v2.0 [Module Federation 2.0](https://module-federation.io/blog/announcement.html) provides some additional out-of-the-box features based on Module Federation, such as dynamic TS type hints, Chrome devtools, Runtime plugins, preloading, making Module Federation more suitable for micro-frontend architecture supporting large-scale web applications. Module Federation v2.0 is implemented based on v1.5. You need to install the additional [@module-federation/rsbuild-plugin](https://npmjs.com/package/@module-federation/rsbuild-plugin) plugin to use Module Federation v2.0. ```ts title="rsbuild.config.ts" import { pluginModuleFederation } from '@module-federation/rsbuild-plugin'; export default defineConfig({ plugins: { pluginModuleFederation({ name: 'remote', // other options }), }, }); ``` Please refer to the [Module Federation v2.0 official documentation](https://module-federation.io/) for detailed usage. ### Module Federation v1.5 This is the version built into Rspack. In addition to supporting Module Federation v1.0's capabilities such as module export, module loading, and dependency sharing, it also adds runtime plugin functionality, allowing users to extend the behavior and functionality of module federation. You can use it through Rsbuild's [moduleFederation.options](/config/module-federation/options.md), no need to install any plugins. ```ts title="rsbuild.config.ts" export default defineConfig({ moduleFederation: { options: { name: 'remote', // other options }, }, }); ``` ## Example repositories Rsbuild has provided some example projects of Module Federation, you can refer to: * [Module Federation v2.0 Example](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/module-federation-enhanced) * [Module Federation v1.5 Example](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/module-federation) --- url: /guide/advanced/environments.md --- # Multi-environment builds Rsbuild supports building outputs for multiple environments at the same time. You can use [environments](/config/environments.md) to build multiple environments in parallel and set a different Rsbuild config for each environment. ## What is environment The `environment` refers to the runtime environment for build output. Common environments include browsers, Node.js, and Workers. Rsbuild allows you to define any environment names and set build options for each environment individually. A typical scenario is server-side rendering (SSR). You can define two environments, `web` and `node`, where the build targets ([output.target](/config/output/target.md)) are `web` and `node`. These are used for client-side rendering (CSR) and server-side rendering (SSR) scenarios. You can also define different environments for the same build target, for example: * Define `rsc` and `ssr` environments, both targeting `node`, used separately for React Server Components and SSR. * Define `desktop` and `mobile` environments, both targeting `web`, used separately for desktop and mobile browsers. Without the `environments` configuration, you would need to define multiple configurations for these scenarios and run multiple independent Rsbuild builds. Now, with the `environments` configuration, you can complete the build for multiple outputs in a single Rsbuild run (Rsbuild achieves this using Rspack's [MultiCompiler](https://rspack.dev/api/javascript-api/compiler#multicompiler)). In Rsbuild, each `environment` is associated with an Rsbuild configuration, an Rspack configuration, and a set of build outputs. Rsbuild plugin developers can customize the build process for a specified environment based on the `environment` name, such as modifying Rsbuild or Rspack configurations, registering or removing plugins, adjusting Rspack rules, and viewing assets information. ## Environment configs Rsbuild supports defining different Rsbuild configs for each environment through [environments](/config/environments.md). For example, if your project wants to support the SSR function, you need to define different configs for client and SSR respectively. You can define a web and node environment respectively. ```ts title="rsbuild.config.ts" export default { environments: { // Configure the web environment for browsers web: { source: { entry: { index: './src/index.client.js', }, }, output: { // Use 'web' target for the browser outputs target: 'web', }, resolve: { alias: { '@common': './src/client/common', }, }, }, // Configure the node environment for SSR node: { source: { entry: { index: './src/index.server.js', }, }, output: { // Use 'node' target for the Node.js outputs target: 'node', }, resolve: { alias: { '@common': './src/server/common', }, }, }, }, }; ``` ### Config merging If you configure `environments`, Rsbuild will merge the config in `environments` with the outer base config. When merging, the config in `environments` has higher priority. In the example above, after merging the configs, Rsbuild generates two standalone environment configs for building web and node environments. * **web environments config**: Generated by merging base config with `environments.web` * **node environments config**: Generated by merging base config with `environments.node` Then, Rsbuild will use these environments configs to internally generate two Rspack configs and execute a single build using Rspack’s MultiCompiler. ### Debug config When you execute the command `npx rsbuild inspect` in the project root directory, you will find the following output: * `rsbuild.config.[name].mjs`: The Rsbuild config used for a certain environment during build. * `rspack.config.[name].mjs`: The Rspack config corresponding to a certain environment when building. ```bash ➜ npx rsbuild inspect config inspection completed, generated files: - Rsbuild config (web): /project/dist/.rsbuild/rsbuild.config.web.mjs - Rsbuild config (node): /project/dist/.rsbuild/rsbuild.config.node.mjs - Rspack config (web): /project/dist/.rsbuild/rspack.config.web.mjs - Rspack config (node): /project/dist/.rsbuild/rspack.config.node.mjs ``` ## Default environment When environments is not specified, Rsbuild will by default create an environment with the same name based on the currently target type (the value of [output.target](/config/output/target.md)). ```ts title="rsbuild.config.ts" export default { output: { target: 'web', }, }; ``` The above config is equivalent to a simplification of the following config: ```ts title="rsbuild.config.ts" export default { environments: { web: { output: { target: 'web', }, }, }, }; ``` ## Build specified environment By default, Rsbuild will build all environments in the Rsbuild configuration when you execute `rsbuild dev` or `rsbuild build`. You can build only the specified environment via `--environment <name>`. ```bash # Build for all environments by default rsbuild dev # Build for the web environment rsbuild dev --environment web # Build for the web and ssr environments rsbuild dev --environment web --environment node # Build multiple environments can be shortened to: rsbuild dev --environment web,node ``` ## Add plugins for specified environment Plugins configured through the [plugins](/config/plugins.md) field support running in all environments. If you want a plugin to run only in a specified environment, you can configure the plugin in the specified `environment`. For example, enable the React plugin only in the web environment: ```ts title="rsbuild.config.ts" import { pluginReact } from '@rsbuild/plugin-react'; export default { environments: { web: { output: { target: 'web', }, plugins: [pluginReact()], }, node: { output: { target: 'node', }, }, }, }; ``` If you are a plugin developer, you can view [Developing environment plugins](/plugins/dev/index.md#environment-plugin) for details. ## Plugin API ### Update environment config Rsbuild supports modifying or adding environment config through the [modifyRsbuildConfig](/plugins/dev/hooks.md#modifyrsbuildconfig) hook. ```ts const myPlugin = () => ({ setup(api) { api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => { return mergeRsbuildConfig(config, { environments: { web1: { source: { entry: { index: './src/web1/index', }, }, }, }, }); }); }, }); ``` ### Configuring a specific environment Rsbuild supports modifying the Rsbuild config of a specific environment through the [modifyEnvironmentConfig](/plugins/dev/hooks.md#modifyenvironmentconfig) hook. ```ts const myPlugin = () => ({ setup(api) { api.modifyEnvironmentConfig((config, { name }) => { if (name !== 'web') { return config; } config.html.title = 'My Default Title'; }); }, }); ``` ## Environment context [Environment context](/api/javascript-api/environment-api.md#environment-context) is a read-only object that provides some context infos about the current environment. Rsbuild supports obtaining environment context information in plugin hooks. For some plugin hooks related to the build environment (such as [modifyRspackConfig](/plugins/dev/hooks.md#modifyrspackconfig) and [modifyBundlerChain](/plugins/dev/hooks.md#modifybundlerchain)), Rsbuild supports obtaining the current environment context through the `environment` parameter. ```ts const myPlugin = () => ({ setup(api) { api.modifyRspackConfig((rspackConfig, { environment }) => { if (environment.name === 'node') { // do some thing } }); }, }); ``` For some global plugin hooks (such as [onDevCompileDone](/plugins/dev/hooks.md#ondevcompiledone), [onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver), etc.), Rsbuild supports obtaining the context of all environments through the `environments` parameter. ```ts const myPlugin = () => ({ setup(api) { api.onDevCompileDone(({ environments }) => { environments.forEach((environment) => { console.log('environment', environment); }); }); }, }); ``` ## Environment API Rsbuild server provides a series of APIs related to the build environment. Users can operate the build artifacts in a specific environment on the server side through the Rsbuild [environment API](/api/javascript-api/environment-api.md#environment-api). You can use the environment API in [Rsbuild DevMiddleware](/config/dev/setup-middlewares.md) or [Custom Server](/api/javascript-api/instance.md#rsbuildcreatedevserver). For example, you can quickly implement an SSR function through the Rsbuild environment API in development mode: ```ts import express from 'express'; import { createRsbuild, loadConfig } from '@rsbuild/core'; const serverRender = ({ environments }) => async (_req, res) => { const bundle = await environments.node.loadBundle('index'); const rendered = bundle.render(); const template = await environments.web.getTransformedHtml('index'); const html = template.replace('<!--app-content-->', rendered); res.writeHead(200, { 'Content-Type': 'text/html', }); res.end(html); }; export async function startDevServer() { const { content } = await loadConfig(); // Init Rsbuild const rsbuild = await createRsbuild({ rsbuildConfig: content, }); const app = express(); // Create Rsbuild dev server instance const rsbuildServer = await rsbuild.createDevServer(); const serverRenderMiddleware = serverRender(rsbuildServer); app.get('/', async (req, res, next) => { try { await serverRenderMiddleware(req, res, next); } catch (err) { logger.error('SSR render error, downgrade to CSR...\n', err); next(); } }); // Apply Rsbuild’s built-in middlewares app.use(rsbuildServer.middlewares); // ... } ``` For detailed usage, please refer to: [SSR + Express Example](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/ssr-express). ## Build order By default, Rsbuild builds all environments in parallel. To control the build order between different environments, you can set build dependencies through Rspack's [dependencies](https://rspack.dev/config/other-options#dependencies) configuration. For example, if you need to build the `web` environment first, then build the `node` environment, you can add the following configuration: ```ts title="rsbuild.config.ts" export default { environments: { web: { tools: { rspack: { name: 'foo', }, }, }, node: { tools: { rspack: { dependencies: ['foo'], }, }, }, }, }; ``` We can use a simple plugin to test the build order of multiple environments: ```ts const testPlugin: RsbuildPlugin = { name: 'test-plugin', setup(api) { api.onBeforeEnvironmentCompile(({ environment }) => { console.log('build start:', environment.name); }); api.onAfterEnvironmentCompile(({ stats, environment }) => { console.log('build done:', environment.name); console.log('stats', stats); }); }, }; // The plugin will output: // - build start: web // - build done: web // - stats: { ... } // - build start: node // - build done: node // - stats: { ... } ``` --- url: /guide/advanced/ssr.md --- # Server-side rendering (SSR) This chapter introduces how to implement SSR functionality using Rsbuild. Please note that Rsbuild itself does not provide out-of-the-box SSR functionality, but instead provides low-level APIs and configurations to allow framework developers to implement SSR. If you require out-of-the-box SSR support, you may consider using full-stack frameworks based on Rsbuild, such as [Modern.js](https://github.com/web-infra-dev/modern.js). ## What is SSR SSR stands for "Server-side rendering". It means that the HTML of the web page is generated by the server and sent to the client, rather than sending only an empty HTML shell and relying on JavaScript to generate the page content. In traditional client-side rendering, the server sends an empty HTML shell and some JavaScript scripts to the client, and then fetching data from the server's API and fills the page with dynamic content. This leads to slow initial page loading times and is not conducive to user experience and SEO. With SSR, the server generates HTML that already contains dynamic content and sends it to the client. This makes the initial page loading faster and more SEO-friendly, as search engines can crawl the rendered page. ## File structure A typical SSR application will have the following files: ``` - index.html - server.js # main application server - src/ - App.js # exports app code - index.client.js # client entry, mounts the app to a DOM element - index.server.js # server entry, renders the app using the framework's SSR API ``` The `index.html` will need to include a placeholder where the server-rendered rendered should be injected: ```html <div id="root"><!--app-content--></div> ``` ## Create SSR configuration In the SSR scenario, two types of outputs (web and node targets), need to be generated at the same time, for client-side rendering (CSR) and server-side rendering (SSR) respectively. At this time, you can use Rsbuild's [multi-environment builds](/guide/advanced/environments.md) capability, define the following configuration: ```ts title="rsbuild.config.ts" export default { environments: { // Configure the web environment for browsers web: { source: { entry: { index: './src/index.client.js', }, }, output: { // Use 'web' target for the browser outputs target: 'web', }, html: { // Custom HTML template template: './index.html', }, }, // Configure the node environment for SSR node: { source: { entry: { index: './src/index.server.js', }, }, output: { // Use 'node' target for the Node.js outputs target: 'node', }, }, }, }; ``` ## Custom server Rsbuild provides the [Dev server API](/api/javascript-api/dev-server-api.md) and [environment API](/guide/advanced/environments.md#environment-api) to allow you to implement SSR. Here is a basic example: ```ts title="server.mjs" import express from 'express'; import { createRsbuild } from '@rsbuild/core'; async function initRsbuild() { const rsbuild = await createRsbuild({ rsbuildConfig: { server: { middlewareMode: true, }, }, }); return rsbuild.createDevServer(); } async function startDevServer() { const app = express(); const rsbuild = await initRsbuild(); const { environments } = rsbuild; // SSR when accessing /index.html app.get('/', async (req, res, next) => { try { // Load server bundle const bundle = await environments.node.loadBundle('index'); const template = await environments.web.getTransformedHtml('index'); const rendered = bundle.render(); // Insert rendered content into HTML template const html = template.replace('<!--app-content-->', rendered); res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html); } catch (err) { logger.error('SSR failed: ', err); next(); } }); app.use(rsbuild.middlewares); const server = app.listen(rsbuild.port, async () => { await rsbuild.afterListen(); }); rsbuild.connectWebSocket({ server }); } startDevServer(); ``` ## Modify startup script After using a custom Server, you need to change the startup command from `rsbuild dev` to `node ./server.mjs`. If you need to preview the online effect of SSR, you also need to modify the preview command. SSR Prod Server example reference: [Example](https://github.com/rspack-contrib/rstack-examples/blob/main/rsbuild/ssr-express/prod-server.mjs). ```json title="package.json" { "scripts": { "build": "rsbuild build", "dev": "node ./server.mjs", "preview": "node ./prod-server.mjs" } } ``` Now, you can run the `npm run dev` command to start the dev server with SSR function, and visit `http://localhost:3000/` to see that the SSR content has been rendered to the HTML page. ## Get manifest By default, scripts and links associated with the current page are automatically inserted into the HTML template. At this time, the compiled HTML template content can be obtained through [getTransformedHtml](/api/javascript-api/environment-api.md#gettransformedhtml). When you need to dynamically generate HTML on the server side, you'll need to inject the URLs of JavaScript and CSS assets into the HTML. By configuring [output.manifest](/config/output/manifest.md), you can easily obtain the manifest information of these assets. Here's an example: ```ts title="rsbuild.config.ts" export default { output: { manifest: true, }, }; ``` ```ts title="server.ts" async function renderHtmlPage(): Promise<string> { const manifest = await fs.promises.readFile('./dist/manifest.json', 'utf-8'); const { entries } = JSON.parse(manifest); const { js, css } = entries['index'].initial; const scriptTags = js .map((url) => `<script src="${url}" defer></script>`) .join('\n'); const styleTags = css .map((file) => `<link rel="stylesheet" href="${file}">`) .join('\n'); return ` <!DOCTYPE html> <html> <head> ${scriptTags} ${styleTags} </head> <body> <div id="root"></div> </body> </html>`; } ``` ## Examples * [SSR + Express Example](https://github.com/rspack-contrib/rstack-examples/blob/main/rsbuild/ssr-express) * [SSR + Express + Manifest Example](https://github.com/rspack-contrib/rstack-examples/blob/main/rsbuild/ssr-express-with-manifest) --- url: /guide/optimization/code-splitting.md --- # Code splitting A great chunk splitting strategy is very important to improve the loading performance of the application. It can make full use of the browser's caching mechanism to reduce the number of requests and improve the loading speed of the application. Several [chunk splitting strategies](/guide/optimization/code-splitting.md) are built into Rsbuild. These should meet the needs of most applications. You can also customize the chunk splitting config to suit your own usage scenario. > See [Rspack - Code Splitting](https://rspack.dev/guide/optimization/code-splitting) for more details. ## Strategies > The chunk splitting config of Rsbuild is in [performance.chunkSplit](/config/performance/chunk-split.md). Rsbuild supports the following chunk splitting strategies: * `split-by-experience`: an empirical splitting strategy, automatically splits some commonly used npm packages into chunks of moderate size. * `split-by-module`: split by NPM package granularity, each NPM package corresponds to a chunk. * `split-by-size`: automatically split according to module size. * `all-in-one`: bundle all codes into one chunk. * `single-vendor`: bundle all NPM packages into a single chunk. * `custom`: custom chunk splitting strategy. ## split-by-experience ### Behavior Rsbuild adopts the `split-by-experience` strategy by default, which is a strategy we have developed from experience. Specifically, when the following npm packages are referenced in your project, they will automatically be split into separate chunks: * `lib-polyfill.js`: includes `core-js`, `@swc/helpers`, `tslib`. * `lib-axios.js`: includes `axios` and related packages. Grouping commonly used packages in this way and then splitting them into individual chunks helps with browser caching. ### Config ```ts export default { performance: { chunkSplit: { strategy: 'split-by-experience', }, }, }; ``` ### Notes * If the npm packages mentioned above are not installed or used in the project, the corresponding chunk will not be generated. ## split-by-module ### Behavior Split each NPM package into a Chunk. ::: warning This strategy will split the node\_modules in the most granular way, and at the same time, under HTTP/2, multiplexing will speed up the loading time of resources.However, in non-HTTP/2 environments, it needs to be used with caution because of HTTP head-of-line blocking problem. ::: ### Config ```ts export default { performance: { chunkSplit: { strategy: 'split-by-module', }, }, }; ``` ### Notes * This configuration will split the node\_modules into smaller chunks, resulting in a large number of file requests. * When using HTTP/2, resource loading time will be accelerated and cache hit rate will be improved due to multiplexing. * When not using HTTP/2, the performance of page loading may be reduced due to HTTP head-of-line blocking. Please use with caution. ## all-in-one ### Behavior This strategy puts all source code and third-party dependencies in the same Chunk. ### Config ```ts export default { performance: { chunkSplit: { strategy: 'all-in-one', }, }, }; ``` ### Notes * This configuration will bundle all the generated JS code into one file (except for dynamically imported chunks). * The size of a single JS file may be very large, leading to a decrease in page loading performance. If you need to bundle the chunks split by dynamic import into the single file, you can set the [output.asyncChunks](https://rspack.dev/config/output#outputasyncchunks) option in Rspack to `false`: ```js export default defineConfig({ performance: { chunkSplit: { strategy: 'all-in-one', }, }, tools: { rspack: { output: { asyncChunks: false, }, }, }, }); ``` ## single-vendor ### Behavior This strategy puts third-party dependencies in one Chunk, and source code in another chunk. ### Config ```ts export default { performance: { chunkSplit: { strategy: 'single-vendor', }, }, }; ``` ### Notes * The size of a single vendor file may be very large, leading to a decrease in page loading performance. ## split-by-size ### Behavior Under this strategy, after setting `minSize`, `maxSize` to a fixed value, Rsbuild will automatically split them without extra config. ### Config ```ts export default { performance: { chunkSplit: { strategy: 'split-by-size', minSize: 30000, maxSize: 50000, }, }, }; ``` ## Custom splitting strategy In addition to using the built-in strategies, you can also customize the splitting strategy to meet more customization needs. Custom strategy is divided into two parts: * Custom group * Custom Rspack `splitChunks` config It is worth noting that these two custom capabilities can be used together with the built-in strategy, that is, you can use the built-in strategy to split commonly used packages, and then use the custom function to split other packages. ### Custom group Rsbuild supports custom group, which is more flexible than the built-in strategies, and simpler than writing Rspack's `splitChunks` config. For example, split the `axios` library under node\_modules into `axios.js`: ```js export default { performance: { chunkSplit: { forceSplitting: { axios: /node_modules[\\/]axios/, }, }, }, }; ``` Through `forceSplitting` config, you can easily split some packages into a Chunk. #### Notes Chunks split using the `forceSplitting` configuration will be inserted into the HTML file as resources requested for the initial screen using `<script>` tags. Therefore, please split them appropriately based on the actual scenario to avoid excessive size of initial screen resources. ### Custom config In addition to using custom grouping, you can also customize Rspack's `splitChunks` config through `override`, for example: * Set `minSize` to 30,000, meaning modules smaller than 30,000 bytes will not be split. ```ts export default { performance: { chunkSplit: { override: { chunks: 'all', minSize: 30000, }, }, }, }; ``` * Bundle all CSS files into a single `styles.css`. ```ts export default { performance: { chunkSplit: { override: { cacheGroups: { styles: { name: 'styles', minSize: 0, chunks: 'all', test: /\.(?:css|less|sass|scss|styl)$/, priority: 99, }, }, }, }, }, }; ``` The `override` config will be merged with Rspack's `splitChunks` config. For specific config details, please refer to [Rspack - splitChunks](https://rspack.dev/config/optimization#optimization-splitchunks). ## Using dynamic import for code splitting In addition to the `chunkSplit` configurations, using [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) for code splitting is also an important optimization technique that can effectively reduce the initial bundle size. :::tip About dynamic import Dynamic import is a new feature introduced in ECMAScript 2020 that allows you to dynamically load JavaScript modules. The underlying Rspack used by the Rsbuild supports dynamic import by default, so you can use it directly in your code. ::: When the bundler encounters the `import()` syntax, it automatically splits the relevant code into a new chunk and loads it on-demand at runtime. For example, if your project has a large module called `bigModule.ts` (which can also be a third-party dependency), you can use dynamic import to load it on-demand: ```js // Somewhere in your code where you need to use bigModule import('./bigModule.ts').then((bigModule) => { // Use bigModule here }); ``` When you run the build command, `bigModule.ts` will be automatically split into a new chunk and loaded on-demand at runtime. --- url: /guide/optimization/optimize-bundle.md --- # Bundle size optimization Bundle size optimization is an important part in production build because it directly affects the user experience of online users. In this document, we will introduce some common bundle size optimization methods in Rsbuild. ## Reduce duplicate dependencies It is common for web projects to bundle multiple versions of third-party dependencies. Duplicate dependencies can lead to increased bundle size and slower build speed. ### Detect duplicate dependencies You can use [Rsdoctor](https://rsdoctor.dev) to detect whether there are duplicate dependencies in the project. Rsdoctor will analyze during the build process, find any duplicate bundled dependencies and display them visually: ![](https://assets.rspack.dev/rsbuild/assets/rsdoctor-duplicated-packages.png) For more details, see [Rsdoctor - Duplicate Dependency Problem](https://rsdoctor.dev/blog/topic/duplicate-pkg-problem). ### Eliminate duplicate dependencies We can eliminate duplicate dependencies with the package manager. * Rsbuild provides the [resolve.dedupe](/config/resolve/dedupe.md) config, which allows you to force the specified packages to be resolved from the project root directory, thereby removing duplicate packages. * If you are using `pnpm >= 7.26.0`, you can use the [pnpm dedupe](https://pnpm.io/cli/dedupe) command to upgrade and eliminate duplicate dependencies. ```bash pnpm dedupe ``` * If you are using `pnpm < 7.26.0`, you can use [pnpm-deduplicate](https://github.com/ocavue/pnpm-deduplicate) to analyze all duplicate dependencies, then update dependencies or declare [pnpm overrides](https://pnpm.io/package_json#pnpmoverrides) to merge duplicated dependencies. ```bash npx pnpm-deduplicate --list ``` * If you are using `yarn`, you can use [yarn-deduplicate](https://github.com/scinos/yarn-deduplicate) to automatically merge duplicated dependencies: ```bash npx yarn-deduplicate && yarn ``` ## Use lightweight libraries It is recommended to using lightweight libraries in your project, such as replacing [moment](https://momentjs.com/) with [day.js](https://day.js.org/). To find out the large libraries in the project, add the `BUNDLE_ANALYZE=true` environment variable when building: ```bash BUNDLE_ANALYZE=true pnpm build ``` See the [performance.bundleAnalyze](/config/performance/bundle-analyze.md) configuration for details. ## Adjust browserslist The Rsbuild will compile the code according to the project's Browserslist config, and inject some Polyfills. If the project does not need to be compatible with legacy browsers, you can adjust the Browserslist and drop some legacy browsers, thereby reducing the compilation overhead on syntax and polyfill. Rsbuild's default Browserslist config is: ```js ['chrome >= 87', 'edge >= 88', 'firefox >= 78', 'safari >= 14']; ``` For example, if you only need to be compatible with browsers above Chrome 100, you can change it to: ```js ['Chrome >= 100']; ``` :::tip Please read the [Browserslist](/guide/advanced/browserslist.md) chapter to know more about the usage of Browserslist. ::: ## Usage polyfill If the current project's [output.polyfill](/config/output/polyfill.md) is set to `'entry'`, and you are certain that third-party dependencies do not require additional polyfills, you can change it to `usage`. In `usage` mode, Rsbuild analyzes the syntax used in the source code and injects the required polyfill code on demand to reduce the size of polyfill. ```js export default { output: { polyfill: 'usage', }, }; ``` :::tip Please read the [Browser Compatibility](/guide/advanced/browser-compatibility.md) chapter to know more about the usage of Browserslist. ::: ## Image compression In general front-end projects, the size of image often accounts for a large proportion of the total bundle size of the project.So if the image size can be reduced as much as possible, it will have a significant optimization effect on the project bundle size. You can enable image compression by registering a plugin in the Rsbuild: ```ts title="rsbuild.config.ts" import { pluginImageCompress } from '@rsbuild/plugin-image-compress'; export default { plugins: [pluginImageCompress()], }; ``` See details in [@rsbuild/plugin-image-compress](https://github.com/rspack-contrib/rsbuild-plugin-image-compress). ## Split chunk A great chunk splitting strategy is very important to improve the loading performance of the application. It can make full use of the browser's caching mechanism to reduce the number of requests and improve the loading speed of the application. Several [chunk splitting strategies](/guide/optimization/code-splitting.md) are built into Rsbuild. These should meet the needs of most applications. You can also customize the chunk splitting config to suit your own usage scenario. For example, split the `axios` library under node\_modules into `axios.js`: ```js export default { performance: { chunkSplit: { strategy: 'split-by-experience', forceSplitting: { axios: /node_modules[\\/]axios/, }, }, }, }; ``` --- url: /guide/optimization/build-performance.md --- # Improve build performance Rsbuild optimizes build performance by default, but as the project becomes larger, you may encounter some build performance problems. This document provides some optional speed-up methods, developers can choose some of them to improve the build performance. ## Performance profiling Performing a performance analysis can help you identify performance bottlenecks in your project, allowing for targeted optimization. Please refer to the [Performance Building Analysis](/guide/debug/build-profiling.md) section for more information. ## General optimization The following are some general optimization methods, which can speed up the development build and production build. ### Enable persistent cache Rsbuild provides [performance.buildCache](/config/performance/build-cache.md) configuration, which can significantly improve the speed of rebuilding. ### Reducing modules Optimizing the number of modules referenced by the application can reduce the bundle size and improve build performance. Please read the [Bundle Size Optimization](/guide/optimization/optimize-bundle.md) section to learn some optimization methods. ### Optimize Tailwind CSS When using Tailwind CSS, if the `content` field in `tailwind.config.js` is not correctly configured, this can lead to poor build performance and HMR performance. Please refer to [Tailwind CSS - Optimize Build Performance](/guide/styling/tailwindcss.md#optimize-build-performance) for more details. ## Development optimization The following are methods for improving performance in development mode. ### Enable lazy compilation Enabling lazy compilation can significantly reduce the number of modules compiled at dev startup and improve startup time. ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: true, }, }; ``` > Please refer to [dev.lazyCompilation](/config/dev/lazy-compilation.md) for more information. ### Enable incremental build Rspack provides experimental [experiments.incremental](https://rspack.dev/config/experiments#experimentsincremental) configuration, which can improve the HMR speed in development mode. ```ts title="rsbuild.config.ts" const isDev = process.env.NODE_ENV === 'development'; export default { tools: { rspack: { experiments: { incremental: isDev, }, }, }, }; ``` ### Source map format In order to provide a good debugging experience, Rsbuild uses the `cheap-module-source-map` format source map by default in development mode, which is a high-quality source map format and will bring certain performance overhead. You can improve build speed by adjusting the source map format in development mode through [output.sourceMap](/config/output/source-map.md). For example to disable source map: ```ts title="rsbuild.config.ts" export default { output: { sourceMap: { js: false, }, }, }; ``` Or set the source map format of the development mode to the cheapest `eval` format: ```ts title="rsbuild.config.ts" export default { output: { sourceMap: { js: process.env.NODE_ENV === 'development' ? 'eval' : false, }, }, }; ``` > For detailed differences between different source map formats, see [Rspack - devtool](https://rspack.dev/config/devtool). ### Browserslist for development This strategy is similar to ["Adjust Browserslist"](/guide/optimization/optimize-bundle.md#adjust-browserslist), the difference is that we can set different browserslist for development and production mode, thereby reducing the compilation overhead in development mode. For example, you can add the following config to `.browserslistrc`, which means that only the latest browsers are compatible in development mode, and the actual browsers are compatible in the production mode: ```yaml title=".browserslistrc" [production] chrome >= 87 edge >= 88 firefox >= 78 safari >= 14 [development] last 1 chrome version last 1 firefox version last 1 safari version ``` Note that this can lead to some differences in the build result between development and production modes. --- url: /guide/optimization/inline-assets.md --- # Inline static assets Inline static assets refer to the practice of including the content of a static asset directly in a HTML or JS file, instead of linking to an external file. This can improve the performance of a website by reducing the number of HTTP requests that the browser has to make to load the page. However, static assets inlining also has some disadvantages, such as increasing the size of a single file, which may lead to slower loading. Therefore, in the actual scenario, it is necessary to decide whether to use static assets inlining according to the specific situation. Rsbuild will automatically inline static assets that are less than 4KiB, but sometimes you may need to manually control assets to force them to be inlined or not, and this document explains how to precisely control the inlining behavior of static assets. ## Automatic inlining By default, Rsbuild will inline assets when the file size of is less than a threshold (the default is 4KiB). When inlined, the asset will be converted to a Base64 encoded string and will no longer send a separate HTTP request. When the file size is greater than this threshold, it is loaded as a separate file with a separate HTTP request. ```js import smallImage from './static/smallImage.png'; console.log(smallImage); // "data:image/png;base64,iVBORw0KGgo..." ``` The threshold can be modified with the [output.dataUriLimit](/config/output/data-uri-limit.md) config. For example, set the threshold of images to 5000 Bytes, and set media assets not to be inlined: ```ts export default { output: { dataUriLimit: { image: 5000, media: 0, }, }, }; ``` ## Force inlining You can force an asset to be inlined by adding the `inline` query when importing the asset, regardless of whether the asset's size is smaller than the size threshold. ```tsx import React from 'react'; import img from '. /foo.png?inline'; export default function Foo() { return <img src={img} />; } ``` In the above example, the `foo.png` image will always be inlined, regardless of whether the size of the image is larger than the threshold. ### Referenced from CSS file When you reference a static asset in your CSS file, you can also force inline the asset with the `inline` query. ```css .foo { background-image: url('. /icon.png?inline'); } ``` :::tip Impact of forcing inlining Inlining large assets will significantly increase the first paint time or first content paint time of a page, which will degrade the user experience. And if you inline a static asset multiple times in a CSS file, the base64 content will be injected repeatedly, increasing the bundle size. Please use forced inlining with care. ::: ## Disable inlining To prevent assets from being inlined and ensure they're always loaded as separate files, regardless of their size, you can add the `url` query parameter. ```tsx import React from 'react'; import img from '. /foo.png?url'; export default function Foo() { return <img src={img} />; } ``` In the above example, the `foo.png` image will always be loaded as a separate file, even if the size of the image is smaller than the threshold. ### Referenced from CSS file When you reference a static asset in your CSS file, you can also force the asset not to be inlined with `url` query. ```css .foo { background-image: url('. /icon.png?url'); } ``` :::tip Impact of disabling inlining Disabling asset inlining will increase the number of assets that the web application needs to load. This will reduce the efficiency of loading assets in a weak network environment or in scenarios where HTTP2 is not enabled. Please disable asset inlining with care. ::: ## Inline JS files In addition to inlining static assets into JS files, Rsbuild also supports inlining JS files into HTML files. Just enable the [output.inlineScripts](/config/output/inline-scripts.md) config, and the generated JS files will not be written into the output directory, but will be directly inlined to the corresponding in the HTML file. ```ts export default { output: { inlineScripts: true, }, }; ``` :::tip Inline JS files may cause the single HTML file to be too large, and it will break the HTTP caching. Please use it with caution. ::: ## Inline CSS files You can also inline CSS files into HTML files. Just enable the [output.inlineStyles](/config/output/inline-styles.md) config, the generated CSS file will not be written into the output directory, but will be directly inlined to the corresponding in the HTML file. ```ts export default { output: { inlineStyles: true, }, }; ``` ## Type declaration When you use URL queries such as `?inline` and `?url` in TypeScript code, TypeScript may prompt that the module is missing a type definition: ``` TS2307: Cannot find module './logo.png?inline' or its corresponding type declarations. ``` To fix this, you can add type declarations for these URL queries, please create `src/env.d.ts` file and add the following type declarations. * Method 1: If the `@rsbuild/core` package is installed, you can reference the [preset types](/guide/basic/typescript.md#preset-types) provided by `@rsbuild/core`: ```ts /// <reference types="@rsbuild/core/types" /> ``` * Method 2: Manually add the required type declarations: ```ts declare module '*?url' { const content: string; export default content; } declare module '*?inline' { const content: string; export default content; } ``` --- url: /guide/migration/rsbuild-0-x.md --- # Migrating from Rsbuild 0.x The document lists all breaking changes from Rsbuild 0.7 to 1.0. You can refer to this document for migration. > See [Breaking changes in Rsbuild v1.0.0](https://github.com/web-infra-dev/rsbuild/discussions/2508) for details. ## \[Important] Lightning CSS loader Rsbuild now enables [lightningcss-loader](https://rspack.dev/guide/features/builtin-lightningcss-loader) by default to transform CSS files, it replaces `autoprefixer` to add vendor prefixes and provides better performance. * `@rsbuild/plugin-lightningcss` has been deprecated and no longer needed. * `tools.autoprefixer` config has been removed. Considering that Lightning CSS has some uncovered edge cases, you can still enable autoprefixer via the postcss config file: ```js title="postcss.config.cjs" module.exports = { plugins: { autoprefixer: {}, }, }; ``` ## \[Important] output.polyfill Rsbuild v1 set [output.polyfill](/config/output/polyfill.md) to `'off'` by default, this can reduce the polyfill code and generate smaller bundles by default. If your application need polyfill, please set `output.polyfill` to `'usage'` or `'entry'`: ```ts title="rsbuild.config.ts" export default { output: { polyfill: 'usage', }, }; ``` ## \[Important] source.decorators Rsbuild now uses `2022-11` decorators version by default. This allows Rsbuild to align the default behavior with TypeScript >= 5.0 and esbuild >= 0.21.0. If you are using the legacy decorators, you can add the following config: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ source: { decorators: { version: 'legacy', }, }, }); ``` ## \[Important] output.targets :::tip Rsbuild v1 removes the `output.targets` option and the target parameters of `source.alias` /`source.entry` and other configs, and instead configures it through `environments` to provide more flexible multi-environment config capabilities. Compared with the original options, `environments` has a wider coverage and can perform differentiated config of more configs in multiple environments. For details, please refer to [Multiple-Environment Builds](/guide/advanced/environments.md). ::: Removed `output.targets` config, use [output.target](/config/output/target.md) and [environments](/config/environments.md) config instead. * before: ```js export default { output: { targets: ['web', 'node'], }, }; ``` * after: ```js export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', }, }, }, }; ``` ## \[Important] Rspack config validation Rsbuild now enables Rspack's scheme validation by default to ensure the Rspack configuration is correct. * If there is a type error in the Rspack config object, an error will be thrown and the build will be aborted. * If there are extra fields in the Rspack config object, an error will be thrown, but the build will not fail. > For more details, see [Rspack - RSPACK\_CONFIG\_VALIDATE](https://rspack.dev/guide/migration/webpack#updating-configuration). ## source.alias Removed `target` param for `source.alias` function, use [environments](/config/environments.md) config instead. * before: ```js export default { source: { alias: (alias, { target }) => { if (target === 'node') { alias['@common'] = './src/node/common'; } else if (target === 'web') { alias['@common'] = './src/web/common'; } }, }, output: { targets: ['web', 'node'], }, }; ``` * after: ```js export default { environments: { web: { source: { alias: { '@common': './src/web/common', }, }, output: { target: 'web', }, }, node: { source: { alias: { '@common': './src/node/common', }, }, output: { target: 'node', }, }, }, }; ``` ## source.entry Removed function usage of `source.entry`, use [environments](/config/environments.md) config instead. * before: ```js export default { source: { entry({ target }) { if (target === 'web') { return { index: './src/index.client.js', }; } if (target === 'node') { return { index: './src/index.server.js', }; } }, }, output: { targets: ['web', 'node'], }, }; ``` * after: ```js export default { environments: { web: { source: { entry: { index: './src/index.client.js', }, }, output: { target: 'web', }, }, node: { source: { entry: { index: './src/index.server.js', }, }, output: { target: 'node', }, }, }, }; ``` ## output.overrideBrowserslist `output.overrideBrowserslist` no longer supports `Record<RsbuildTarget, string[]` type, use [environments](/config/environments.md) config instead. * before: ```js export default { output: { overrideBrowserslist: { web: ['iOS >= 9', 'Android >= 4.4'], node: ['node >= 20'], }, }, }; ``` * after: ```js export default defineConfig({ environments: { web: { output: { overrideBrowserslist: ['iOS >= 9', 'Android >= 4.4'], }, }, node: { output: { overrideBrowserslist: ['node >= 20'], }, }, }, }); ``` ## output.emitAssets `output.emitAssets` changed to boolean type, use [environments](/config/environments.md) config instead. * before: ```js export default { output: { targets: ['web', 'node'], emitAssets: ({ target }) => target !== 'node', }, }; ``` * after: ```js export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', emitAssets: false, }, }, }, }; ``` ## output.distPath.server Removed `output.distPath.server`, use the [environments](/config/environments.md) config instead. ```js export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', distPath: { root: 'dist/server', }, }, }, }, }; ``` ## output.minify.html Rsbuild v1 removed the `output.minify.html` and `output.minify.htmlOptions` options, and no longer minify the HTML files. Previously Rsbuild uses `html-minifier-terser` to minify the HTML files. But the performance of `html-minifier-terser` can not meet the needs of Rsbuild applications, and In most cases, there is little benefit in compressing HTML. At this stage, Rsbuild will not built-in `html-minifier-terser`, so we provide a standalone [rsbuild-plugin-html-minifier-terser](https://github.com/rspack-contrib/rsbuild-plugin-html-minifier-terser) to support HTML minification. ```ts title="rsbuild.config.ts" import { pluginHtmlMinifierTerser } from 'rsbuild-plugin-html-minifier-terser'; export default { plugins: [pluginHtmlMinifierTerser()], }; ``` And we plan to use some faster Rust-based HTML minimizer in the future. ## output.charset The default value of [output.charset](/config/output/charset.md) has been changed from `ascii` to `utf8`. To use `ascii`, add the following config: ```ts export default { output: { charset: 'ascii', }, }; ``` ## dev.startUrl `dev.startUrl` has been renamed to [server.open](/config/server/open.md): ```js export default { // [!code --] dev: { startUrl: true, // [!code --] }, // [!code --] // [!code ++] server: { open: true, // [!code ++] }, // [!code ++] }; ``` ## dev.client.port The default value of [dev.client.port](/config/dev/client.md) changed from `<port>` to `''` (use `location.port`). Use the previous value if you want to keep the behavior: ```js export default { dev: { client: { port: '<port>', }, }, }; ``` ## html.appIcon Previously, [html.appIcon](/config/html/app-icon.md) did not support for web app manifests, meaning it was only available on iOS. Now `html.appIcon` supports generating web app manifests, and the type of `html.appIcon` has been changed. * before: ```js export default { html: { appIcon: './src/icon.png', }, }; ``` * after: ```js export default { html: { appIcon: { icons: [{ src: './src/icon.png', size: 180 }], }, }, }; ``` ## Others Rsbuild 1.0 has made some adjustments and optimizations to plugins API and dev server API. Includes: * The `onBeforeBuild` hook supports triggering multiple times in watch mode. * Added `onBeforeEnvironmentCompile` and `onAfterEnvironmentCompile` hooks, which are triggered before/after executing the build of a single environment respectively. * Removed `api.getHtmlPaths` and replaced it with `environment.htmlPaths`. * Removed `api.context.entry` and replaced it with `environment.entry`. * Removed `api.context.targets` and replaced it with `environment.target`. * Removed `rsbuildServer.onHTTPUpgrade` and replaced it with `rsbuildServer.connectWebSocket`. --- url: /guide/migration/webpack.md --- # Webpack This section introduces how to migrate a project using webpack to Rsbuild. ## Installing dependencies First, you need to replace the npm dependencies of webpack with Rsbuild's dependencies. * Remove webpack dependencies: - Install Rsbuild dependencies: ## Updating npm scripts Next, you need to update the npm scripts in your package.json to use Rsbuild's CLI commands. ```json title="package.json" { "scripts": { "serve": "webpack serve -c webpack.config.js", // [!code --] "build": "webpack build -c webpack.config.js", // [!code --] "dev": "rsbuild dev", // [!code ++] "build": "rsbuild build" // [!code ++] } } ``` ## Create configuration file Create a Rsbuild configuration file `rsbuild.config.ts` in the same directory as package.json, and add the following content: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ plugins: [], }); ``` > See [Configure Rsbuild](/guide/configuration/rsbuild.md) for more. ## Configuration migration In a webpack project, there might be some complex `webpack.config.js` configuration files. After migrating to Rsbuild, most webpack configurations are built-in and do not require manual configuration, such as output, resolve, module.rules, etc. For the few webpack configurations that need to be migrated, you can choose the following options: * Use the [tools.rspack](/config/tools/rspack.md) option (Rspack and webpack configurations are basically equivalent). ```ts title="rsbuild.config.ts" export default { tools: { rspack: { plugins: [new SomeWebpackPlugin()], }, }, }; ``` * Use encapsulated configs in Rsbuild, for example, options for css-loader can be set through [tools.cssLoader](/config/tools/css-loader.md). > See [Configure Rspack](/guide/configuration/rspack.md) for more. ### Build entry webpack uses the `entry` field to set the build entry. In Rsbuild, you can use [source.entry](/config/source/entry.md) to set it. ```ts title="rsbuild.config.ts" export default { source: { entry: { foo: './src/pages/foo/index.ts', bar: './src/pages/bar/index.ts', }, }, }; ``` ### Cleaning up config Since Rsbuild has built-in some common loaders and plugins, you can remove the following dependencies, which will significantly improve the dependency installation speed of the project: * css-loader * babel-loader * style-loader * postcss-loader * html-webpack-plugin * mini-css-extract-plugin * autoprefixer * @babel/core * @babel/preset-env * @babel/preset-typescript * @babel/runtime * ... :::tip The above only lists some of the common dependencies that can be removed. In actual webpack projects, there may be many other dependencies, please handle them as appropriate. ::: ### Using plugins Rsbuild offers a rich set of plugins that provide out-of-the-box support for common scenarios. You can refer to the [Plugin List](/plugins/list/index.md) documentation to learn about these plugins. Taking a React project as an example, let's see how to integrate Rsbuild plugins. First, you can remove some React-related build dependencies that are already built into the Rsbuild React plugin, such as: * `react-refresh` * `@babel/preset-react` * `@pmmmwh/react-refresh-webpack-plugin` Then see the [React Plugin](/plugins/list/plugin-react.md) documentation, register it and use it as follows: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; // [!code highlight] export default defineConfig({ plugins: [pluginReact()], // [!code highlight] }); ``` Most of the common webpack loaders and plugins can still be used in Rsbuild, but we recommend prioritizing the plugins provided by Rsbuild. This can further simplify your configuration. Below is their mapping relationship: | webpack | Rsbuild | | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | | [@babel/preset-react](https://npmjs.com/package/@babel/preset-react) | [React Plugin](/plugins/list/plugin-react.md) | | [vue-loader](https://npmjs.com/package/vue-loader) | [Vue Plugin](/plugins/list/plugin-vue.md) or [Vue 2 Plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue2) | | [svelte-loader](https://npmjs.com/package/svelte-loader) | [Svelte Plugin](/plugins/list/plugin-svelte.md) | | [babel-preset-solid](https://npmjs.com/package/babel-preset-solid) | [Solid Plugin](/plugins/list/plugin-solid.md) | | [babel-loader](https://npmjs.com/package/babel-loader) | [Babel Plugin](/plugins/list/plugin-babel.md) | | [sass-loader](https://npmjs.com/package/sass-loader) | [Sass Plugin](/plugins/list/plugin-sass.md) | | [less-loader](https://npmjs.com/package/less-loader) | [Less Plugin](/plugins/list/plugin-less.md) | | [stylus-loader](https://npmjs.com/package/stylus-loader) | [Stylus Plugin](/plugins/list/plugin-stylus.md) | | [mdx-loader](https://npmjs.com/package/mdx-loader) | [MDX Plugin](https://github.com/rspack-contrib/rsbuild-plugin-mdx) | | [pug-loader](https://npmjs.com/package/pug-loader) | [Pug Plugin](https://github.com/rspack-contrib/rsbuild-plugin-pug) | | [yaml-loader](https://npmjs.com/package/yaml-loader) | [Yaml Plugin](https://github.com/rspack-contrib/rsbuild-plugin-yaml) | | [toml-loader](https://npmjs.com/package/toml-loader) | [Toml Plugin](https://github.com/rspack-contrib/rsbuild-plugin-toml) | | [@svgr/webpack](https://npmjs.com/package/@svgr/webpack) | [SVGR Plugin](/plugins/list/plugin-svgr.md) | | [fork-ts-checker-webpack-plugin](https://npmjs.com/package/fork-ts-checker-webpack-plugin) | [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check) | | [node-polyfill-webpack-plugin](https://npmjs.com/package/node-polyfill-webpack-plugin) | [Node Polyfill Plugin](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) | | [@vue/babel-plugin-jsx](https://npmjs.com/package/@vue/babel-plugin-jsx) | [Vue JSX Plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx) | | [@vue/babel-preset-jsx](https://npmjs.com/package/@vue/babel-preset-jsx) | [Vue 2 JSX Plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue2-jsx) | | [eslint-webpack-plugin](https://npmjs.com/package/eslint-webpack-plugin) | [ESLint Plugin](https://github.com/rspack-contrib/rsbuild-plugin-eslint) | | [babel-plugin-styled-components](https://npmjs.com/package/babel-plugin-styled-components) | [Styled Components Plugin](https://github.com/rsbuild-contrib/rsbuild-plugin-styled-components) | ### Configure dev server Rsbuild does not support the use of Rspack's [devServer](https://rspack.dev/config/dev-server) config. Please refer to [Rspack Dev Server](/guide/basic/server.md#rspack-dev-server) for replacement. ## Babel migration Rsbuild uses SWC by default, so most commonly used Babel plugins are no longer required. Here are some common Babel plugins migration examples. ### @babel/preset-env `@babel/preset-env` is no longer required, Rsbuild will automatically downgrade code based on the [browserslist](/guide/advanced/browserslist.md) configuration. Note that Rsbuild does not inject polyfill by default. You can refer to [Polyfill mode](/guide/advanced/browser-compatibility.md#polyfill-mode) for how to inject. ### @babel/preset-typescript `@babel/preset-typescript` is no longer required, as Rsbuild enables SWC's TypeScript transformation by default. ### @babel/preset-react `@babel/preset-react` is no longer required, replace it with [@rsbuild/plugin-react](/plugins/list/plugin-react.md). ### @babel/plugin-transform-runtime `@babel/plugin-transform-runtime` is no longer required, Rsbuild has built-in equivalent `@swc/helpers` as runtime helpers. ### babel-plugin-import `babel-plugin-import` can be replaced with the [source.transformImport](/config/source/transform-import.md) configuration in Rsbuild. * Babel configuration: ```js title="babel.config.js" module.exports = { plugins: [ [ 'import', { libraryName: 'some-library', libraryDirectory: 'es', style: true }, ], ], }; ``` * Rsbuild configuration: ```ts title="rsbuild.config.ts" export default { source: { transformImport: [ { libraryName: 'some-library', libraryDirectory: 'es', style: true }, ], }, }; ``` ## Validating results After completing the above steps, you have completed the basic migration from webpack to Rsbuild. You can now run the `npm run dev` command to try starting the dev server. If you encounter any issues during the build process, please debug according to the error log, or check the webpack configuration to see if there are any necessary configurations that have not been migrated to Rsbuild. ## Contents supplement The current document only covers part of the migration process. If you find suitable content to add, feel free to contribute to the documentation via pull request 🤝. > The documentation for rsbuild can be found in the [rsbuild/website](https://github.com/web-infra-dev/rsbuild/tree/main/website) directory. --- url: /guide/migration/cra.md --- # Create React App This chapter introduces how to migrate a [Create React App](https://github.com/facebook/create-react-app) (CRA) or [CRACO](https://craco.js.org/) project to Rsbuild. :::tip CRA eject If your project has already run the CRA `eject` command, then most of the content in this document will no longer be applicable. After ejecting a CRA project, it becomes more like a project directly using webpack, so you can refer to the [webpack migration guide](/guide/migration/webpack.md). ::: ## Installing dependencies First, you need to replace the npm dependencies of CRA with Rsbuild's dependencies. * Remove CRA dependencies: > For projects using CRACO, you can also remove the @craco/craco dependency. * Install Rsbuild dependencies: ## Updating npm scripts Next, you need to update the npm scripts in package.json to Rsbuild's CLI commands. ```json title="package.json" { "scripts": { "start": "react-scripts start", // [!code --] "build": "react-scripts build", // [!code --] "eject": "react-scripts eject", // [!code --] "start": "rsbuild dev", // [!code ++] "build": "rsbuild build", // [!code ++] "preview": "rsbuild preview" // [!code ++] } } ``` :::tip Rsbuild does not integrate testing frameworks, so it does not provide a command to replace `react-scripts test`. You can directly use testing frameworks such as Jest or Vitest. You can refer to the [Rsbuild react-jest](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/react-jest) example project for configuration. ::: ## Creating configuration file Create a Rsbuild configuration file `rsbuild.config.ts` in the same directory as package.json and add the following content: ```typescript title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginReact } from '@rsbuild/plugin-react'; export default defineConfig({ plugins: [pluginReact()], }); ``` ## HTML template CRA uses the `public/index.html` file as the default HTML template. In Rsbuild, you can specify the HTML template through [html.template](/config/html/template.md): ```ts title="rsbuild.config.ts" export default defineConfig({ html: { template: './public/index.html', }, }); ``` In the HTML template, if you are using the `%PUBLIC_URL%` variable from CRA, replace it with Rsbuild's [assetPrefix variable](/config/html/template-parameters.md) and use a forward slash for concatenation: ```html <!-- [!code --] --> <link rel="icon" href="%PUBLIC_URL%/favicon.ico" /> <!-- [!code ++] --> <link rel="icon" href="<%= assetPrefix %>/favicon.ico" /> ``` This completes the basic migration from CRA to Rsbuild. You can now run the `npm run start` command to try starting the dev server. ## Output directory By default, CRA outputs to the `build` directory, while Rsbuild's default output directory is `dist`. You can configure Rsbuild's [output.distPath.root](/config/output/dist-path.md) option to change the directory to `build`, in line with CRA: ```ts title="rsbuild.config.ts" export default { output: { distPath: { root: 'build', }, }, }; ``` > For more details, please refer to the [Output Files](/guide/basic/output-files.md) section. ## Using CSS preprocessors Rsbuild supports CSS preprocessors such as Sass and Less through plugins. Please refer to: * [Sass Plugin](/plugins/list/plugin-sass.md) * [Less Plugin](/plugins/list/plugin-less.md) * [Stylus Plugin](/plugins/list/plugin-stylus.md) ## Using SVGR If you are using the "SVG to React Component" feature of CRA (i.e., [SVGR](https://react-svgr.com/)), you also need to install the SVGR plugin for Rsbuild. For example, if you are using the following usage: ```jsx import { ReactComponent as Logo } from './logo.svg'; const App = () => ( <div> <Logo /> </div> ); ``` You only need to install and register `@rsbuild/plugin-svgr`: ```ts title="rsbuild.config.ts" import { pluginSvgr } from '@rsbuild/plugin-svgr'; export default { plugins: [pluginSvgr({ mixedImport: true })], }; ``` Please refer to the [SVGR plugin](/plugins/list/plugin-svgr.md) documentation to learn how to use SVGR in Rsbuild. ## Configuration migration Here is the corresponding Rsbuild configuration for [CRA configuration](https://create-react-app.dev/docs/advanced-configuration/): | CRA | Rsbuild | | ----------------------- | ----------------------------------------------------------------------------------------------- | | HOST | [server.host](/config/server/host.md) | | PORT | [server.port](/config/server/port.md) | | HTTPS | [server.https](/config/server/https.md) | | WDS\_SOCKET\_HOST | [dev.client.host](/config/dev/client.md) | | WDS\_SOCKET\_PATH | [dev.client.path](/config/dev/client.md) | | WDS\_SOCKET\_PORT | [dev.client.port](/config/dev/client.md) | | PUBLIC\_URL | [dev.assetPrefix](/config/dev/asset-prefix.md) / [output.assetPrefix](/config/output/asset-prefix.md) | | BUILD\_PATH | [output.distPath](/config/output/dist-path.md) | | GENERATE\_SOURCEMAP | [output.sourceMap](/config/output/source-map.md) | | IMAGE\_INLINE\_SIZE\_LIMIT | [output.dataUriLimit](/config/output/data-uri-limit.md) | | FAST\_REFRESH | [dev.hmr](/config/dev/hmr.md) | | TSC\_COMPILE\_ON\_ERROR | [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check) | Notes: * The above table does not cover all configurations of CRA, feel free to add more. ## Compile node\_modules By default, CRA uses Babel to compile dependencies in node\_modules, but Rsbuild does not, to avoid the performance overhead and potential compilation errors caused by secondary compilation. To handle syntax compatibility issues caused by dependencies in node\_modules, you can use the [source.include](/config/source/include.md#compile-node_modules) config to compile node\_modules. ```ts title="rsbuild.config.ts" export default { source: { // Compile all JS files and exclude core-js include: [{ not: /[\\/]core-js[\\/]/ }], }, }; ``` ## Env variables CRA injects environment variables starting with `REACT_APP_` into the client code by default, while Rsbuild injects environment variables starting with `PUBLIC_` by default (see [public variables](/guide/advanced/env-vars.md#public-variables)). To be compatible with CRA's behavior, you can manually call Rsbuild's [loadEnv](/api/javascript-api/core.md#loadenv) method to read environment variables starting with `REACT_APP_`, and inject them into the client code through the [source.define](/config/source/define.md) config. ```ts title="rsbuild.config.ts" import { defineConfig, loadEnv } from '@rsbuild/core'; const { publicVars } = loadEnv({ prefixes: ['REACT_APP_'] }); export default defineConfig({ source: { define: publicVars, }, }); ``` Note that CRA allows access to the full `process.env` object in the code and also allows destructuring of `process.env`. However, Rsbuild does not define the `process.env` object due to bundle size and security concerns. ```ts title="src/index.js" // In CRA, you can access it like this const { PUBLIC_URL } = process.env; console.log(PUBLIC_URL); console.log(process.env); ``` In Rsbuild, you can use the [source.define](/config/source/define.md) config to set `process.env` and read the `rawPublicVars` returned by the `loadEnv` method to allow the above usage: ```ts title="rsbuild.config.ts" import { defineConfig, loadEnv } from '@rsbuild/core'; const { publicVars, rawPublicVars } = loadEnv({ prefixes: ['REACT_APP_'] }); export default defineConfig({ source: { define: { ...publicVars, 'process.env': JSON.stringify(rawPublicVars), }, }, }); ``` ## Import unknown assets In CRA, if you import an asset that the build tool cannot recognize, CRA will by default output the file to the `build/static/media` directory, for example, the `document.pdf` file: ```js title="index.js" import document from './document.pdf'; ``` In Rsbuild, when importing unrecognized assets, Rsbuild will logs errors: ``` You may need an appropriate loader to handle this file type. ``` To resolve this error, you can use the following methods: * Configure a suitable loader to handle this type of asset via [tools.rspack](/config/tools/rspack.md). * Configure [asset modules](https://rspack.dev/guide/features/asset-module) rule to handle this type of asset via [tools.rspack](/config/tools/rspack.md). For example, you can add the following asset modules config to get the same output result as CRA: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { module: { rules: [ { // Match .png asset // You can change this regular expression to match different types of files test: /\.png$/, type: 'asset/resource', generator: { filename: 'static/media/[name].[hash][ext]', }, }, ], }, }, }, }; ``` ## Remove react-app-polyfill CRA provides [react-app-polyfill](https://npmjs.com/package/react-app-polyfill) to manually inject polyfill code. In the Rsbuild project, you can remove the dependency and code related to react-app-polyfill, as Rsbuild will automatically read the browserslist config and allow you to enable polyfill injection through the [output.polyfill](/config/output/polyfill.md) config. 1. Remove the `react-app-polyfill` reference: ```ts title="src/index.js" import 'react-app-polyfill/ie11'; // [!code --] import 'react-app-polyfill/stable'; // [!code --] ``` 2. Configure [output.polyfill](/config/output/polyfill.md): ```ts title="rsbuild.config.ts" export default { output: { polyfill: 'usage', }, }; ``` > Read [Browser compatibility](/guide/advanced/browser-compatibility.md) to understand how Rsbuild handles polyfills. ## Setup ESLint CRA uses ESLint to lint the code by default. Rsbuild does not include linting by default, but you can add a separate npm script to run ESLint in `package.json`. First, install [eslint](https://eslint.org/) and [eslint-config-react-app](https://npmjs.com/package/eslint-config-react-app), you need to install ESLint v8 to keep consistent with CRA: Then, add the `lint` command in `package.json`, and confirm that the project contains an `eslintConfig` configuration or an independent ESLint configuration file: ```json title="package.json" { "scripts": { "lint": "eslint src" }, "eslintConfig": { "extends": ["react-app", "react-app/jest"] } } ``` Then, you can use the `npm run lint` command to run ESLint. ### Run ESLint during the build In addition to adding the `lint` command in `package.json`, you can also add the [@rsbuild/plugin-eslint](https://github.com/rspack-contrib/rsbuild-plugin-eslint) plugin to maintain the same behavior as CRA. `@rsbuild/plugin-eslint` allows you to run ESLint during the build process. ```ts title="rsbuild.config.ts" import { pluginEslint } from '@rsbuild/plugin-eslint'; export default { plugins: [pluginEslint()], }; ``` After registering the plugin, ESLint will run automatically during development (`npm run dev`) and production builds (`npm run build`). The plugin will display ESLint warnings and errors in the console output. :::warning We do not recommend using the `@rsbuild/plugin-eslint` plugin, as running ESLint during the build process will significantly increase the build time. Instead, we recommend using a separate `lint` command to run ESLint checks. ::: ## Reading jsconfig.json In non-TypeScript projects, CRA supports reading the `paths` field in jsconfig.json as the path alias. To use this feature in Rsbuild, refer to the [Path Alias - jsconfig.json](/guide/advanced/alias.md#jsconfigjson). ## CRACO migration If your project is using [CRACO](https://craco.js.org) to override CRA configuration, you can refer to the table below for migration: | CRACO | Rsbuild | | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | | [webpack.configure](https://craco.js.org/docs/configuration/webpack/#webpackconfigure) | [tools.rspack](/config/tools/rspack.md) | | [webpack.alias](https://craco.js.org/docs/configuration/webpack/#webpackalias) | [resolve.alias](/config/resolve/alias.md) | | [webpack.plugins.add](https://craco.js.org/docs/configuration/webpack/#webpackplugins) | [appendPlugins of tools.rspack](/config/tools/rspack.md#appendplugins) | | [webpack.plugins.remove](https://craco.js.org/docs/configuration/webpack/#webpackpluginsremove) | [removePlugin of tools.rspack](/config/tools/rspack.md#removeplugin) | | [style.modules](https://craco.js.org/docs/configuration/style/#stylemodules) | [output.cssModules](/config/output/css-modules.md) | | [style.css](https://craco.js.org/docs/configuration/style/#stylecss) | [tools.cssLoader](/config/tools/css-loader.md) | | [style.sass](https://craco.js.org/docs/configuration/style/#stylesass) | [Sass Plugin](/plugins/list/plugin-sass.md) | | [style.postcss](https://craco.js.org/docs/configuration/style/#stylepostcss) | [tools.postcss](/config/tools/postcss.md) | | [babel](https://craco.js.org/docs/configuration/babel/) | [Babel Plugin](/plugins/list/plugin-babel.md) | | [typescript](https://craco.js.org/docs/configuration/typescript/) | [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check) | | [devServer](https://craco.js.org/docs/configuration/devserver/) | [server configs](/config/index.md) | ### Example Here is an example of migrating from `webpack.configure` to `tools.rspack`: * Before migration: ```js title="craco.config.js" const { whenDev } = require('@craco/craco'); module.exports = { webpack: { configure: { resolve: { mainFields: ['browser', 'module', 'main'], }, }, plugins: [...whenDev(() => [new MyWebpackPlugin()], [])], }, }; ``` * After migration: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { resolve: { mainFields: ['browser', 'module', 'main'], }, plugins: process.env.NODE_ENV === 'development' ? [new MyWebpackPlugin()] : [], }, }, }; ``` ## Contents supplement The current document only covers part of the migration process. If you find suitable content to add, feel free to contribute to the documentation via pull request 🤝. > The documentation for rsbuild can be found in the [rsbuild/website](https://github.com/web-infra-dev/rsbuild/tree/main/website) directory. --- url: /guide/migration/vue-cli.md --- # Vue CLI This chapter introduces how to migrate a [Vue CLI](https://github.com/vuejs/vue-cli) project to Rsbuild. ## Install dependencies First, you need to replace the npm dependencies of Vue CLI with Rsbuild's dependencies. * Remove Vue CLI dependencies: - Install Rsbuild dependencies: :::tip If your project is based on Vue 2, replace `@rsbuild/plugin-vue` with `@rsbuild/plugin-vue2`. ::: ## Update npm scripts Next, you need to update the npm scripts in the package.json file to Rsbuild's CLI commands. ```json title="package.json" { "scripts": { "serve": "vue-cli-service serve", // [!code --] "build": "vue-cli-service build", // [!code --] "serve": "rsbuild dev", // [!code ++] "build": "rsbuild build", // [!code ++] "preview": "rsbuild preview" // [!code ++] } } ``` :::tip Rsbuild does not integrate ESLint, so it does not provide a command to replace `vue-cli-service lint`. You can directly use ESLint's [CLI commands](https://eslint.org/docs/latest/use/command-line-interface) as an alternative. ::: ## Create configuration file Create a Rsbuild configuration file `rsbuild.config.ts` in the same directory as package.json, and add the following content: ```typescript import { defineConfig } from '@rsbuild/core'; import { pluginVue } from '@rsbuild/plugin-vue'; export default defineConfig({ plugins: [pluginVue()], source: { // Specify the entry file entry: { index: './src/main.js', }, }, }); ``` :::tip If your project is based on Vue 2, use `import { pluginVue2 } from '@rsbuild/plugin-vue2';`. ::: ## HTML template Vue CLI uses the `public/index.html` file as the default HTML template. In Rsbuild, you can specify the HTML template through [html.template](/config/html/template.md): ```ts title="rsbuild.config.ts" export default defineConfig({ html: { template: './public/index.html', }, }); ``` In the HTML template, if you are using the `BASE_URL` variable from Vue CLI, replace it with Rsbuild's [assetPrefix variable](/config/html/template-parameters.md) and use a forward slash for concatenation: ```html <link rel="icon" href="<%= BASE_URL %>favicon.ico" /> <!-- [!code --] --> <link rel="icon" href="<%= assetPrefix %>/favicon.ico" /> <!-- [!code ++] --> ``` This completes the basic migration from Vue CLI to Rsbuild. You can now run the `npm run serve` command to try starting the dev server. ## Configuration migration Here is the corresponding Rsbuild configuration for Vue CLI configuration: | Vue CLI | Rsbuild | | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | [publicPath](https://cli.vuejs.org/config/#publicpath) | [dev.assetPrefix](/config/dev/asset-prefix.md) / [output.assetPrefix](/config/output/asset-prefix.md) | | [outputDir](https://cli.vuejs.org/config/#outputdir) / [assetsDir](https://cli.vuejs.org/config/#assetsdir) | [output.distPath](/config/output/dist-path.md) | | [filenameHashing](https://cli.vuejs.org/config/#filenamehashing) | [output.filenameHash](/config/output/filename-hash.md) | | [pages](https://cli.vuejs.org/config/#pages) | [source.entry](/config/source/entry.md) / [html.template](/config/html/template.md) / [html.title](/config/html/title.md) | | [transpileDependencies](https://cli.vuejs.org/config/#transpiledependencies) | [source.include](/config/source/include.md) | | [productionSourceMap](https://cli.vuejs.org/config/#productionsourcemap) / [css.sourceMap](https://cli.vuejs.org/config/#css-sourcemap) | [output.sourceMap](/config/output/source-map.md) | | [crossorigin](https://cli.vuejs.org/config/#crossorigin) | [html.crossorigin](/config/html/crossorigin.md) | | [configureWebpack](https://cli.vuejs.org/config/#configurewebpack) | [tools.rspack](/config/tools/rspack.md) | | [chainWebpack](https://cli.vuejs.org/config/#chainwebpack) | [tools.bundlerChain](/config/tools/bundler-chain.md) | | [css.extract](https://cli.vuejs.org/config/#css-extract) | [output.injectStyles](/config/output/inject-styles.md) | | [css.loaderOptions](https://cli.vuejs.org/config/#css-loaderoptions) | [tools.cssLoader](/config/tools/css-loader.md) / [less](/plugins/list/plugin-less.md) / [sass](/plugins/list/plugin-sass.md) / [postcss](/config/tools/postcss.md) | | [devServer.proxy](https://cli.vuejs.org/config/#devserver-proxy) | [server.proxy](/config/server/proxy.md) | Notes: * When migrating `configureWebpack`, note that most of the webpack and Rsbuild configs are the same, but there are also some differences or functionalities not implemented in Rsbuild. * The above table does not cover all configurations of Vue CLI, feel free to add more. ## Environment variables Vue CLI injects environment variables starting with `VUE_APP_` into the client code by default, while Rsbuild injects environment variables starting with `PUBLIC_` by default (see [public variables](/guide/advanced/env-vars.md#public-variables)). To be compatible with Vue CLI's behavior, you can manually call Rsbuild's [loadEnv](/api/javascript-api/core.md#loadenv) method to read environment variables starting with `VUE_APP_`, and inject them into the client code through the [source.define](/config/source/define.md) config. ```ts title="rsbuild.config.ts" import { defineConfig, loadEnv } from '@rsbuild/core'; const { publicVars } = loadEnv({ prefixes: ['VUE_APP_'] }); export default defineConfig({ source: { define: publicVars, }, }); ``` ## Contents supplement The current document only covers part of the migration process. If you find suitable content to add, feel free to contribute to the documentation via pull request 🤝. > The documentation for rsbuild can be found in the [rsbuild/website](https://github.com/web-infra-dev/rsbuild/tree/main/website) directory. --- url: /guide/migration/vite.md --- # Vite This chapter introduces how to migrate a Vite project to Rsbuild. ## Installing dependencies First, you need to replace the npm dependencies of Vite with Rsbuild's dependencies. * Remove Vite dependencies: - Install Rsbuild dependencies: ## Updating npm scripts Next, you need to update the npm scripts in your package.json to use Rsbuild's CLI commands. ```json title="package.json" { "scripts": { "dev": "vite", // [!code --] "build": "vite build", // [!code --] "preview": "vite preview", // [!code --] "dev": "rsbuild dev", // [!code ++] "build": "rsbuild build", // [!code ++] "preview": "rsbuild preview" // [!code ++] } } ``` ## Create configuration file Create a Rsbuild configuration file `rsbuild.config.ts` in the same directory as package.json, and add the following content: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ plugins: [], }); ``` ## Build entry The default build entry points for Rsbuild and Vite are different. Vite uses `index.html` as the default entry, while Rsbuild uses `src/index.js`. When migrating from Vite to Rsbuild, you can use Rsbuild's [source.entry](/config/source/entry.md) to set the build entry and [html.template](/config/html/template.md) to set the template. Using a newly created Vite project as an example, first delete the `<script>` tags from `index.html`: ```html title="index.html" <!-- [!code --] --> <script type="module" src="/src/main.ts"></script> ``` Then add the following config. ```ts title="rsbuild.config.ts" export default { html: { template: './index.html', }, source: { entry: { index: './src/main.ts', }, }, }; ``` Rsbuild will automatically inject the `<script>` tags into the generated HTML files during the build process. ## Migrating plugins Most common Vite plugins can be easily migrated to Rsbuild plugins, such as: | Vite | Rsbuild | | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | [@vitejs/plugin-react](https://npmjs.com/package/@vitejs/plugin-react) | [@rsbuild/plugin-react](/plugins/list/plugin-react.md) | | [@vitejs/plugin-react-swc](https://npmjs.com/package/@vitejs/plugin-react-swc) | [@rsbuild/plugin-react](/plugins/list/plugin-react.md) | | [@vitejs/plugin-vue](https://npmjs.com/package/@vitejs/plugin-vue) | [@rsbuild/plugin-vue](/plugins/list/plugin-vue.md) | | [@vitejs/plugin-vue2](https://npmjs.com/package/@vitejs/plugin-vue2) | [@rsbuild/plugin-vue2](https://github.com/rspack-contrib/rsbuild-plugin-vue2) | | [@vitejs/plugin-vue-jsx](https://npmjs.com/package/@vitejs/plugin-vue-jsx) | [@rsbuild/plugin-vue-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx) | | [@vitejs/plugin-vue2-jsx](https://npmjs.com/package/@vitejs/plugin-vue2-jsx) | [@rsbuild/plugin-vue2-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue2-jsx) | | [@vitejs/plugin-basic-ssl](https://npmjs.com/package/@vitejs/plugin-basic-ssl) | [@rsbuild/plugin-basic-ssl](https://github.com/rspack-contrib/rsbuild-plugin-basic-ssl) | | [@vitejs/plugin-legacy](https://npmjs.com/package/@vitejs/plugin-legacy) | No need to use, see [Browser Compatibility](/guide/advanced/browser-compatibility.md) for details | | [@sveltejs/vite-plugin-svelte](https://npmjs.com/package/@sveltejs/vite-plugin-svelte) | [@rsbuild/plugin-svelte](/plugins/list/plugin-svelte.md) | | [vite-plugin-svgr](https://npmjs.com/package/vite-plugin-svgr) | [@rsbuild/plugin-svgr](/plugins/list/plugin-svgr.md) | | [vite-plugin-checker](https://npmjs.com/package/vite-plugin-checker) | [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check) | | [vite-plugin-eslint](https://npmjs.com/package/vite-plugin-eslint) | [@rsbuild/plugin-eslint](https://github.com/rspack-contrib/rsbuild-plugin-eslint) | | [vite-plugin-static-copy](https://npmjs.com/package/vite-plugin-static-copy) | [output.copy](/config/output/copy.md) | | [vite-plugin-node-polyfills](https://npmjs.com/package/vite-plugin-node-polyfills) | [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) | | [vite-plugin-solid](https://npmjs.com/package/vite-plugin-solid) | [@rsbuild/plugin-solid](/plugins/list/plugin-solid.md) | | [@preact/preset-vite](https://npmjs.com/package/@preact/preset-vite) | [@rsbuild/plugin-preact](/plugins/list/plugin-preact.md) | You can refer to [Plugin List](/plugins/list/index.md) to learn more about available plugins. ## Configuration migration Here is the corresponding Rsbuild configuration for Vite configuration: | Vite | Rsbuild | | ------------------------------------- | ---------------------------------------------------------------- | | root | [root](/config/root.md) | | mode | [mode](/config/mode.md) | | base | [server.base](/config/server/base.md) | | define | [source.define](/config/source/define.md) | | plugins | [plugins](/config/plugins.md) | | appType | [server.historyApiFallback](/config/server/history-api-fallback.md) | | envDir | [Env directory](/guide/advanced/env-vars.md#env-directory) | | cacheDir | [buildCache](/config/performance/build-cache.md) | | publicDir | [server.publicDir](/config/server/public-dir.md) | | assetsInclude | [source.assetsInclude](/config/source/assets-include.md) | | resolve.alias | [resolve.alias](/config/resolve/alias.md) | | resolve.dedupe | [resolve.dedupe](/config/resolve/dedupe.md) | | resolve.extensions | [resolve.extensions](/config/resolve/extensions.md) | | resolve.conditions | [tools.rspack.resolve.conditionNames](/config/tools/rspack.md) | | resolve.mainFields | [tools.rspack.resolve.mainFields](/config/tools/rspack.md) | | resolve.preserveSymlinks | [tools.rspack.resolve.symlinks](/config/tools/rspack.md) | | html.cspNonce | [security.nonce](/config/security/nonce.md) | | css.modules | [output.cssModules](/config/output/css-modules.md) | | css.postcss | [tools.postcss](/config/tools/postcss.md) | | css.preprocessorOptions.sass | [pluginSass](/plugins/list/plugin-sass.md) | | css.preprocessorOptions.less | [pluginLess](/plugins/list/plugin-less.md) | | css.preprocessorOptions.stylus | [pluginStylus](/plugins/list/plugin-stylus.md) | | css.devSourcemap | [output.sourceMap](/config/output/source-map.md) | | css.lightningcss | [tools.lightningcssLoader](/config/tools/lightningcss-loader.md) | | server.host, preview.host | [server.host](/config/server/host.md) | | server.port, preview.port | [server.port](/config/server/port.md) | | server.cors, preview.cors | [server.cors](/config/server/cors.md) | | server.strictPort, preview.strictPort | [server.strictPort](/config/server/strict-port.md) | | server.https, preview.https | [server.https](/config/server/https.md) | | server.open, preview.open | [server.open](/config/server/open.md) | | server.proxy, preview.proxy | [server.proxy](/config/server/proxy.md) | | server.headers, preview.headers | [server.headers](/config/server/headers.md) | | server.hmr | [dev.hmr](/config/dev/hmr.md), [dev.client](/config/dev/client.md) | | server.middlewareMode | [server.middlewareMode](/config/server/middleware-mode.md) | | build.target, build.cssTarget | [Browserslist](/guide/advanced/browserslist.md) | | build.outDir, build.assetsDir | [output.distPath](/config/output/dist-path.md) | | build.assetsInlineLimit | [output.dataUriLimit](/config/output/data-uri-limit.md) | | build.cssMinify | [output.minify](/config/output/minify.md) | | build.sourcemap | [output.sourceMap](/config/output/source-map.md) | | build.lib | Use [Rslib](https://github.com/web-infra-dev/rslib) | | build.manifest | [output.manifest](/config/output/manifest.md) | | build.ssrEmitAssets | [output.emitAssets](/config/output/emit-assets.md) | | build.minify, build.terserOptions | [output.minify](/config/output/minify.md) | | build.emptyOutDir | [output.cleanDistPath](/config/output/clean-dist-path.md) | | build.copyPublicDir | [server.publicDir](/config/server/public-dir.md) | | build.reportCompressedSize | [performance.printFileSize](/config/performance/print-file-size.md) | | ssr, worker | [environments](/config/environments.md) | Notes: * The above table does not cover all configurations of Vite, feel free to add more. ## Environment variables Vite injects environment variables starting with `VITE_` into the client code by default, while Rsbuild injects environment variables starting with `PUBLIC_` by default (see [public variables](/guide/advanced/env-vars.md#public-variables)). To be compatible with Vite's behavior, you can manually call Rsbuild's [loadEnv](/api/javascript-api/core.md#loadenv) method to read environment variables starting with `VITE_`, and inject them into the client code through the [source.define](/config/source/define.md) config. ```ts title="rsbuild.config.ts" import { defineConfig, loadEnv } from '@rsbuild/core'; const { publicVars } = loadEnv({ prefixes: ['VITE_'] }); export default defineConfig({ source: { define: publicVars, }, }); ``` Rsbuild injects the following [environment variables](/guide/advanced/env-vars.md) by default: * `import.meta.env.MODE` * `import.meta.env.BASE_URL` * `import.meta.env.PROD` * `import.meta.env.DEV` For `import.meta.env.SSR`, you can set it through the [environments](/config/environments.md) and [source.define](/config/source/define.md) configuration options: ```ts title="rsbuild.config.ts" export default defineConfig({ environments: { web: { source: { define: { 'import.meta.env.SSR': JSON.stringify(false), }, }, }, node: { source: { define: { 'import.meta.env.SSR': JSON.stringify(true), }, }, output: { target: 'node', }, }, }, }); ``` ## Preset types Vite provides some preset type definitions through the `vite-env.d.ts` file. When migrating to Rsbuild, you can use the [preset types](/guide/basic/typescript.md#preset-types) provided by `@rsbuild/core`: ```ts title="src/env.d.ts" // [!code --] /// <reference types="vite/client" /> // [!code ++] /// <reference types="@rsbuild/core/types" /> ``` ## Glob import Vite provides `import.meta.glob()` for importing multiple modules. When migrating to Rsbuild, you can use the [import.meta.webpackContext()](https://rspack.dev/api/runtime-api/module-variables#importmetawebpackcontext) function of Rspack instead: * Vite: ```js const modules = import.meta.glob('./dir/*.js'); for (const path in modules) { modules[path]().then((mod) => { console.log(path, mod); }); } ``` * Rsbuild: ```js const context = import.meta.webpackContext('./dir', { // Whether to search subdirectories recursive: false, regExp: /\.js$/, }); for (const path of context.keys()) { const mod = context(path); console.log(path, mod); } ``` ## Migrating Vite plugins Rsbuild's plugin API covers most of the Vite and Rollup plugin hooks, for example: | Vite plugin hooks | Rsbuild plugin API | | ----------------- | ---------------------------------------------------------------------------------------------------------------------- | | `resolveId` | [resolve](/plugins/dev/core.md#apiresolve) | | `transform` | [transform](/plugins/dev/core.md#apitransform) | | `config` | [modifyRsbuildConfig](/plugins/dev/hooks.md#modifyrsbuildconfig) | | `configResolved` | [getNormalizedConfig](/plugins/dev/core.md#apigetnormalizedconfig) | | `configureServer` | [onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver) | | `buildStart` | [onBeforeBuild](/plugins/dev/hooks.md#onbeforebuild), [onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver) | | `buildEnd` | [onAfterBuild](/plugins/dev/hooks.md#onafterbuild), [onCloseDevServer](/plugins/dev/hooks.md#onclosedevserver) | | `closeBundle` | [onCloseBuild](/plugins/dev/hooks.md#onclosebuild), [onCloseDevServer](/plugins/dev/hooks.md#onclosedevserver) | See [Plugin system](/plugins/dev/index.md) for more details. ## Validating results After completing the above steps, you have completed the basic migration from Vite to Rsbuild. You can now run the `npm run dev` command to try starting the dev server. If you encounter any issues during the build process, please debug according to the error log, or check the Vite configuration to see if there are any necessary configurations that have not been migrated to Rsbuild. ## Contents supplement The current document only covers part of the migration process. If you find suitable content to add, feel free to contribute to the documentation via pull request 🤝. > The documentation for rsbuild can be found in the [rsbuild/website](https://github.com/web-infra-dev/rsbuild/tree/main/website) directory. --- url: /guide/migration/modern-builder.md --- # Modern.js Builder This chapter introduces how to migrate a Modern.js Builder (or EdenX Builder) project to Rsbuild. ## Key differences Rsbuild is the new version of Modern.js Builder, with the following key differences: * Rsbuild has better performance. When using Rspack simultaneously, **the startup speed and build speed of Rsbuild are 1.5 to 2 times faster than Builder**. * Rsbuild only supports Rspack as the bundler and no longer supports webpack. * Rsbuild's CLI tool and dev server are more powerful and support more features. ## Installing dependencies First, you need to replace the npm dependencies related to Builder with Rsbuild's dependencies. * Remove Builder's dependencies: - Install Rsbuild's dependencies: ## Updating npm scripts Next, you need to update the npm scripts in the package.json to Rsbuild's CLI commands. ```json title="package.json" { "scripts": { "dev": "builder dev", // [!code --] "build": "builder build", // [!code --] "serve": "builder serve", // [!code --] "dev": "rsbuild dev", // [!code ++] "build": "rsbuild build", // [!code ++] "preview": "rsbuild preview" // [!code ++] } } ``` ## Modifying configuration files * Rename `builder.config.ts` to `rsbuild.config.ts`. * Change the import of the `defineConfig` method from `@modern-js/builder-cli` to `@rsbuild/core`. * Change the `builderPlugins` field to `plugins`. ```ts title="rsbuild.config.ts" import { defineConfig } from '@modern-js/builder-cli'; // [!code --] import { defineConfig } from '@rsbuild/core'; // [!code ++] export default defineConfig({ builderPlugins: [], // [!code --] plugins: [], // [!code ++] }); ``` ## Replacing plugins Rsbuild and Builder have incompatible plugin systems, so you need to replace Builder's plugins with Rsbuild's plugins. The following table shows the correspondence between Builder plugins and Rsbuild plugins: | Builder | Rsbuild | | ---------------------------------------- | ------------------------------------------------------------------------------------------------- | | @modern-js/builder-plugin-vue | [@rsbuild/plugin-vue](/plugins/list/plugin-vue.md) | | @modern-js/builder-plugin-vue2 | [@rsbuild/plugin-vue2](https://github.com/rspack-contrib/rsbuild-plugin-vue2) | | @modern-js/builder-plugin-stylus | [@rsbuild/plugin-stylus](/plugins/list/plugin-stylus.md) | | @modern-js/builder-plugin-node-polyfill | [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill) | | @modern-js/builder-plugin-image-compress | [@rsbuild/plugin-image-compress](https://github.com/rspack-contrib/rsbuild-plugin-image-compress) | | @modern-js/builder-plugin-swc | Enabled by default, no need to use | | @modern-js/builder-plugin-esbuild | No longer supported | For example, if you were using `@modern-js/builder-plugin-vue`, you need to first install `@rsbuild/plugin-vue`, then import the plugin in `rsbuild.config.ts` and add it to the `plugins` field. ```ts title="rsbuild.config.ts" import { builderPluginVue } from '@modern-js/builder-plugin-vue'; // [!code --] import { pluginVue } from '@rsbuild/plugin-vue'; // [!code ++] export default defineConfig({ builderPlugins: [builderPluginVue()], // [!code --] plugins: [pluginVue()], // [!code ++] }); ``` ## Add React-related plugins Rsbuild is not coupled with any front-end UI framework. Therefore, if you are a React project, you need to manually add [React Plugin](/plugins/list/plugin-react.md): ```ts title="rsbuild.config.ts" import { pluginReact } from '@rsbuild/plugin-react'; export default { plugins: [pluginReact()], }; ``` If you are using SVGR in your current project, you also need to register [SVGR Plugin](/plugins/list/plugin-svgr.md): ```ts title="rsbuild.config.ts" import { pluginSvgr } from '@rsbuild/plugin-svgr'; export default { plugins: [pluginSvgr()], }; ``` If you are a user of other frameworks, you can refer to [Rsbuild Plugin List](/plugins/list/index.md) to select the corresponding framework plugin. ## Configuration migration Most configs in Rsbuild and Builder are consistent, with only a few adjustments. You can refer to the [Rsbuild options](/config/index.md) to view the configs of Rsbuild. It is worth noting that, compared to Builder, **there are some differences in default values and behaviors in Rsbuild**: * **Browserslist:** The default is minimum compatible with browsers that support [Native ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules), refer to [Default Browserslist](/guide/advanced/browserslist.md#default-browserslist). * **HTML file output path:** default output to the root of dist directory, refer to [Default Directory Structure](/guide/basic/output-files.md#default-directory-structure). * **Polyfill injection method:** Inject on demand by default, refer to [output.polyfill](/config/output/polyfill.md). * **TypeScript type check:** not enabled by default, you need to manually register the [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check). * **Modify DevServer configuration:** Modify `dev` and `server` configuration instead. ## Validating results After completing the above steps, you have migrated from Modern.js Builder to Rsbuild. You can now try starting the dev server by running the `npm run dev` command. If you encounter any issues during the build process, please debug according to the error logs. ## Contents supplement The current document only covers part of the migration process. If you find suitable content to add, feel free to contribute to the documentation via pull request 🤝. > The documentation for rsbuild can be found in the [rsbuild/website](https://github.com/web-infra-dev/rsbuild/tree/main/website) directory. --- url: /guide/debug/debug-mode.md --- # Debug mode Rsbuild provides a debug mode to troubleshoot problems, you can add the `DEBUG=rsbuild` environment variable when building to enable Rsbuild's debug mode. ```bash # Debug in development mode DEBUG=rsbuild pnpm dev # Debug in production mode DEBUG=rsbuild pnpm build ``` In debug mode, Rsbuild will output some additional log information, and write the Rsbuild config and Rspack config to the dist directory, which is convenient for developers to view and debug. ## Log information In debug mode, you will see some logs in the terminal starting with `rsbuild`, including internal operations performed by Rsbuild and the current version of Rspack being used. ```bash $ DEBUG=rsbuild pnpm dev ... rsbuild init plugins rsbuild init plugins done rsbuild use Rspack v1.0.0 ... ``` In addition, the following logs will be output in the terminal, indicating that the Rsbuild has written the internally generated build configs to disk, and you can open these config files to view the corresponding content. ```bash config inspection completed, generated files: - Rsbuild config: /Project/demo/dist/.rsbuild/rsbuild.config.mjs - Rspack config (web): /Project/demo/dist/.rsbuild/rspack.config.web.mjs ``` ## Rsbuild config file In debug mode, Rsbuild will automatically generate `dist/.rsbuild/rsbuild.config.mjs` file, which contains the final generated Rsbuild config. In this file, you can know the final result of the Rsbuild config you passed in after being processed by the framework and Rsbuild. The structure of the file is as follows: ```js title="rsbuild.config.mjs" export default { dev: { // some configs... }, source: { // some configs... }, // other configs... }; ``` For a complete introduction to Rsbuild config, please see the [Configure Rsbuild](/guide/configuration/rsbuild.md) chapter. ## Rspack config file Rsbuild will also automatically generate `dist/.rsbuild/rspack.config.web.mjs` file, which contains the final generated Rspack config. In this file, you can see what is included in the config that Rsbuild finally passes to Rspack. The structure of the file is as follows: ```js title="rspack.config.web.mjs" export default { resolve: { // some resolve configs... }, module: { // some Rspack loaders... }, plugins: [ // some Rspack plugins... ], // other configs... }; ``` For a complete introduction to Rspack configs, please see [Rspack official documentation](https://rspack.dev/config/). --- url: /guide/debug/build-profiling.md --- # Build profiling Performing a performance analysis can help you identify performance bottlenecks in your project, allowing for targeted optimization. ## Using Rsdoctor Rsdoctor is a build analyser that can visually display the compilation time of each loaders and plugins. Please refer to [Use Rsdoctor](/guide/debug/rsdoctor.md) for more information. ## Node.js profiling When Rsbuild executes a build, it will include the runtime overhead of both JavaScript and Rust code, and the overhead of data communication between JavaScript and Rust. In general, the performance overhead on the JavaScript side will be greater than that on the Rust side. You can use Node.js profiling to analyze the overhead on the JS side, which helps to identify performance bottlenecks on the JS side. For example, to perform the [CPU profiling](https://nodejs.org/docs/v20.17.0/api/cli.html#--cpu-prof) analysis, run the following command in the root directory of your project: ```bash # dev node --cpu-prof ./node_modules/@rsbuild/core/bin/rsbuild.js dev # build node --cpu-prof ./node_modules/@rsbuild/core/bin/rsbuild.js build ``` The above commands will generate a `*.cpuprofile` file. We can use [speedscope](https://github.com/jlfwong/speedscope) to visualize this file: ```bash # Install speedscope npm install -g speedscope # View cpuprofile content # Replace the name with the local file name speedscope CPU.date.000000.00000.0.001.cpuprofile ``` ## Rspack profiling Rsbuild supports the use of the `RSPACK_PROFILE` environment variable for Rspack build performance profile. ```json title="package.json" { "scripts": { "dev:profile": "RSPACK_PROFILE=ALL rsbuild dev", "build:profile": "RSPACK_PROFILE=ALL rsbuild build" } } ``` As Windows does not support the above usage, you can also use [cross-env](https://npmjs.com/package/cross-env) to set environment variables. This ensures compatibility across different systems: ```json title="package.json" { "scripts": { "dev:profile": "cross-env RSPACK_PROFILE=ALL rsbuild dev", "build:profile": "cross-env RSPACK_PROFILE=ALL rsbuild build" }, "devDependencies": { "cross-env": "^7.0.0" } } ``` When the build command is finished, or the dev server is shutdown, Rsbuild will generate a `rspack-profile-${timestamp}` folder in the dist folder, and it will contain `logging.json`, `trace.json` and `jscpuprofile.json` files: * `trace.json`: The time spent on each phase of the Rust side is recorded at a granular level using tracing and can be viewed using [ui.perfetto.dev](https://ui.perfetto.dev/). * `jscpuprofile.json`: The time spent at each stage on the JavaScript side is recorded at a granular level using [Node.js inspector](https://nodejs.org/dist/latest-v18.x/docs/api/inspector.html) and can be viewed using [speedscope.app](https://www.speedscope.app/). * `logging.json`: Includes some logging information that keeps a coarse-grained record of how long each phase of the build took. (Not supported in development mode yet) :::tip For more information about Rspack build profiling, refer to [Rspack - Profiling](https://rspack.dev/contribute/development/profiling). ::: --- url: /guide/debug/rsdoctor.md --- # Use Rsdoctor [Rsdoctor](https://rsdoctor.dev/) is a build analyzer tailored for the Rspack ecosystem. Rsdoctor is committed to being a one-stop, intelligent build analyzer that makes the build process transparent, predictable, and optimizable through visualization and smart analysis, helping development teams precisely identify bottlenecks, optimize performance, and improve engineering quality. To debug the build outputs or build process, you can use Rsdoctor for troubleshooting. ## Quick start In a Rsbuild-based project, you can enable Rsdoctor as follows: 1. Install the Rsdoctor plugin: 2. Add `RSDOCTOR=true` env variable before the CLI command: ```json title="package.json" { "scripts": { "dev:rsdoctor": "RSDOCTOR=true rsbuild dev", "build:rsdoctor": "RSDOCTOR=true rsbuild build" } } ``` As Windows does not support the above usage, you can also use [cross-env](https://npmjs.com/package/cross-env) to set environment variables. This ensures compatibility across different systems: ```json title="package.json" { "scripts": { "dev:rsdoctor": "cross-env RSDOCTOR=true rsbuild dev", "build:rsdoctor": "cross-env RSDOCTOR=true rsbuild build" }, "devDependencies": { "cross-env": "^7.0.0" } } ``` After running the above commands, Rsbuild will automatically register the Rsdoctor plugin, and after the build is completed, it will open the build analysis page. For complete features, please refer to [Rsdoctor document](https://rsdoctor.dev/). ## Options To configure the [options](https://rsdoctor.dev/config/options/options) provided by the Rsdoctor plugin, please manually register the Rsdoctor plugin: ```ts title="rsbuild.config.ts" import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin'; export default { tools: { rspack: { plugins: [ process.env.RSDOCTOR === 'true' && new RsdoctorRspackPlugin({ // plugin options }), ], }, }, }; ``` --- url: /guide/faq/general.md --- # General FAQ ### What is the relationship between Rsbuild and Rspack? Rspack is the base bundler for Rsbuild. The goal of Rsbuild is to provide out-of-the-box building capabilities for Rspack users, allowing developers to start a web project with zero configuration. The main differences between Rspack and Rsbuild are: * Rspack projects need to be configured from scratch, while Rsbuild provides default best practice configurations and supports extending Rspack configurations. * Rspack projects require integration with loaders and plugins from the community to support different scenarios, while Rsbuild provides official plugins and default support for common frontend frameworks and build capabilities. * The capabilities of Rspack CLI are comparable to webpack CLI, with relatively streamlined functionality, while Rsbuild provides a more powerful CLI and a more complete dev server. *** ### Can Rsbuild be used to build libraries or UI components? Rsbuild is out-of-the-box for building web applications. For libraries and UI components, it is recommended to use [Rslib](https://github.com/web-infra-dev/rslib), which is a library development tool based on Rsbuild, and can reuse the configuration and plugins of Rsbuild. *** ### What is the relationship between Rsbuild and Modern.js? Modern.js is a progressive web development framework built on top of Rsbuild. The building capabilities of Modern.js are based on Rsbuild. The main differences between Modern.js and Rsbuild are: * Modern.js is based on React, while Rsbuild is not coupled with any frontend UI framework. * Modern.js is a full-stack solution, providing runtime and server-side capabilities, while Rsbuild is a build tool with other capabilities extendable through plugins. * Modern.js has more built-in features, while Rsbuild pursues lightweight and flexibility. --- url: /guide/faq/features.md --- # Features FAQ ### How to import UI component library on demand? To configure the on-demand import of the component library, you can configure it through [source.transformImport](/config/source/transform-import.md), which is equivalent to [babel-plugin-import](https://npmjs.com/package/babel-plugin-import). ```ts export default { source: { transformImport: [ { libraryName: 'my-components', libraryDirectory: 'es', style: true, }, ], }, }; ``` *** ### How to run ESLint during compilation? For the sake of compilation performance, Rsbuild will not perform ESLint verification during the compilation process by default. If you require this feature, you can use Rsbuild's [ESLint plugin](https://github.com/rspack-contrib/rsbuild-plugin-eslint). *** ### How to configure CDN path for static assets? To upload static assets such as JS and CSS to CDN for use, set the URL prefix of static assets through the [output.assetPrefix](/config/output/asset-prefix.md) configuration. ```js export default { output: { assetPrefix: 'https://cdn.example.com/assets/', }, }; ``` *** ### How to remove console after production build? For the production build, we can remove the `console` from the code, so as to avoid the log of the development mode being output to the production. Rsbuild provides a configuration option to remove console by default, please see [performance.removeConsole](/config/performance/remove-console.md). *** ### How to view the final generated Rspack configuration? By using the Rsbuild debug mode, you can view the Rspack configuration generated by Rsbuild. You can enable the debug mode of Rsbuild by adding the `DEBUG=rsbuild` environment variable when performing the build. In this mode, the internally generated Rspack configuration will be outputted to the "dist" directory. ```bash ➜ DEBUG=rsbuild pnpm dev ... rsbuild init plugins rsbuild init plugins done rsbuild use Rspack v1.0.0 ... config inspection completed, generated files: - Rsbuild config: /root/my-project/dist/.rsbuild/rsbuild.config.mjs - Rspack config (web): /root/my-project/dist/.rsbuild/rspack.config.web.mjs ``` *** ### How to ignore specific warnings? By default, Rsbuild will print all error and warning logs generated by the build process. If a large number of warning logs are generated due to the three-party package, it cannot be processed temporarily, and you want to ignore it. Specific warning logs can be ignored through the `ignoreWarnings` configuration provided by Rspack. ```ts export default { tools: { rspack: { ignoreWarnings: [/Using \/ for division outside of calc()/], }, }, }; ``` For details, please refer to: [ignoreWarnings](https://rspack.dev/config/other-options#ignorewarnings). --- url: /guide/faq/exceptions.md --- # Exceptions FAQ ### Find ESNext code in the compiled files? By default, Rsbuild does not compile JavaScript files under `node_modules`. If an npm package used in the project contains ESNext syntax, it will be bundled into the output. When this happens, you can specify directories or modules that need to be compiled additionally through the [source.include](/config/source/include.md) configuration option. *** ### Build error `Error: [object Object] is not a PostCSS plugin` ? Currently, Rsbuild is using PostCSS v8. If you encounter the `Error: [object Object] is not a PostCSS plugin` error during the compilation process, it is usually caused by referencing the wrong version of PostCSS, for example, the version of `postcss` (peerDependencies) in `cssnano` does not meet expectations. You can find the dependencies of `UNMET PEER DEPENDENCY` through `npm ls postcss`, and then install the correct version of dependencies by specifying the PostCSS version in package.json. ``` npm ls postcss ├─┬ css-loader@6.3.0 │ └── UNMET PEER DEPENDENCY postcss@8.3.9 ├─┬ css-minimizer-webpack-plugin@3.0.0 │ └── UNMET PEER DEPENDENCY postcss@8.3.9 ``` *** ### Build error `You may need additional loader`? If the following error message is encountered during the compilation process, it means that there are individual files that cannot be compiled correctly. ```bash Module parse failed: Unexpected token File was processed with these loaders: * some-loader/index.js You may need an additional loader to handle the result of these loaders. ``` Please check if any file formats not supported by Rsbuild are being referenced, and configure the corresponding Rspack loader to compile them. *** ### Compilation error `export 'foo' (imported as 'foo') was not found in './utils'`? If you encounter this error during the compilation process, it means that your code is referencing an export that does not exist. For example, in the following code, `index.ts` is importing the `foo` variable from `utils.ts`, but `utils.ts` only exports the `bar` variable. ```ts // utils.ts export const bar = 'bar'; // index.ts import { foo } from './utils'; ``` In this case, Rsbuild will throw the following error: ```bash Compile Error: File: ./src/index.ts export 'foo' (imported as 'foo') was not found in './utils' (possible exports: bar) ``` If you encounter this issue, the first step is to check the import/export statements in your code and correct any invalid code. There are some common mistakes: * Importing a non-existent variable: ```ts // utils.ts export const bar = 'bar'; // index.ts import { foo } from './utils'; ``` * Re-exporting a type without adding the `type` modifier, causing transpilers like SWC or Babel to fail in recognizing the type export, resulting in compilation errors. ```ts // utils.ts export type Foo = 'bar'; // index.ts export { Foo } from './utils'; // Incorrect export type { Foo } from './utils'; // Correct ``` In some cases, the error may be caused by a third-party dependency that you cannot modify directly. In this situation, if you are sure that the issue does not affect your application, you can add the following configuration to change the log level from `error` to `warn`: ```ts title="rsbuild.config.ts" export default { tools: { rspack: { module: { parser: { javascript: { exportsPresence: 'warn', }, }, }, }, }, }; ``` However, it is important to contact the developer of the third-party dependency immediately to fix the issue. > You can refer to the Rspack documentation for more details on [module.parser.javascript.exportsPresence](https://rspack.dev/config/module#moduleparserjavascriptexportspresence). *** ### Tree shaking does not take effect? Rsbuild will enable the tree shaking of Rspack by default during the production build. Whether tree shaking can take effect depends on whether the code can meet the conditions of Rspack's tree shaking. If you find that tree shaking is not working as expected, you can check whether the `sideEffects` config of the related npm package is correct. If you do not understand the role of `sideEffects`, or if you are interested in the principles behind tree shaking, you can read [Rspack Official Documentation - Tree Shaking](https://rspack.dev/guide/optimization/tree-shaking). *** ### `JavaScript heap out of memory` when compiling? This error indicates that there is a memory overflow problem during the packaging process. In most cases, it is because the bundled content exceeds the default memory limit of Node.js. In case of OOM issues, the easiest way to fix this is by increasing the memory cap, Node.js provides the `--max-old-space-size` option to set this. You can set this parameter by adding [NODE\_OPTIONS](https://nodejs.org/api/cli.html#node_optionsoptions) before the CLI command. For example, add parameters before the `rsbuild build` command: ```json title="package.json" { "scripts": { "build": "rsbuild build" // [!code --] "build": "NODE_OPTIONS=--max_old_space_size=16384 rsbuild build" // [!code ++] } } ``` If you are executing other commands, such as `rsbuild dev`, please add parameters before the corresponding command. The value of the `max_old_space_size` parameter represents the upper limit of the memory size (MB). Generally, it can be set to `16384` (16GB). The following parameters are explained in more detail in the official Node.js documentation: * [NODE\_OPTIONS](https://nodejs.org/api/cli.html#node_optionsoptions) * [--max-old-space-size](https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes) In addition to increasing the memory limit, it is also a solution to improve efficiency by enabling some compilation strategies, please refer to [Improve Build Performance](/guide/optimization/build-performance.md). If the above methods cannot solve your problem, it may be that some abnormal logic in the project has caused memory overflow. You can debug recent code changes and locate the root cause of problems. If it cannot be located, please contact us. *** ### `Can't resolve 'core-js/modules/abc.js'` when compiling? If you get an error similar to the following when compiling, it means that [core-js](https://github.com/zloirock/core-js) cannot be resolved properly in the project. ``` Module not found: Can't resolve 'core-js/modules/es.error.cause.js' ``` Usually, you don't need to install `core-js` in the project, because the Rsbuild already has a built-in `core-js` v3. If there is an error that `core-js` cannot be found, there may be several reasons: 1. The current project overrides the built-in `alias` configuration of Rsbuild, causing the incorrect resolution of the `core-js` path when referenced. In this case, you can check the `alias` configuration of the project. 2. Some code in the project depends on `core-js` v2. In this case, you usually need to find out the corresponding code and upgrade `core-js` to the v3. 3. An npm package in `node_modules` imported `core-js`, but does not declare the `core-js` dependency in `dependencies`. In this case, you need to declare the `core-js` dependency in the corresponding npm package, or install a copy of `core-js` in the project root directory. --- url: /guide/faq/hmr.md --- # HMR FAQ ### How to troubleshooting HMR ineffective issues? There are several possible reasons why HMR may not be work. This document will cover most common causes and provide guidance for troubleshooting. Please refer to the following content for troubleshooting. Before starting the troubleshooting process, it is helpful to have a basic understanding of how HMR works: :::tip HMR Principle 1. The browser establishes a WebSocket connection with the dev server for real-time communication. 2. Whenever the dev server finishes recompiling, it sends a notification to the browser via the WebSocket. The browser then sends a `hot-update.(js|json)` request to the dev server to load the newly compiled module. 3. After receiving the new module, if it is a React project, React Refresh, an official React tool, is used to update React components. Other frameworks have similar tools. ::: After understanding the principle of HMR, you can follow these steps for basic troubleshooting: #### 1. Check the WebSocket connection Open the browser console and check for the presence of the `[HMR] connected.` log. * If it is present, the WebSocket connection is working correctly. You can continue with the following steps. * If it is not present, open the Network panel in Chrome and check the status of the `ws://[host]:[port]/rsbuild-hmr` request. If the request is failed, this indicates that the HMR failed because the WebSocket connection was not successfully established. There can be various reasons why the WebSocket connection fails to establish, such as using a network proxy that prevents the WebSocket request from reaching the dev server. You can check whether the WebSocket request address matches your dev server address. If it does not match, you can configure the WebSocket request address using [dev.client](/config/dev/client.md). #### 2. Check the hot-update requests When you modify the code of a module and trigger a recompilation, the browser sends several `hot-update.json` and `hot-update.js` requests to the dev server to fetch the updated code. You can try modifying a module and inspect the content of the `hot-update.(js|json)` requests. If the content of the request is the latest code, it indicates that the hot update request is working correctly. If the content of the request is incorrect, it is likely due to a network proxy. Check whether the address of the `hot-update.(js|json)` request matches your dev server address. If it does not match, you need to adjust the proxy rules to route the `hot-update.(js|json)` request to the dev server address. #### 3. Check for other causes If the above two steps do not reveal any issues, it is possible that other factors are causing the HMR to fail. For example, it could be that the code does not meet React's requirements for HMR. You can refer to the following questions for further troubleshooting. *** ### HMR not working when external React? To ensure that HMR works properly, we need to use the development builds of React and ReactDOM. If you exclude React via `externals` when bundling, the production build of React is usually injected through CDN, and this can cause HMR to fail. ```js export default { output: { externals: { react: 'React', 'react-dom': 'ReactDOM', }, }, }; ``` To solve this problem, you need to reference the React development artifacts and install React DevTools, then hot reloading will work properly. If you are unsure about the type of React build you are using, you can refer to the [React documentation - Use the Production Build](https://legacy.reactjs.org/docs/optimizing-performance.html#use-the-production-build). *** ### HMR not working when setting filename hash in development mode? Usually, we only set the filename hash in the production mode (i.e., when `process.env.NODE_ENV === 'production'`). If you set the filename hash in the development mode, it may cause HMR to fail (especially for CSS files). This is because every time the file content changes, the hash value changes, preventing tools like [mini-css-extract-plugin](https://npmjs.com/package/mini-css-extract-plugin) from reading the latest file content. * Correct usage: ```js export default { output: { filename: { css: process.env.NODE_ENV === 'production' ? '[name].[contenthash:8].css' : '[name].css', }, }, }; ``` * Incorrect usage: ```js export default { output: { filename: { css: '[name].[contenthash:8].css', }, }, }; ``` *** ### HMR not working when use https? If https is enabled, the HMR connection may fail due to a certificate issue, and if you open the console, you will get an HMR connect failed error. ``` » WebSocket connection to 'wss://localhost:3000/rsbuild-hmr' failed: [HMR] disconnected. Attempting to reconnect. ``` The solution to this problem is to click on "Advanced" -> "Proceed to some page (unsafe)" on the Chrome problem page. > Tips: When accessing the page through Localhost, the words "Your connection is not private" may not appear and can be handled by visiting the Network domain. --- url: /config/index.md --- # Config overview This page lists all the configurations for Rsbuild. See ["Configure Rsbuild"](/guide/configuration/rsbuild.md) for details. --- url: /config/root.md --- # root * **Type:** `string` * **Default:** [process.cwd()](https://nodejs.org/api/process.html#processcwd) * **Version:** `>= 1.0.0` Specify the project root directory. Can be an absolute path, or a path relative to `process.cwd()`. The value of Rsbuild `root` is also be passed to the [context](https://rspack.dev/config/context) configuration of Rspack. :::tip The value of `root` does not affect the path of the `.env` file, as the `.env` file is resolved before the Rsbuild configuration file. Rsbuild CLI supports using the `--root` option to specify the root directory, which can affect the path of the `.env` file. See ["CLI"](/guide/basic/cli.md) for more details. ::: ## Example * Relative path: ```ts title="rsbuild.config.ts" export default { root: './foo', }; ``` * Absolute path: ```ts title="rsbuild.config.ts" import { join } from 'node:path'; export default { root: join(__dirname, 'foo'), }; ``` --- url: /config/mode.md --- # mode * **Type:** `'production' | 'development' | 'none'` * **Version:** `>= 1.0.0` Specify the build mode for Rsbuild, as each mode has different default behavior and optimizations. For example, the `production` mode will minify code by default. The value of Rsbuild `mode` is also be passed to the [mode](https://rspack.dev/config/mode) configuration of Rspack. :::tip The value of `mode` does not affect the loading results of the `.env` file, as the `.env` file is resolved before the Rsbuild configuration file. Rsbuild CLI supports using the `--env-mode` option to specify the env mode. See ["Env mode"](/guide/advanced/env-vars.md#env-mode) for more details. ::: ## Default values The default value of `mode` depends on the `process.env.NODE_ENV` environment variable: * If `NODE_ENV` is `production`, the default value is `production`. * If `NODE_ENV` is `development`, the default value is `development`. * If `NODE_ENV` has any other value, the default value is `none`. If you set the value of `mode`, the value of `NODE_ENV` will be ignored. ```ts title="rsbuild.config.ts" export default { mode: 'production', }; ``` ### Command line When using Rsbuild's command line: * `rsbuild dev` will set the default values of `NODE_ENV` and `mode` to `development`. * `rsbuild build` and `rsbuild preview` will set the default values of `NODE_ENV` and `mode` to `production`. ### JavaScript API When using Rsbuild's JavaScript API: * [rsbuild.startDevServer](/api/javascript-api/instance.md#rsbuildstartdevserver) and [rsbuild.createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver) will set the default values of `NODE_ENV` and `mode` to `development`. * [rsbuild.build](/api/javascript-api/instance.md#rsbuildbuild) and [rsbuild.preview](/api/javascript-api/instance.md#rsbuildpreview) will set the default values of `NODE_ENV` and `mode` to `production`. ## Development mode If the value of `mode` is `development`: * Enable HMR and register the [HotModuleReplacementPlugin](https://rspack.dev/plugins/webpack/hot-module-replacement-plugin). * Generate JavaScript source maps, but do not generate CSS source maps. See [output.sourceMap](/config/output/source-map.md) for details. * The `process.env.NODE_ENV` in the source code will be replaced with `'development'`. * The `import.meta.env.MODE` in the source code will be replaced with `'development'`. * The `import.meta.env.DEV` in the source code will be replaced with `true`. * The `import.meta.env.PROD` in the source code will be replaced with `false`. ## Production mode If the value of `mode` is `production`: * Enable JavaScript code minification and register the [SwcJsMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin). * Enable CSS code minification and register the [LightningCssMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/lightning-css-minimizer-rspack-plugin). * Generated JavaScript and CSS filenames will have hash suffixes, see [output.filenameHash](/config/output/filename-hash.md). * Generated CSS Modules classnames will be shorter, see [cssModules.localIdentName](/config/output/css-modules.md#cssmoduleslocalidentname). * Do not generate JavaScript and CSS source maps, see [output.sourceMap](/config/output/source-map.md). * The `process.env.NODE_ENV` in the source code will be replaced with `'production'`. * The `import.meta.env.MODE` in the source code will be replaced with `'production'`. * The `import.meta.env.DEV` in the source code will be replaced with `false`. * The `import.meta.env.PROD` in the source code will be replaced with `true`. ## None mode If the value of `mode` is `none`: * Do not enable any optimizations. * The `process.env.NODE_ENV` in the source code will not be replaced. * The `import.meta.env.MODE` in the source code will be replaced with `'none'`. * The `import.meta.env.DEV` in the source code will be replaced with `false`. * The `import.meta.env.PROD` in the source code will be replaced with `false`. --- url: /config/plugins.md --- # plugins Used to register Rsbuild plugins. Async plugin (promise) in the plugins array will be resolved, and falsy values will be ignored. * **Type:** ```ts type Falsy = false | null | undefined; type RsbuildPlugins = ( | RsbuildPlugin | Falsy | Promise<RsbuildPlugin | Falsy | RsbuildPlugins> | RsbuildPlugins )[]; ``` * **Default:** `undefined` > Please check out the [Plugin List](/plugins/list/index.md) page to discover all available plugins. ## Example For example, register the Stylus plugin in Rsbuild. * Installing the plugin: * Registering the plugin: ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginStylus } from '@rsbuild/plugin-stylus'; export default defineConfig({ plugins: [pluginStylus()], }); ``` ## Execution order By default, plugins are executed in the order they appear in the `plugins` array. Built-in Rsbuild plugins are executed before user-registered plugins. When a plugin internally uses fields that control the order, such as `pre` and `post`, the execution order is adjusted based on them. See [Pre Plugins](/plugins/dev/core.md#pre-pluginss) for more details. ## Nested plugins Rsbuild also supports adding nested plugins. You can pass in an array containing multiple plugins, similar to a plugin preset collection. This is particularly useful for implementing complex functionalities that require a combination of multiple plugins (such as framework integration). ```ts title="rsbuild.config.ts" function myPlugin() { return [fooPlugin(), barPlugin()]; } export default { plugins: [myPlugin()], }; ``` ## Local plugins If your local code repository contains Rsbuild plugins, you can import them using relative paths. ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginCustom } from './plugins/pluginCustom'; export default defineConfig({ plugins: [pluginCustom()], }); ``` ## Plugin options If a plugin provides custom options, you can pass the configurations through the plugin function's parameters. ```ts title="rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; import { pluginStylus } from '@rsbuild/plugin-stylus'; export default defineConfig({ plugins: [ pluginStylus({ stylusOptions: { lineNumbers: false, }, }), ], }); ``` ## Plugin registration phase It should be noted that plugin registration can only be performed during the Rsbuild initialization phase. You cannot dynamically add other plugins within a plugin through the plugin API: ```ts title="rsbuild.config.ts" // Wrong function myPlugin() { return { setup(api) { api.modifyRsbuildConfig((config, { mergeRsbuildConfig }) => { return mergeRsbuildConfig(config, { plugins: [fooPlugin(), barPlugin()], // <- it won't work }); }); }, }; } // Correct function myPlugin() { return [fooPlugin(), barPlugin()]; } export default { plugins: [myPlugin()], }; ``` ## Rspack plugins The `plugins` option is used to register Rsbuild plugins. If you need to register Rspack or webpack plugins, please use [tools.rspack](/config/tools/rspack.md). ```ts title="rsbuild.config.ts" export default { // Rsbuild Plugins plugins: [pluginStylus()], tools: { rspack: { // Rspack or webpack Plugins plugins: [new SomeWebpackPlugin()], }, }, }; ``` ## Unplugin [unplugin](https://github.com/unjs/unplugin) is a unified plugin system for various build tools. You can use plugins implemented based on unplugin in Rsbuild, just import the `/rspack` subpath of the plugin and register it via [tools.rspack](/config/tools/rspack.md). Here is an example of using [unplugin-vue-components](https://npmjs.com/package/unplugin-vue-components): ```ts import { defineConfig } from '@rsbuild/core'; import { pluginVue } from '@rsbuild/plugin-vue'; import Components from 'unplugin-vue-components/rspack'; export default defineConfig({ plugins: [pluginVue()], tools: { rspack: { plugins: [ Components({ // options }), ], }, }, }); ``` :::tip When using the transform hook in unplugin, please use the `transformInclude` hook to match the specified module. When the transform hook matches the `.html` module, it will replace the default EJS transformation of the [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). ::: > Please ensure that the version of `unplugin` package is >= v1.6.0. --- url: /config/environments.md --- # environments Rsbuild supports building outputs for multiple environments. You can use `environments` to define different Rsbuild configurations for each environment. > Please refer to [Multi-environment builds](/guide/advanced/environments.md) for more information. * **Type:** ```ts interface EnvironmentConfig { plugins?: RsbuildPlugins; dev?: Pick< DevConfig, 'hmr' | 'assetPrefix' | 'progressBar' | 'lazyCompilation' | 'writeToDisk' >; html?: HtmlConfig; tools?: ToolsConfig; source?: SourceConfig; output?: OutputConfig; resolve?: ResolveConfig; security?: SecurityConfig; performance?: PerformanceConfig; moduleFederation?: ModuleFederationConfig; } type Environments = { [name: string]: EnvironmentConfig; }; ``` * **Default:** `undefined` ## Example Configure Rsbuild configuration for `web` (client) and `node` (SSR) environments: ```ts title="rsbuild.config.ts" export default { // Shared configuration for all environments resolve: { alias: { '@common': './src/common', }, }, environments: { // configuration for client web: { source: { entry: { index: './src/index.client.js', }, }, output: { target: 'web', }, resolve: { alias: { '@common1': './src/web/common1', }, }, }, // configuration for SSR node: { source: { entry: { index: './src/index.server.js', }, }, output: { target: 'node', }, resolve: { alias: { '@common1': './src/ssr/common1', }, }, }, }, }; ``` For the `web` environment, the merged Rsbuild configuration is: ```js const webConfig = { source: { entry: { index: './src/index.client.js', }, }, output: { target: 'web', }, resolve: { alias: { '@common': './src/common', '@common1': './src/web/common1', }, }, }; ``` For the `node` environment, the merged Rsbuild configuration is: ```js const nodeConfig = { source: { entry: { index: './src/index.server.js', }, }, output: { target: 'node', }, resolve: { alias: { '@common': './src/common', '@common1': './src/ssr/common1', }, }, }; ``` --- url: /config/dev/asset-prefix.md --- # dev.assetPrefix * **Type:** `boolean | string | 'auto'` * **Default:** [server.base](/config/server/base.md) Set the URL prefix of static assets in [development mode](/config/mode.md). `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 development mode. In the production mode, please use the [output.assetPrefix](/config/output/asset-prefix.md) to set the URL prefix. ## Default value The default value of `dev.assetPrefix` is the same as [server.base](/config/server/base.md). When `server.base` is `/foo`, `index.html` and other static assets can be accessed through `http://localhost:3000/foo/`. It should be noted that when customizing the `dev.assetPrefix` option, if you want static assets to be normally accessible through the Rsbuild dev server, `dev.assetPrefix` should contain the same URL prefix as `server.base`, such as: ```ts export default { dev: { assetPrefix: '/foo/bar/', }, server: { base: '/foo', }, }; ``` ## Boolean type If `assetPrefix` is set to `true`, the URL prefix will be `http://localhost:<port>/`: ```js export default { dev: { assetPrefix: true, }, }; ``` The resource URL loaded in the browser is as follows: ```html <script defer src="http://localhost:3000/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 a `string` type, the string will be used as a prefix and automatically appended to the static resource URL. * For example, set to a path relative to the root directory: ```js export default { dev: { assetPrefix: '/example/', }, }; ``` The resource URL loaded in the browser is as follows: ```html <script defer src="http://localhost:3000/example/static/js/index.js"></script> ``` * For example, set to a complete URL: ```js export default { dev: { assetPrefix: 'https://example.com/assets/', }, }; ``` The resource URL loaded in the browser is as follows: ```html <script defer src="https://example.com/assets/static/js/index.js"></script> ``` ### Port placeholder The port number that Rsbuild server listens on may change. For example, if the port is in use, Rsbuild will automatically increment the port number until it finds an available port. To avoid `dev.assetPrefix` becoming invalid due to port changes, you can use one of the following methods: * Enable [server.strictPort](/config/server/strict-port.md). * Use the `<port>` placeholder to refer to the current port number. Rsbuild will replace the placeholder with the actual port number it is listening on. ```ts title="rsbuild.config.ts" export default { dev: { assetPrefix: 'http://localhost:<port>/', }, }; ``` ## Path types assetPrefix can be set to the following types of paths: * **absolute path**: This is the most common practice, can be specific server paths, like `/assets/`. * **'auto'**: Rspack will automatically calculate the path and generate relative paths based on file location. :::tip It's not recommended to set assetPrefix as a relative path, such as `'./assets/'`. This is because when assets are at different path depths, using relative paths may cause assets to load incorrectly. ::: ## Compare with `publicPath` The functionality of `dev.assetPrefix` is basically the same as the [output.publicPath](https://rspack.dev/config/output#outputpublicpath) config in Rspack. The differences from the native configuration are as follows: * `dev.assetPrefix` only takes effect in development mode. * `dev.assetPrefix` default value is the same as [server.base](/config/server/base.md). * `dev.assetPrefix` automatically appends a trailing `/` by default. * The value of `dev.assetPrefix` is written to the [process.env.ASSET\_PREFIX](/guide/advanced/env-vars.md#processenvasset_prefix) environment variable (can only be accessed in client code). ## Dynamic asset prefix Use the `__webpack_public_path__` variable provided by Rspack to dynamically set the URL prefix of static assets in JavaScript code. See [Rspack - Dynamically set publicPath](https://rspack.dev/config/output#dynamically-set-publicpath). --- url: /config/dev/cli-shortcuts.md --- # dev.cliShortcuts * **Type:** ```ts type CliShortcuts = | boolean | { help?: boolean; custom?: (shortcuts: CliShortcut[]) => CliShortcut[]; }; ``` * **Default:** `true` when using Rsbuild CLI, `false` otherwise. * **Version:** `>= 1.0.11` Whether to enable CLI shortcuts. ## All shortcuts Press `h + Enter` to show all shortcuts: ``` Shortcuts: c + enter clear console o + enter open in browser q + enter quit process r + enter restart server u + enter show urls ``` ## Example * Enable: ```js export default { dev: { cliShortcuts: true, }, }; ``` * Disable: ```js export default { dev: { cliShortcuts: false, }, }; ``` ## Custom shortcuts `custom` option can be used to custom shortcuts, the value is a function that receives the default shortcuts array and returns a new shortcuts array. * Add custom shortcuts: ```js export default { dev: { cliShortcuts: { custom: (shortcuts) => { return [ ...shortcuts, { key: 's', description: 'say hello', action: () => { console.log('hello world!'); }, }, ]; }, }, }, }; ``` * Disable some shortcuts: ```js export default { dev: { cliShortcuts: { custom: (shortcuts) => { return shortcuts.filter((shortcut) => shortcut.key !== 'o'); }, }, }, }; ``` ## Print help `help` option can be used to control whether to print the help hint when the server is started: ```bash ➜ press h + enter to show shortcuts ``` * Disable: ```js export default { dev: { cliShortcuts: { help: false, }, }, }; ``` --- url: /config/dev/client.md --- # dev.client Configure the client code injected by Rsbuild during the development process. This can be used to set the WebSocket URL for HMR. * **Type:** ```ts type Client = { // The protocol name for the WebSocket request protocol?: 'ws' | 'wss'; // The path for the WebSocket request path?: string; // The port number for the WebSocket request port?: string | number; // The host for the WebSocket request host?: string; // The maximum number of reconnection attempts after a WebSocket request is disconnected. reconnect?: number; // Whether to display an error overlay in the browser when a compilation error occurs overlay?: boolean; }; ``` * **Default:** ```js const defaultConfig = { path: '/rsbuild-hmr', // By default it is set to "location.port" port: '', // By default it is set to "location.hostname" host: '', // By default it is set to "location.protocol === 'https:' ? 'wss' : 'ws'"" protocol: undefined, reconnect: 100, overlay: true, }; ``` ## Configure WebSocket URL By default, when you start the dev server and visit the `http://localhost:3000/`, a WebSocket request is made to `ws://localhost:3000/rsbuild-hmr`, establishing a connection between the page and the dev server. In some development scenarios, you may need to adjust the WebSocket URL to ensure that the WebSocket request can connect correctly. For example, if you are developing using a proxy tool, you may actually be accessing an online domain. In this case, you can manually configure `dev.client` to point the WebSocket URL to your local dev server. Below is an example where the WebSocket request URL is `ws://127.0.0.1:3000/rsbuild-hmr`: ```ts title="rsbuild.config.ts" export default { dev: { client: { protocol: 'ws', // Usually `127.0.0.1` is used to avoid cross-origin requests being blocked by the browser host: '127.0.0.1', port: 3000, }, }, }; ``` ### Port placeholder The port number that Rsbuild server listens on may change. For example, if the port is in use, Rsbuild will automatically increment the port number until it finds an available port. To avoid `client.port` becoming invalid due to port changes, you can use one of the following methods: * Enable [server.strictPort](/config/server/strict-port.md). * Use the `<port>` placeholder to refer to the current port number. Rsbuild will replace the placeholder with the actual port number it is listening on. ```ts title="rsbuild.config.ts" export default { dev: { client: { port: '<port>', }, }, }; ``` ## hot-update files During the HMR process, the page will make GET requests to get hot-update files, including `*.hot-update.json` and `*.hot-update.js`. These files contain the necessary information for hot updates, such as the updated modules and their code. Hot-update files are considered to be static assets. If you need to configure the URL for hot-update files, please use the [dev.assetPrefix](/config/dev/asset-prefix.md) option. ## Error overlay The `dev.client.overlay` option allows you to choose whether or not to enable the error overlay feature. By default, Rsbuild will display an error overlay in the browser when a compilation error occurs, providing error messages and stacks: ![error overlay](https://assets.rspack.dev/rsbuild/assets/rsbuild-error-overlay.png) To disable the error overlay, set it to `false`: ```ts title="rsbuild.config.ts" export default { dev: { client: { overlay: false, }, }, }; ``` :::tip The error overlay feature requires the current browser to support [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components). If the browser does not support it, the overlay will not be displayed. ::: --- url: /config/dev/hmr.md --- # dev.hmr * **Type:** `boolean` * **Default:** `true` Whether to enable Hot Module Replacement. Please refer to [Hot Module Replacement](/guide/advanced/hmr.md) for more information. > You can configure the HMR behavior of the client code via [dev.client](/config/dev/client.md). ## Disabling HMR If `dev.hmr` is set to `false`, HMR and react-refresh will be disabled and Rsbuild will automatically fall back to [dev.liveReload](/config/dev/live-reload.md). ```js export default { dev: { hmr: false, }, }; ``` --- url: /config/dev/lazy-compilation.md --- # dev.lazyCompilation * **Type:** ```ts type LazyCompilationOptions = | boolean | { /** * Enable lazy compilation for entries. */ entries?: boolean; /** * Enable lazy compilation for dynamic imports. */ imports?: boolean; /** * Specify which imported modules should be lazily compiled. */ test?: RegExp | ((m: Module) => boolean); /** * The path to a custom runtime code that overrides the default lazy compilation client. */ client?: string; /** * Tells the client the server URL that needs to be requested. */ serverUrl?: string; }; ``` * **Default:** `false` * **Version:** `>= 1.3.0` Enable lazy compilation (compilation on demand), implemented based on Rspack's [lazy compilation](https://rspack.dev/guide/features/lazy-compilation) feature. ## Introduction Although Rspack itself has good performance, the overall build time can still be less than ideal when building applications with a large number of modules. This is because the modules in the application need to be compiled by various loaders, such as `postcss-loader`, `sass-loader`, `vue-loader`, etc., which introduce additional compilation overhead. Lazy compilation is an effective strategy to improve the startup performance of the development phase. Instead of compiling all modules at initialization, it compiles modules on demand as they're needed. This means that developers can quickly see the application running when starting the dev server, and build the required modules in batches. By compiling on demand, unnecessary compilation time can be reduced. As the project scales up, compilation time does not significantly increase, which greatly enhances the development experience. :::tip Lazy compilation is only effective for dev builds and does not affect production builds. ::: ## Example ### Enable lazy compilation ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: true, }, }; ``` This is equivalent to the following configuration: ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: { imports: true, entries: true, }, }, }; ``` ### Entry modules Use `lazyCompilation.entries` to control whether to lazily compile entry modules: ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: { entries: true, }, }, }; ``` With the `entries` option enabled, Rsbuild will not compile all pages when you start the dev server. Instead, it will only compile a specific page when you visit it. When lazily compiling entry modules, please note: * It only applies to multi-page applications (MPA) and does not optimize single-page applications (SPA). * When you visit a page, you need to wait for the page to finish compiling before you can see its content. ### Async modules Use `lazyCompilation.imports` to control whether to lazily compile [dynamic imported](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) modules. ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: { imports: true, }, }, }; ``` When the `imports` option is enabled, all async modules will only be compiled when requested. If your project is a single-page application (SPA) and you have split the routes using dynamic import, this will significantly speed up the startup time. ### Server URL Use [lazyCompilation.serverUrl](https://rspack.dev/config/experiments#lazycompilationserverurl) to tell the client the server URL that needs to be requested. ```ts title="rsbuild.config.ts" export default { dev: { lazyCompilation: { serverUrl: 'http://localhost:<port>', }, }, }; ``` :::tip Rsbuild will replace the `<port>` placeholder with the actual port number the server is listening on. ::: --- url: /config/dev/live-reload.md --- # dev.liveReload * **Type:** `boolean` * **Default:** `true` Whether to reload the page when source files are changed. By default, Rsbuild uses HMR as the preferred method to update modules. If HMR is disabled or cannot be used in certain scenarios, it will automatically fallback to liveReload. Please refer to [Hot Module Replacement](/guide/advanced/hmr.md) for more information. ## Disabling live reload To disable live reload, set both `dev.hmr` and `dev.liveReload` to `false`. Then, no WebSocket requests will be made to the dev server on the page, and the page will not automatically refresh when file change. ```js export default { dev: { hmr: false, liveReload: false, }, }; ``` --- url: /config/dev/progress-bar.md --- # dev.progressBar * **Type:** ```ts 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. ```js export default { dev: { progressBar: true, }, }; ``` * **Example:** Disable the progress bar. ```js export default { dev: { progressBar: false, }, }; ``` * **Example:** Modify the progress bar `id` To modify the text displayed on the left side of the progress bar, set the `id` option: ```ts export default { dev: { progressBar: { id: 'Some Text', }, }, }; ``` --- url: /config/dev/setup-middlewares.md --- # dev.setupMiddlewares * **Type:** ```ts title="rsbuild.config.ts" type SetupMiddlewaresServer = { sockWrite: ( type: string, data?: string | boolean | Record<string, any>, ) => void; environments: EnvironmentAPI; }; type SetupMiddlewares = Array< ( middlewares: { unshift: (...handlers: RequestHandler[]) => void; push: (...handlers: RequestHandler[]) => void; }, server: SetupMiddlewaresServer, ) => void >; ``` * **Default:** `undefined` Provides the ability to execute a custom function and apply custom middlewares. ## Execution order The order among several different types of middleware is: `unshift` => internal middlewares => `push`. ```ts title="rsbuild.config.ts" export default { dev: { setupMiddlewares: [ (middlewares, server) => { middlewares.unshift((req, res, next) => { console.log('first'); next(); }); middlewares.push((req, res, next) => { console.log('last'); next(); }); }, ], }, }; ``` ## Server API In the `setupMiddlewares` function, you can access the `server` object, which provides some server APIs. ### sockWrite `sockWrite` allows middlewares to send 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. ```ts title="rsbuild.config.ts" export default { dev: { setupMiddlewares: [ (middlewares, server) => { if (someCondition) { server.sockWrite('static-changed'); } }, ], }, }; ``` > Sending `content-changed` and `static-changed` have the same effect. Since `content-changed` has been deprecated, please use `static-changed` instead. ### environments `environments` includes Rsbuild's [environment API](/api/javascript-api/environment-api.md#environment-api), which allows you to get the build outputs information for a specific environment in the server side. ```ts title="rsbuild.config.ts" export default { dev: { setupMiddlewares: [ (middlewares, server) => { middlewares.unshift(async (req, _res, next) => { const webStats = await server.environments.web.getStats(); console.log(webStats.toJson({ all: false })); next(); }); }, ], }, }; ``` --- url: /config/dev/watch-files.md --- # dev.watchFiles * **Type:** ```ts type WatchFiles = { paths: string | string[]; type?: 'reload-page' | 'reload-server'; // watch options for chokidar options?: ChokidarOptions; }; type WatchFilesConfig = WatchFiles | WatchFiles[]; ``` * **Default:** `undefined` Watch specified files and directories for changes. When a file change is detected, it can trigger a page reload or restart the dev server. ## paths * **Type:** `string | string[]` * **Default:** `undefined` Paths of the files or directories to be watched, supports glob syntax. It can be a single path or an array of multiple paths. * Watching a single file: ```js export default { dev: { watchFiles: { paths: 'public/demo.txt', }, }, }; ``` * Using glob to match multiple files: ```js export default { dev: { watchFiles: { paths: 'src/**/*.txt', }, }, }; ``` * Watching multiple file paths: ```js export default { dev: { watchFiles: { paths: ['src/**/*.txt', 'public/**/*'], }, }, }; ``` ## type * **Type:** `'reload-page' | 'reload-server'` * **Default:** `'reload-page'` Specifies whether to trigger a page reload or restart the dev server when a file changes. ### reload-page `reload-page` means that when a file changes, the page opened in the browser will automatically reload. If the type is not explicitly specified, Rsbuild will default to the `reload-page` behavior. This can be used to watch changes to static assets, such as files in the `public` directory. ```js export default { dev: { watchFiles: { type: 'reload-page', paths: 'public/**/*', }, }, }; ``` > If both [dev.hmr](/config/dev/hmr.md) and [dev.liveReload](/config/dev/live-reload.md) are set to `false`, the page will not automatically reload. ### reload-server `reload-server` means that the dev server will automatically restart when a file changes. This can be used to watch changes to configuration files, such as modules imported by the `rsbuild.config.ts` file. For example, if you maintain some common configuration files in the `config` directory, such as `common.ts`, you want the dev server to automatically restart when these files change. Example configuration: ```ts title="rsbuild.config.ts" import { commonConfig } from './config/common'; export default { ...commonConfig, dev: { watchFiles: { type: 'reload-server', paths: ['./config/*.ts'], }, }, }; ``` It should be noted that the reload-server functionality is provided by Rsbuild CLI. If you are using a custom server or an upper-layer framework based on the Rsbuild, this configuration is currently not supported. ## options * **Type:** `ChokidarOptions` * **Default:** `undefined` `watchFiles` is implemented based on [chokidar v4](https://github.com/paulmillr/chokidar#api), and you can pass chokidar options through `options`. ```js export default { dev: { watchFiles: { paths: 'src/**/*.txt', options: { usePolling: false, }, }, }, }; ``` ## Notes `watchFiles` is not applicable for watching build dependency files. When an Rsbuild build starts, the underlying Rspack will automatically watches all build dependencies. Any changes to these files will trigger a new build. If you want to prevent some files from triggering a rebuild when they change, you can use Rspack's [watchOptions.ignored](https://rspack.dev/config/watch#watchoptionsignored) configuration item. > See [HMR - File Watching](/guide/advanced/hmr.md#file-watching) for more details. --- url: /config/dev/write-to-disk.md --- # dev.writeToDisk * **Type:** `boolean | ((filename: string) => boolean)` * **Default:** `false` Controls whether the build output from development mode is written to disk. :::tip In development mode, Rsbuild stores the build outputs in memory on the dev server by default, rather than writing then to disk. This can reduce the overhead of fs operations. You can refer to [View Static Assets](/guide/basic/server.md#view-static-assets) to view all static assets generated in the current build. ::: ## Writing to disk You can choose to write the build output to disk, which is usually used for inspecting the content of the build output or configuring proxy rules for static assets. Simply set the `dev.writeToDisk` option to `true`: ```ts export default { dev: { writeToDisk: true, }, }; ``` :::tip Setting `writeToDisk: true` is used for viewing the build output from development mode. It does not change the behavior of the dev server. When accessing files through a browser, the dev server will still read the file content from memory. ::: ## Matching specific files You can also set `dev.writeToDisk` to a function to match only certain files. When the function returns `false`, the file will not be written; when it returns `true`, the file will be written to disk. For example, to write files to disk while excluding hot-update temporary files: ```ts export default { dev: { writeToDisk: (file) => !file.includes('.hot-update.'), }, }; ``` --- url: /config/resolve/alias-strategy.md --- # resolve.aliasStrategy * **Type:** `'prefer-tsconfig' | 'prefer-alias'` * **Default:** `'prefer-tsconfig'` * **Version:** `>=1.1.7` Set the strategy for path alias resolution, to control the priority relationship between the `paths` option in `tsconfig.json` and the [resolve.alias](/config/resolve/alias.md) option of Rsbuild. :::tip See [Path aliases](/guide/advanced/alias.md) for the differences between the `paths` option in `tsconfig.json` and the `resolve.alias` option of Rsbuild. ::: ## prefer-tsconfig By default, `resolve.aliasStrategy` is set to `'prefer-tsconfig'`. In this case, both the `paths` option in `tsconfig.json` and the `alias` option in the bundler will take effect, but the `paths` option in tsconfig has a higher priority. For example, if the following configurations are set at the same time: * tsconfig paths: ```json title="tsconfig.json" { "compilerOptions": { "paths": { "@common/*": ["./src/common-1/*"] } } } ``` * `resolve.alias`: ```ts export default { resolve: { alias: { '@common': './src/common-2', '@utils': './src/utils', }, }, }; ``` Since the tsconfig paths have a higher priority, the following will happen: * `@common` will use the value defined in tsconfig paths, pointing to `./src/common-1` * `@utils` will use the value defined in `resolve.alias`, pointing to `./src/utils` ## prefer-alias If the value of `resolve.aliasStrategy` is set to `prefer-alias`, the `paths` option in `tsconfig.json` will only be used to provide TypeScript type definitions and will not affect the bundling result. In this case, the bundler will only read the `alias` option as the path alias. ```ts export default { resolve: { aliasStrategy: 'prefer-alias', }, }; ``` For example, if the following configurations are set at the same time: * tsconfig paths: ```json title="tsconfig.json" { "compilerOptions": { "paths": { "@common/*": ["./src/common-1/*"], "@utils/*": ["./src/utils/*"] } } } ``` * `resolve.alias`: ```ts export default { resolve: { alias: { '@common': './src/common-2', }, }, }; ``` Since the tsconfig paths are only used to provide types, only the `@common` alias will be effective, pointing to the `./src/common-2` directory. In most cases, you don't need to use `prefer-alias`, but you can consider using it if you need to dynamically generate some alias configurations. For example, generating the `alias` option based on environment variables: ```ts export default { resolve: { alias: { '@common': process.env.NODE_ENV === 'production' ? './src/common-prod' : './src/common-dev', }, }, }; ``` --- url: /config/resolve/alias.md --- # resolve.alias * **Type:** ```ts type Alias = Record<string, string | false | (string | false)[]> | Function; ``` * **Default:** ```ts const defaultAlias = { '@swc/helpers': path.dirname(require.resolve('@swc/helpers/package.json')), }; ``` * **Version:** `>=1.1.7` Set the alias for the module path, which is used to simplify the import path or redirect the module reference. For TypeScript projects, you only need to configure [compilerOptions.paths](https://typescriptlang.org/tsconfig#paths) in the `tsconfig.json` file. The Rsbuild will automatically recognize it, so there is no need to configure the `resolve.alias` option separately. For more details, please refer to [Path Aliases](/guide/advanced/alias.md). :::tip In versions prior to Rsbuild 1.1.7, you can use the `source.alias` to set alias, but it will be removed in the next major version. ::: ## Basic usage `resolve.alias` can be an object, the `key` is the module path in the source code to be replaced, and the `value` is the target path to which the module will be mapped. ```ts title="rsbuild.config.ts" export default { resolve: { alias: { '@common': './src/common', }, }, }; ``` With the above configuration, if `@common/Foo.tsx` is imported in the code, it will be mapped to the `<project-root>/src/common/Foo.tsx`. ## Function usage The `resolve.alias` can be a function, it will accept the previous alias object, and you can modify it. ```ts title="rsbuild.config.ts" export default { resolve: { alias: (alias) => { alias['@common'] = './src/common'; }, }, }; ``` To remove the built-in `@swc/helpers` alias, delete it in the function: ```ts title="rsbuild.config.ts" export default { resolve: { alias: (alias) => { delete alias['@swc/helpers']; }, }, }; ``` You can also return a new object as the final result in the function, which will replace the preset alias object. ```ts title="rsbuild.config.ts" export default { resolve: { alias: (alias) => { return { '@common': './src/common', }; }, }, }; ``` ## Differences with Rspack Rsbuild's `resolve.alias` is similar to Rspack's [resolve.alias](https://rspack.dev/config/resolve#resolvealias) configuration, but there are some differences: * If the value of `resolve.alias` is a relative path, Rsbuild will automatically convert it to an absolute path to ensure that the path is relative to the project root. ```ts title="rsbuild.config.ts" export default { resolve: { alias: { // Will be converted to `<project-root>/src/common` '@common': './src/common', }, }, }; ``` * Rsbuild additionally supports the function type. ## Set by environment When you build for multiple [environments](/config/environments.md), you can set different alias for each environment: For example, set different alias for `web` and `node` environments: ```ts title="rsbuild.config.ts" export default { environments: { web: { resolve: { alias: { '@common': './src/web/common', }, }, output: { target: 'web', }, }, node: { resolve: { alias: { '@common': './src/node/common', }, }, output: { target: 'node', }, }, }, }; ``` ## Exact matching By default, `resolve.alias` will automatically match sub-paths, for example, with the following configuration: ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { resolve: { alias: { '@common': './src/common', }, }, }; ``` It will match as follows: ```ts import a from '@common'; // resolved to `./src/common` import b from '@common/util'; // resolved to `./src/common/util` ``` You can add the `$` symbol to enable exact matching, which will not automatically match sub-paths. ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { resolve: { alias: { '@common$': './src/common', }, }, }; ``` It will match as follows: ```ts import a from '@common'; // resolved to `./src/common` import b from '@common/util'; // remains as `@common/util` ``` ## Handling npm packages You can use `alias` to resolve an npm package to a specific directory. For example, if multiple versions of the `react` are installed in the project, you can alias `react` to the version installed in the root `node_modules` directory to avoid bundling multiple copies of the React code. ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { resolve: { alias: { react: path.resolve(__dirname, './node_modules/react'), }, }, }; ``` When using alias to handle npm packages, please be aware of whether different major versions of the package are being used in the project. For example, if a module or npm dependency in your project uses the React 19 API, and you alias React to version 17, the module will not be able to reference the React 19 API, resulting in code exceptions. ## Handling loader `resolve.alias` does not support creating aliases for loaders. To create aliases for loaders, use Rspack's [resolveLoader](https://rspack.dev/config/resolve-loader) configuration. ```ts title="rsbuild.config.ts" export default { tools: { rspack: { resolveLoader: { alias: { 'amazing-loader': require.resolve('path-to-your-amazing-loader'), }, }, }, }, }; ``` --- url: /config/resolve/dedupe.md --- # resolve.dedupe * **Type:** `string[]` * **Default:** `undefined` * **Version:** `>= 1.1.7` Force Rsbuild to resolve the specified packages from project root, which is useful for deduplicating packages and reducing the bundle size. ## Example For example, assume your project is based on React 19, and you are using the `foo` package that depends on React 17, then your project will have two different versions of the React: ``` app/ ├── src/ └── node_modules/ ├── foo/ │ └── node_modules/ │ ├── react (v17) │ └── react-dom (v17) ├── react (v19) └── react-dom (v19) ``` In this case, you can use the `resolve.dedupe` config to remove the duplicate React packages, and resolve all `react` and `react-dom` packages to `/node_modules/react` and `/node_modules/react-dom`: ```ts title="rsbuild.config.ts" export default defineConfig({ resolve: { dedupe: ['react', 'react-dom'], }, }); ``` Note that using `resolve.dedupe` to unify different major versions of a package, it may cause some packages to fail because they may depend on specific versions of APIs or features. For example, if `foo` depends on a React 17-specific API or feature, then unifying React 17 and React 19 with React 19 using `resolve.dedupe` may cause `foo` to fail. ## How it works `resolve.dedupe` is implemented based on [resolve.alias](/config/resolve/alias.md), it will get the path of the specified package through `require.resolve` in the project root directory and set it to the alias. In the above example, `resolve.dedupe` will be converted to the following alias config: ```ts const alias = { react: '/app/node_modules/react', 'react-dom': '/app/node_modules/react-dom', }; ``` The alias generated by `resolve.dedupe` will be merged with the configured `resolve.alias` in the project, and the `resolve.alias` config will take precedence when the keys are the same. --- url: /config/resolve/extensions.md --- # resolve.extensions * **Type:** `string[]` * **Default:** `['.ts', '.tsx', '.mjs', '.js', '.jsx', '.json']` * **Version:** `>= 1.1.9` Automatically resolve file extensions when importing modules. This means you can import files without explicitly writing their extensions. For example, if importing `'./index'`, Rsbuild will try to resolve using the following order * `./index.ts` * `./index.tsx` * `./index.mjs` * `./index.js` * `./index.jsx` * `./index.json` :::tip It is not recommended to omit `.vue` or other custom import extension names using `resolve.extensions`, as this may interfere IDE and type support. ::: ## Example The value of `resolve.extensions` overrides the default value of Rsbuild: ```ts title="rsbuild.config.ts" export default { resolve: { extensions: ['.ts', '.tsx', '.js'], }, }; ``` ## Rspack config `resolve.extensions` is provided by Rspack, see [Rspack - resolve.extensions](https://rspack.dev/config/resolve#resolveextensions). You can also configure it using [tools.rspack](/config/tools/rspack.md): ```ts title="rsbuild.config.ts" export default { tools: { rspack: { resolve: { extensions: ['.ts', '.tsx', '.js'], }, }, }, }; ``` The difference between them is how the configuration is merged. `tools.rspack` merges the configuration arrays based on [webpack-merge](https://github.com/survivejs/webpack-merge), which means `tools.rspack.resolve.extensions` will merge with the default value of Rsbuild, rather than overriding it. --- url: /config/source/assets-include.md --- # source.assetsInclude * **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `undefined` * **Version:** `>= 1.0.18` Include additional files that should be treated as static assets. By default, Rsbuild treats common image, font, audio, and video files as static assets. Through the `source.assetsInclude` config, you can specify additional file types that should be treated as static assets. These added static assets are processed using the same rules as the built-in supported static assets, see [Static Assets](/guide/basic/static-assets.md). The value of `source.assetsInclude` is the same as the `test` option in Rspack loader. It can be a regular expression, string, array, logical condition, etc. For more details, see [Rspack RuleSetCondition](https://rspack.dev/config/module#condition). ## Example * Treating `.json5` files as static assets: ```ts export default defineConfig({ source: { assetsInclude: /\.json5$/, }, }); ``` * Treating multiple file types as static assets: ```ts export default defineConfig({ source: { assetsInclude: [/\.json5$/, /\.pdf$/], }, }); ``` * Treating specific files as static assets: ```ts import path from 'node:path'; export default defineConfig({ source: { assetsInclude: path.resolve(__dirname, 'src/assets/foo.json5'), }, }); ``` --- url: /config/source/decorators.md --- # source.decorators * **Type:** ```ts type Decorators = { version?: 'legacy' | '2022-03'; }; ``` Used to configure the decorators syntax. ## decorators.version * **Type:** `'legacy' | '2022-03'` * **Default:** `'2022-03'` Specify the decorator syntax version to be used. If you want to know the differences between different decorators versions, you can refer to: [How does this proposal compare to other versions of decorators?](https://github.com/tc39/proposal-decorators?tab=readme-ov-file#how-does-this-proposal-compare-to-other-versions-of-decorators) ### 2022-03 `2022-03` corresponds to the Stage 3 decorator proposal, equivalent to the decorator syntax supported by TypeScript 5.0 by default. ```ts title="rsbuild.config.ts" export default { source: { decorators: { version: '2022-03', }, }, }; ``` Reference documentation: * [JavaScript meta programming with the 2022-03 decorators API](https://2ality.com/2022/10/javascript-decorators.html) * [TypeScript 5.0 Decorators](https://typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#decorators) ### legacy Equivalent to TypeScript's `experimentalDecorators: true`. ```ts title="rsbuild.config.ts" export default { source: { decorators: { version: 'legacy', }, }, }; ``` Reference documentation: * [A Complete Guide to TypeScript Decorators](https://mirone.me/a-complete-guide-to-typescript-decorator/) * [TypeScript Decorators](https://typescriptlang.org/docs/handbook/decorators.html) --- url: /config/source/define.md --- # source.define * **Type:** `Record<string, unknown>` * **Default:** `{}` Replaces variables in your code with other values or expressions at compile time. This can be useful for allowing different behavior between development builds and production builds. Each key passed into options is an identifier or multiple identifiers joined with `.`. * If the value is a string it will be used as a code fragment. * If the value isn't a string, it will be stringified (including functions). * If the value is an object all keys are defined the same way. * If you prefix typeof to the key, it's only defined for typeof calls. > For more usage, please refer to [Using define](/guide/advanced/env-vars.md#using-define) and [Rspack - DefinePlugin](https://rspack.dev/plugins/webpack/define-plugin). ## Example ```js export default { source: { define: { PRODUCTION: JSON.stringify(true), VERSION: JSON.stringify('5fa3b9'), BROWSER_SUPPORTS_HTML5: true, TWO: '1 + 1', 'typeof window': JSON.stringify('object'), 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'import.meta.test': JSON.stringify('foo'), }, }, }; ``` Expressions will be replaced with the corresponding code fragments: ```js const foo = TWO; // ⬇️ Turn into being... const foo = 1 + 1; ``` --- url: /config/source/entry.md --- # source.entry * **Type:** ```ts type Entry = Record< string, string | string[] | (Rspack.EntryDescription & { html?: boolean }) >; ``` * **Default:** ```ts const defaultEntry = { // Rsbuild also supports other suffixes by default, such as ts, tsx, jsx, mts, cts, mjs, cjs index: './src/index.js', }; ``` Used to set the entry modules for building. The usage of `source.entry` is similar to the `entry` option in [Rspack](https://rspack.dev/config/entry). The main difference is that Rsbuild will register [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin) for each entry in `source.entry` to generate the corresponding HTML files. * **Example:** ```ts title="rsbuild.config.ts" export default { source: { entry: { foo: './src/pages/foo/index.ts', bar: './src/pages/bar/index.ts', }, }, }; ``` The generated directory structure is as follows: ``` . ├── foo.html ├── bar.html └── static ├── css │ ├── foo.css │ └── bar.css └── js ├── foo.js └── bar.js ``` If you do not need to generate HTML files, you can set [tools.htmlPlugin](/config/tools/html-plugin.md) to `false` to disable this behavior. ## Description object `source.entry` also supports Rspack's entry description object. For example: ```ts title="rsbuild.config.ts" export default { source: { entry: { foo: { import: './src/foo.js', runtime: 'foo', }, bar: { import: './src/bar.js', runtime: 'bar', }, }, }, }; ``` Rsbuild has added an `html` attribute for the description object, which is used to control whether an HTML file is generated. For example, the `bar` entry does not generate an HTML file: ```ts title="rsbuild.config.ts" export default { source: { entry: { foo: './src/foo.js', bar: { import: './src/bar.js', html: false, }, }, }, }; ``` > For the complete usage of the description object, please refer to [Rspack - Entry Description Object](https://rspack.dev/config/entry#entry-description-object). ## Set by environment When you build for multiple [environments](/config/environments.md), you can set different entry for each environment: For example, set different entry for `web` and `node` environments: ```ts title="rsbuild.config.ts" export default { environments: { web: { source: { entry: { index: './src/index.client.js', }, }, output: { target: 'web', }, }, node: { source: { entry: { index: './src/index.server.js', }, }, output: { target: 'node', }, }, }, }; ``` ## Asynchronous setting To set entry asynchronously, for example, use [glob](https://npmjs.com/package/glob) to scan the directory, you can export an async function in `rsbuild.config.ts`: ```ts title="rsbuild.config.ts" import path from 'node:path'; import { glob } from 'glob'; import { defineConfig } from '@rsbuild/core'; export default defineConfig(async () => { const entryFiles = await glob('./src/**/main.{ts,tsx,js,jsx}'); const entry = Object.fromEntries( entryFiles.map((file) => { const entryName = path.basename(path.dirname(file)); return [entryName, `./${file}`]; }), ); return { source: { entry: entry, }, }; }); ``` --- url: /config/source/exclude.md --- # source.exclude * **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `[]` Exclude JavaScript or TypeScript files that do not need to be compiled by [SWC](/guide/configuration/swc.md). ## Usage The usage of `source.exclude` is consistent with [Rule.exclude](https://rspack.dev/config/module#ruleexclude) in Rspack, which supports passing in strings or regular expressions to match the module path. For example: ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { source: { exclude: [path.resolve(__dirname, 'src/module-a'), /src\/module-b/], }, }; ``` > Refer to [source.include](/config/source/include.md) to learn more. ## Exclude from bundling `source.exclude` is used to specify JavaScript/TypeScript files that do not need to be compiled. This means that these files will not be translated by SWC, but the referenced files will still be bundled into the outputs. If you want certain files to be excluded and not bundled into the outputs, you can use Rspack's [IgnorePlugin](https://rspack.dev/plugins/webpack/ignore-plugin). ```ts title="rsbuild.config.ts" export default { tools: { rspack: (config, { rspack }) => { config.plugins?.push( new rspack.IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/, }), ); return config; }, }, }; ``` --- url: /config/source/include.md --- # source.include * **Type:** [Rspack.RuleSetCondition](https://rspack.dev/config/module#condition) Specify additional JavaScript files that need to be compiled by [SWC](/guide/configuration/swc.md). ## Default value To avoid double compilation, by default, Rsbuild's built-in [swc-loader](https://rspack.dev/guide/features/builtin-swc-loader) compiles the following files: * TypeScript and JSX files in any directory, matching file extensions `.ts`, `.tsx`, `.jsx`, `.mts`, `.cts`. * JavaScript files in the [root](/config/root.md) directory, excluding the `node_modules` directory, matching file extensions `.js`, `.mjs`, `.cjs`. The default value of `source.include` can be expressed as: ```ts const defaultInclude = [ { and: [rootPath, { not: /[\\/]node_modules[\\/]/ }], }, /\.(?:ts|tsx|jsx|mts|cts)$/, ]; ``` ## Usage Through the `source.include` config, you can specify directories or modules that need to be compiled by Rsbuild. The usage of `source.include` is consistent with [Rule.include](https://rspack.dev/config/module#ruleinclude) in Rspack, which supports passing in strings or regular expressions to match the module path. For example: ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { source: { include: [path.resolve(__dirname, '../other-dir')], }, }; ``` ## Compile npm packages A typical usage scenario is to compile npm packages under node\_modules, because some third-party dependencies have ESNext syntax, which may cause them to fail to run on low-version browsers. You can solve the problem by using this config to specify the dependencies that need to be compiled. :::tip If you are unsure which third-party dependencies in node\_modules contain ESNext syntax, you can use the [@rsbuild/plugin-check-syntax](https://github.com/rspack-contrib/rsbuild-plugin-check-syntax) for checking. The plugin can help you find the modules that contain ESNext syntax. ::: Take `query-string` as an example, you can add the following config: ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { source: { include: [ // Method 1: // Match by regular expression // All paths containing `node_modules/query-string/` will be matched /node_modules[\\/]query-string[\\/]/, // Method 2: // First get the path of the module by require.resolve // Then pass path.dirname to point to the corresponding directory path.dirname(require.resolve('query-string')), ], }, }; ``` The above two methods match the absolute paths of files using "path prefixes" and "regular expressions" respectively. It is worth noting that all referenced modules in the project will be matched. Therefore, you should avoid using overly loose values for matching to prevent compilation performance issues or compilation errors. :::tip In the regular expression example, we use `[\\/]` to match the path separator because different operating systems use different path separators. Using `[\\/]` ensures that the paths can be matched on macOS, Linux and Windows. ::: ## Compile sub dependencies When you compile an npm package via `source.include`, Rsbuild will only compile the matching module by default, not the **Sub Dependencies** of the module. Take `query-string` for example, it depends on the `decode-uri-component` package, which also has ESNext code, so you need to add the `decode-uri-component` package to `source.include` as well. ```ts title="rsbuild.config.ts" export default { source: { include: [ /node_modules[\\/]query-string[\\/]/, /node_modules[\\/]decode-uri-component[\\/]/, ], }, }; ``` ## Compile libraries in monorepo When developing in Monorepo, if you need to refer to the source code of other libraries in Monorepo, you can add the corresponding library to `source.include`: ```ts title="rsbuild.config.ts" import path from 'node:path'; const packagesDir = path.resolve(__dirname, '../../packages'); export default { source: { include: [ // Compile all files in Monorepo's package directory // It is recommended to exclude the node_modules { and: [packagesDir, { not: /[\\/]node_modules[\\/]/ }], }, ], }, }; ``` ## Matching symlink If you match a module that is symlinked to the current project, then you need to match the **real path** of the module, not the symlinked path. For example, if you symlink the `packages/foo` path in Monorepo to the `node_modules/foo` path of the current project, you need to match the `packages/foo` path, not the `node_modules/foo` path. ## Compile node\_modules In general, `source.include` should not be used to compile the entire `node_modules` directory. For example, the following configuration is not recommended: ```ts title="rsbuild.config.ts" export default { source: { include: [/[\\/]node_modules[\\/]/], }, }; ``` This is because most of the npm packages in `node_modules` are already compiled, and it is usually unnecessary to recompile them. Compiling the entire `node_modules` will increase compilation time and may cause unexpected errors in certain npm packages, such as `core-js`, which may result in runtime exceptions after compilation. If you are willing to accept the increase in compilation time, you can use the following configuration to compile all JavaScript files but exclude \`core-js': ```ts title="rsbuild.config.ts" export default { source: { include: [{ not: /[\\/]core-js[\\/]/ }], }, }; ``` --- url: /config/source/pre-entry.md --- # source.preEntry * **Type:** `string | string[]` * **Default:** `undefined` Add a script before the entry file of each page. This script will be executed before the page code. It can be used to execute global logics, such as injecting polyfills, setting global styles, etc. ## Add a single script First create a `src/polyfill.ts` file: ```js console.log('I am a polyfill'); ``` Then configure `src/polyfill.ts` to `source.preEntry`: ```js export default { source: { preEntry: './src/polyfill.ts', }, }; ``` Re-run the compilation and visit any page, you can see that the code in `src/polyfill.ts` has been executed, and the `I am a polyfill` is logged in the console. ## Add global style You can also configure the global style through `source.preEntry`, this CSS code will be loaded earlier than the page code, such as introducing a `normalize.css` file: ```js export default { source: { preEntry: './src/normalize.css', }, }; ``` ## Add multiple scripts You can add multiple scripts by setting `preEntry` to an array, and they will be executed in array order: ```js export default { source: { preEntry: ['./src/polyfill-a.ts', './src/polyfill-b.ts'], }, }; ``` --- url: /config/source/transform-import.md --- # source.transformImport * **Type:** ```ts type TransformImport = | Array<{ libraryName: string; libraryDirectory?: string; style?: string | boolean; styleLibraryDirectory?: string; camelToDashComponentName?: boolean; transformToDefaultImport?: boolean; customName?: string; customStyleName?: string; }> | Function; ``` * **Default:** `undefined` Transform the import path, which can be used to modularly import the subpath of third-party packages. The functionality is similar to [babel-plugin-import](https://npmjs.com/package/babel-plugin-import). ## Example ### Import antd on demand When using the [antd](https://github.com/ant-design/ant-design) component library (versions below v5), you can import components on demand with the following config: ```js export default { source: { transformImport: [ { libraryName: 'antd', libraryDirectory: 'es', style: 'css', }, ], }, }; ``` The source code is: ```js import { Button } from 'antd'; ``` Will be transformed into: ```js import Button from 'antd/es/button'; import 'antd/es/button/style'; ``` ### Import lodash on demand When using lodash, you can automatically refer to the subpath through `transformImport` to reduce bundle size. ```js export default { source: { transformImport: [ { libraryName: 'lodash', customName: 'lodash/{{ member }}', }, ], }, }; ``` The source code is: ```js import { get } from 'lodash'; ``` Will be transformed to: ```js import get from 'lodash/get'; ``` Please avoid the following usage, otherwise all of lodash's code will be imported: ```js import _ from 'lodash'; import lodash from 'lodash'; ``` ## Scope `transformImport` is only applicable to modules compiled by Rsbuild. Note that Rsbuild does not compile JavaScript files in the node\_modules by default. This means that the code in the node\_modules directory will not be processed by `transformImport`. If you want to process the code in node\_modules through `transformImport`, please add the relevant modules to the [source.include](/config/source/include.md) config. ```ts export default { source: { include: [/node_modules[\\/]some-package[\\/]/], }, }; ``` ## Options ### libraryName * **Type:** `string` The original import path that needs to be transformed. ### libraryDirectory * **Type:** `string` * **Default:** `'lib'` Used to splice the transformed path, the splicing rule is `${libraryName}/${libraryDirectory}/${member}`, where member is the imported member. Example: ```ts import { Button } from 'foo'; ``` Out: ```ts import Button from 'foo/lib/button'; ``` ### style * **Type:** `boolean` * **Default:** `undefined` Determines whether to import related styles. If it is `true`, the path `${libraryName}/${libraryDirectory}/${member}/style` will be imported. If it is `false` or `undefined`, the style will not be imported. When it is set to `true`: ```ts import { Button } from 'foo'; ``` Out: ```ts import Button from 'foo/lib/button'; import 'foo/lib/button/style'; ``` ### styleLibraryDirectory * **Type:** `string` * **Default:** `undefined` This configuration is used to splice the import path when importing styles. If this configuration is specified, the `style` configuration option will be ignored. The spliced import path is `${libraryName}/${styleLibraryDirectory}/${member}`. When it is set to `styles`: ```ts import { Button } from 'foo'; ``` Out: ```ts import Button from 'foo/lib/button'; import 'foo/styles/button'; ``` ### camelToDashComponentName * **Type:** `boolean` * **Default:** `true` Whether to convert camelCase imports to kebab-case. Example: ```ts import { ButtonGroup } from 'foo'; ``` Out: ```ts // set to true: import ButtonGroup from 'foo/button-group'; // set to false: import ButtonGroup from 'foo/ButtonGroup'; ``` ### transformToDefaultImport * **Type:** `boolean` * **Default:** `true` Whether to convert import statements to default imports. Example: ```ts import { Button } from 'foo'; ``` Out: ```ts // set to true: import Button from 'foo/button'; // set to false: import { Button } from 'foo/button'; ``` ### customName * **Type:** `string` * **Default:** `undefined` Customize the transformed path. For example, the following config will transform `import { foo } from 'my-lib'` into `import foo from 'my-lib/foo'`. ```js export default { source: { transformImport: [ { libraryName: 'my-lib', customName: `my-lib/{{ member }}`, }, ], }, }; ``` In addition, you can also declare the format of the path after transformation, such as setting it to `my-lib/{{ camelCase member }}` to convert member into camel case. The following formats are supported: * `kebabCase`: lowercase letters, words joined by hyphens. For example: `my-variable-name`. * `snakeCase`: lowercase letters, words joined by underscores. For example: `my_variable_name`. * `camelCase`: first letter lowercase, the first letter of each following word uppercase. For example: `myVariableName`. * `upperCase`: uppercase letters, other characters unchanged. For example: `MY-VARIABLE-NAME`. * `lowerCase`: lowercase letters, other characters unchanged. For example: `my-variable-name`. ### customStyleName * **Type:** `string` * **Default:** `undefined` Customize the transformed style path, the usage is consistent with `customName`. ## Function type The `transformImport` can be a function, it will accept the previous value, and you can modify it. ```ts export default { source: { transformImport: (imports) => { return imports.filter((data) => data.libraryName !== 'antd'); }, }, }; ``` You can also return a new value as the final result in the function, which will replace the previous value. ```ts export default { source: { transformImport: () => { return [ { libraryName: 'antd', libraryDirectory: 'es', style: 'css', }, ]; }, }, }; ``` --- url: /config/source/tsconfig-path.md --- # source.tsconfigPath * **Type:** `string` * **Default:** `'tsconfig.json'` Configure a custom tsconfig.json file path to use, can be a relative or absolute path. ## Purpose The `tsconfig.json` configuration file affects the following behaviors of Rsbuild: * The `paths` field is used to configure [Path Aliases](/guide/advanced/alias.md). * Sets the scope and rules for the [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check). ## Example The value of `source.tsconfigPath` can be set to a relative or an absolute path. Relative path will be resolved relative to the project root directory. * Relative path example: ```ts export default { source: { tsconfigPath: './tsconfig.custom.json', }, }; ``` * Absolute path example: ```ts import path from 'node:path'; export default { source: { tsconfigPath: path.join(__dirname, 'tsconfig.custom.json'), }, }; ``` --- url: /config/output/asset-prefix.md --- # output.assetPrefix * **Type:** `string | 'auto'` * **Default:** [server.base](/config/server/base.md) In [production mode](/config/mode.md), use this option to set the URL prefix for static assets, such as setting it to a CDN URL. `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 production mode. In development mode, please use the [dev.assetPrefix](/config/dev/asset-prefix.md) to set the URL prefix. ## Example Setting `output.assetPrefix` will add the value as a prefix to the URLs of all static assets like JavaScript, CSS, images, etc. * For example, setting it to a CDN address: ```js export default { output: { assetPrefix: 'https://cdn.example.com/assets/', }, }; ``` After the build, the URL of the JS file will be: ```html <script defer src="https://cdn.example.com/assets/static/js/index.ebc4ff4f.js" ></script> ``` * Setting it to a relative path: ```js export default { output: { assetPrefix: './', }, }; ``` After the build, the URL of the JS file will be: ```html <script defer src="./static/js/index.ebc4ff4f.js"></script> ``` ## Default value The default value of `output.assetPrefix` is the same as [server.base](/config/server/base.md). When `server.base` is `/foo`, `index.html` and static assets can be accessed through `http://localhost:3000/foo/`. It should be noted that when customizing the `output.assetPrefix` option, if you want static assets to be accessible normally during [Rsbuild preview](/guide/basic/cli.md#rsbuild-preview), `output.assetPrefix` should contain the same URL prefix as `server.base`, such as: ```ts export default { output: { assetPrefix: '/foo/bar/', }, server: { base: '/foo', }, }; ``` ## Path types assetPrefix can be set to the following types of paths: * **absolute path**: This is the most common practice, can be specific server paths, like `/assets/`, or setting to CDN paths, like `https://cdn.example.com/assets/`. * **relative path**: such as `./assets/`. * **'auto'**: Rspack will automatically calculate the path and generate relative paths based on file location. :::tip It's not recommended to set assetPrefix as a relative path, such as `'./assets/'`. This is because when assets are at different path depths, using relative paths may cause assets to load incorrectly. ::: ## Compare with `publicPath` The functionality of `output.assetPrefix` is basically the same as the [output.publicPath](https://rspack.dev/config/output#outputpublicpath) config in Rspack. The differences from the native configuration are as follows: * `output.assetPrefix` only takes effect in production mode. * `output.assetPrefix` default value is the same as [server.base](/config/server/base.md). * `output.assetPrefix` automatically appends a trailing `/` by default. * The value of `output.assetPrefix` is written to the [process.env.ASSET\_PREFIX](/guide/advanced/env-vars.md#processenvasset_prefix) environment variable (can only be accessed in client code). ## Dynamic asset prefix Use the `__webpack_public_path__` variable provided by Rspack to dynamically set the URL prefix of static assets in JavaScript code. See [Rspack - Dynamically set publicPath](https://rspack.dev/config/output#dynamically-set-publicpath). --- url: /config/output/charset.md --- # output.charset * **Type:** `'ascii' | 'utf8'` * **Default:** `'utf8'` The `charset` config allows you to specify the [character encoding](https://developer.mozilla.org/en-US/docs/Glossary/Character_encoding) for output files to ensure they are displayed correctly in different environments. ## UTF8 By default, the output of Rsbuild is encoded in [UTF-8](https://developer.mozilla.org/en-US/docs/Glossary/UTF-8), which is the most commonly used character encoding in web applications. When your web server returns the resource, please ensure that it sends the correct [Content-Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type) response header so that the browser can parse it correctly. ## ASCII If you want the output files to use [ASCII](https://developer.mozilla.org/en-US/docs/Glossary/ASCII) encoding, you can set this in the config file like this: ```js export default { output: { charset: 'ascii', }, }; ``` When using ASCII encoding, all non-ASCII characters are escaped with backslashes, which may make the files slightly larger and harder to read. ## Notes Currently, the `charset` option only affects files compiled with [SWC](/guide/configuration/swc.md), which by default includes JavaScript and TypeScript files. However, HTML and CSS files are not affected by the `charset` option. For HTML files, Rsbuild adds a `<meta charset="utf-8">` tag by default. You can change this using the [html.meta](/config/html/meta.md) option. --- url: /config/output/clean-dist-path.md --- # output.cleanDistPath * **Type:** ```ts type CleanDistPath = boolean | 'auto' | CleanDistPathObject; ``` * **Default:** `'auto'` Whether to clean up all files under the output directory before the build starts, the output directory is the value of [output.distPath.root](/config/output/dist-path.md). ## Default behavior The default value of `output.cleanDistPath` is `'auto'`: * In development mode, if the value of [dev.writeToDisk](/config/dev/write-to-disk.md) is `false`, Rsbuild will not perform cleanup. * In any mode, if [output.distPath.root](/config/output/dist-path.md) is an external directory or equals to the project root directory, Rsbuild will not perform cleanup to avoid accidentally deleting files from other directories. ```js export default { output: { distPath: { root: '../../some-dir', }, }, }; ``` ## Forced switch You can set `cleanDistPath` to `true` to force it to be enabled, or set it to `false` to force it to be disabled. ```js export default { output: { cleanDistPath: true, }, }; ``` ## Conditional If you only need to clean files in production mode, but not in development mode, you can configure it as: ```js export default { output: { cleanDistPath: process.env.NODE_ENV === 'production', }, }; ``` ## Options `output.cleanDistPath` supports configuration as an object to achieve more granular control. ### enable * **Type:** `boolean | 'auto'` * **Default:** `'auto'` Whether to clean up all files under the output directory before the build starts. ```js export default { output: { // Equivalent to `cleanDistPath: true` cleanDistPath: { enable: true, }, }, }; ``` ### keep * **Type:** `RegExp[]` * **Default:** `undefined` Specify the files to keep in the output directory. If the file's absolute path matches the regular expression in `keep`, the file will not be removed. For example, to keep the `dist/foo.json` file: ```js export default { output: { cleanDistPath: { keep: [/dist\/foo.json/], }, }, }; ``` --- url: /config/output/copy.md --- # output.copy * **Type:** `Rspack.CopyRspackPluginOptions | Rspack.CopyRspackPluginOptions['patterns']` * **Default:** `undefined` Copies the specified file or directory to the dist directory, implemented based on [rspack.CopyRspackPlugin](https://rspack.dev/plugins/rspack/copy-rspack-plugin). > Please refer to the configuration options here: [rspack.CopyRspackPlugin](https://rspack.dev/plugins/rspack/copy-rspack-plugin). ## Example Copy files from `./src/assets` to the `./dist` directory: ```js export default { output: { copy: [ // `./src/assets/image.png` -> `./dist/image.png` { from: './src/assets' }, ], }, }; ``` Copy files from `./src/assets` to the `./dist/assets` directory: ```js export default { output: { copy: [ // `./src/assets/image.png` -> `./dist/assets/image.png` { from: './src/assets', to: 'assets' }, ], }, }; ``` --- url: /config/output/css-modules.md --- # output.cssModules * **Type:** `CSSModules` For custom CSS Modules configuration. The CSS Modules feature of Rsbuild is based on the `modules` option of css-loader. You can refer to [css-loader - modules](https://github.com/webpack-contrib/css-loader?tab=readme-ov-file#modules) to learn more. ## cssModules.auto The `auto` configuration option allows CSS Modules to be automatically enabled based on their filenames. * **Type:** ```ts type Auto = | boolean | RegExp | (( resourcePath: string, resourceQuery: string, resourceFragment: string, ) => boolean); ``` * **Default:** `true` Type description: * `true`: enable CSS Modules for all files matching `/\.module\.\w+$/i.test(filename)` regexp. * `false`: disable CSS Modules. * `RegExp`: enable CSS Modules for all files matching `/RegExp/i.test(filename)` regexp. * `function`: enable CSS Modules for files based on the filename satisfying your filter function check. ```ts export default { output: { cssModules: { auto: (resource) => { return resource.includes('.module.') || resource.includes('shared/'); }, }, }, }; ``` ## cssModules.exportLocalsConvention Style of exported class names. * **Type:** ```ts type CSSModulesLocalsConvention = | 'asIs' | 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'; ``` * **Default:** `'camelCase'` Type description: * `asIs`: Class names will be exported as is. * `camelCase`: Class names will be camelized, the original class name will be exported. * `camelCaseOnly`: Class names will be camelized, the original class name will not be exported. * `dashes`: Only dashes in class names will be camelized, the original class name will be exported. * `dashesOnly`: Dashes in class names will be camelized, the original class name will not be exported. ```ts export default { output: { cssModules: { exportLocalsConvention: 'camelCaseOnly', }, }, }; ``` ## cssModules.exportGlobals * **Type:** `boolean` * **Default:** `false` Allows exporting names from global class names, so you can use them via import. ### Example Set the `exportGlobals` to `true`: ```ts export default { output: { cssModules: { exportGlobals: true, }, }, }; ``` Use `:global()` in CSS Modules: ```css title="style.module.css" :global(.blue) { color: blue; } .red { color: red; } ``` Then you can import the class name wrapped with `:global()`: ```tsx title="Button.tsx" import styles from './style.module.css'; console.log(styles.blue); // 'blue' console.log(styles.red); // 'red-[hash]' ``` ## cssModules.localIdentName * **Type:** `string` * **Default:** ```ts // isProd indicates that the production build const localIdentName = isProd ? '[local]-[hash:base64:6]' : '[path][name]__[local]-[hash:base64:6]'; ``` Sets the format of the class names generated by CSS Modules after compilation. ### Default value `localIdentName` has different default values in development and production. In a production, Rsbuild will generate shorter class names to reduce the bundle size. ```ts import styles from './index.module.scss'; // In development, the value is `src-index-module__header-[hash]` // In production, the value is `header-[hash]` console.log(styles.header); ``` ### Template string You can use the following template strings in `localIdentName`: * `[name]` - the basename of the asset. * `[local]` - original class. * `[hash]` - the hash of the string. * `[folder]` - the folder relative path. * `[path]` - the relative path. * `[file]` - filename and path. * `[ext]` - extension with leading dot. * `[hash:<hashDigest>:<hashDigestLength>]`: hash with hash settings. ### Example Set `localIdentName` to other value: ```ts export default { output: { cssModules: { localIdentName: '[hash:base64:4]', }, }, }; ``` ## cssModules.mode * **Type:** ```ts type Mode = | 'local' | 'global' | 'pure' | 'icss' | ((resourcePath: string) => 'local' | 'global' | 'pure' | 'icss'); ``` * **Default:** `'local'` Controls the mode of compilation applied to the CSS Modules. ### Optional values `cssModules.mode` can take one of the following values: 1. `'local'` (default): This enables the CSS Modules specification for scoping CSS locally. Class and ID selectors are rewritten to be module-scoped, and `@value` bindings are injected. 2. `'global'`: This opts-out of the CSS Modules behavior, disabling both local scoping and injecting `@value` bindings. Global selectors are preserved as-is. 3. `'pure'`: This enables dead-code elimination by removing any unused local classnames and values from the final CSS. It still performs local scoping and `@value` injection. 4. `'icss'`: This compiles to the low-level Interoperable CSS format, which provides a syntax for declaring `:import` and `:export` dependencies between CSS and other languages. It does not perform any scoping or `@value` injection. The `'local'` mode is the most common use case for CSS Modules, enabling modular and locally-scoped styles within components. The other modes may be used in specific scenarios. For example: ```ts export default { output: { cssModules: { mode: 'global', }, }, }; ``` ### Function You can also pass a function to `modules.mode` that determines the mode based on the resource path, query, or fragment. This allows you to use different modes for different files. For example, to use local scoping for `.module.css` files and global styles for other files: ```js modules: { mode: (resourcePath) => { if (/\.module\.\css$/.test(resourcePath)) { return 'local'; } return 'global'; }; } ``` ## cssModules.namedExport * **Type:** `boolean` * **Default:** `false` Whether to enable ES modules named export for class names. ```ts export default { output: { cssModules: { namedExport: true, }, }, }; ``` ### Example ```css title="style.module.css" .foo { color: blue; } ``` * `namedExport: false`: ```js import styles from './style.module.css'; console.log(styles.foo); ``` * `namedExport: true`: ```js import { foo } from './style.module.css'; // or import * as styles from './style.module.css'; console.log(foo); console.log(styles.foo); ``` :::tip When `namedExport` is set to true, the `default` class exported by CSS Modules will be automatically renamed to `_default` class because `default` is a reserved word in ECMA modules. ::: --- url: /config/output/data-uri-limit.md --- # output.dataUriLimit * **Type:** ```ts type DataUriLimit = | number | { svg?: number; font?: number; image?: number; media?: number; assets?: number; }; ``` * **Default:** ```js const defaultDatUriLimit = { svg: 4096, font: 4096, image: 4096, media: 4096, assets: 4096, }; ``` Set the size threshold to inline static assets such as images and fonts. By default, static assets will be Base64 encoded and inline into the page if the size is less than 4KiB. You can adjust the threshold by setting the `dataUriLimit` config. Detail: * `svg`: The threshold of the SVG image. * `font`: The threshold of the font file. * `image`: The threshold of non-SVG images. * `media`: The threshold of media assets such as videos. * `assets`: The threshold of other static assets. Such as the assets defined in [Extend Asset Types](/guide/basic/static-assets.md#extend-asset-types). > See [Inline static assets](/guide/optimization/inline-assets.md) for more details. ## Example * Inline all static assets less than 10KiB: ```js export default { output: { dataUriLimit: 10 * 1024, }, }; ``` * Disable inlining of static assets: ```js export default { output: { dataUriLimit: 0, }, }; ``` * Inline all static assets: ```js export default { output: { dataUriLimit: Number.MAX_SAFE_INTEGER, }, }; ``` * Set the threshold for image assets to 5KiB, do not inline video assets: ```js export default { output: { dataUriLimit: { image: 5 * 1024, media: 0, }, }, }; ``` --- url: /config/output/dist-path.md --- # output.distPath * **Type:** ```ts type DistPathConfig = { root?: string; html?: string; js?: string; jsAsync?: string; css?: string; cssAsync?: string; svg?: string; font?: string; wasm?: string; image?: string; media?: string; assets?: string; }; ``` * **Default:** ```js const defaultDistPath = { root: 'dist', html: './', js: output.target === 'node' ? '' : 'static/js', jsAsync: output.target === 'node' ? '' : 'static/js/async', css: 'static/css', cssAsync: 'static/css/async', svg: 'static/svg', font: 'static/font', wasm: 'static/wasm', image: 'static/image', media: 'static/media', assets: 'static/assets', }; ``` Set the directory of the output files. Rsbuild will emit files to the specified subdirectory according to the file type. > See [Output files](/guide/basic/output-files.md) for more information. ## File types `output.distPath` can be set differently for different file types. Here are the details of each `output.distPath` option: * `root`: The root directory of all output files. * `html`: The output directory of HTML files. * `js`: The output directory of JavaScript files. * `jsAsync`: The output directory of async JavaScript files, which by default will be output to the `async` subdirectory of `distPath.js`. * `css`: The output directory of CSS style files. * `cssAsync`: The output directory of async CSS files, which by default will be output to the `async` subdirectory of `distPath.css`. * `svg`: The output directory of SVG images. * `font`: The output directory of font files. * `wasm`: The output directory of WebAssembly files. * `image`: The output directory of non-SVG images. * `media`: The output directory of media assets, such as videos. * `assets`: The output directory of other static assets. Such as the assets defined in [Extend Asset Types](/guide/basic/static-assets.md#extend-asset-types). ## Root directory The `root` is the root directory of the build artifacts and can be specified as a relative or absolute path. If the value of `root` is a relative path, it will be appended to the project's root directory to form an absolute path. Other directories can only be specified as relative paths and will be output relative to the `root` directory. ## Example The JavaScript files will be output to the `distPath.root` + `distPath.js` directory, which is `dist/static/js`. To output JavaScript files to the `build/resource/js` directory, add the following config: ```ts title="rsbuild.config.ts" export default { output: { distPath: { root: 'build', js: 'resource/js', }, }, }; ``` The above config will generate the following directory structure: ```bash build ├── resource │ └── js │ └── index.js └── index.html ``` --- url: /config/output/emit-assets.md --- # output.emitAssets * **Type:** `boolean` * **Default:** `true` Control whether to emit static assets such as images, fonts, audio, video, etc. In scenarios such as SSR, you may not need to emit duplicate static assets. Therefore, you can return `false` in `emitAssets` to emitting assets. ## Example For example, the following example will emit static assets when building web bundles, and avoid emitting when building node bundles. ```js export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', emitAssets: false, }, }, }, }; ``` --- url: /config/output/emit-css.md --- # output.emitCss * **Type:** `boolean` * **Default:** `true` when [output.target](/config/output/target.md) is `web`, otherwise `false` Whether to emit CSS to the output bundles. If `false`, the CSS will not be extracted to separate files or injected into the JavaScript bundles via [output.injectStyles](/config/output/inject-styles.md). :::tip When `output.emitCss` is `false`, the class name information of CSS Modules will still be injected into the JS bundles, which helps to ensure the correctness of CSS Modules class names in SSR. ::: ## Example When building Node.js bundles, if you need to output CSS files, you can set `output.emitCss` to `true`: ```js export default { output: { target: 'node', emitCss: true, }, }; ``` --- url: /config/output/externals.md --- # output.externals * **Type:** ```ts type Externals = | string | object | function | RegExp | Array<string | object | function | RegExp>; ``` * **Default:** `undefined` At build time, prevent some `import` dependencies from being packed into bundles in your code, and instead fetch them externally at runtime. > For more information, please see: [Rspack Externals](https://rspack.dev/config/externals). ## Example Exclude the `react-dom` dependency from the build product. To get this module at runtime, the value of `react-dom` will globally retrieve the `ReactDOM` variable. ```js export default { output: { externals: { 'react-dom': 'ReactDOM', }, }, }; ``` :::tip If [output.target](/config/output/target.md) is `web-worker`, externals will not take effect. This is because the Web Worker environment can not access global variables. ::: --- url: /config/output/filename-hash.md --- # output.filenameHash * **Type:** `boolean | string` * **Default:** `true` Whether to add a hash value to the filename after the production build. ### Disable hash By default, the filename of the output files will include a hash value: ```bash dist/static/css/index.7879e19d.css dist/static/js/index.18a568e5.js ``` You can set `output.filenameHash` to false to disable this behavior: ```js export default { output: { filenameHash: false, }, }; ``` After rebuilding, the output filenames becomes: ```bash dist/static/css/index.css dist/static/js/index.js ``` ### Hash format The default hash format is `contenthash:8`, which generates an 8-bit hash based on the content of the file. You can set `output.filenameHash` to other formats supported by Rspack and customize the length. ```js export default { output: { filenameHash: 'fullhash:16', }, }; ``` The optional hash formats are: * `fullhash`: The hash value of the entire compilation. If any file changes, the hash values of all output files in the entire project will change. * `chunkhash`: The hash value of the chunk. The hash value will only change when the content of the chunk (and its included modules) changes. * `contenthash`: The hash value of the file content. The hash value will only change when the content of the file itself changes. ### Notes * [output.filename](/config/output/filename.md) has a higher priority than `output.filenameHash`. * By default, when the target is not `web`, the hash will not be included in the filename of the output files, such as Node.js bundles. * By default, the filename in development mode does not include a hash. --- url: /config/output/filename.md --- # output.filename * **Type:** ```ts type FilenameConfig = { html?: string; js?: string | Function; css?: string | Function; svg?: string | Function; font?: string | Function; image?: string | Function; media?: string | Function; assets?: string | Function; }; ``` * **Default:** ```js // Development mode const devDefaultFilename = { html: '[name].html', js: '[name].js', css: '[name].css', svg: '[name].[contenthash:8].svg', font: '[name].[contenthash:8][ext]', image: '[name].[contenthash:8][ext]', media: '[name].[contenthash:8][ext]', assets: '[name].[contenthash:8][ext]', }; // Production mode const prodDefaultFilename = { html: '[name].html', js: output.target === 'node' ? '[name].js' : '[name].[contenthash:8].js', css: '[name].[contenthash:8].css', svg: '[name].[contenthash:8].svg', font: '[name].[contenthash:8][ext]', image: '[name].[contenthash:8][ext]', media: '[name].[contenthash:8][ext]', assets: '[name].[contenthash:8][ext]', }; ``` Sets the filename of output files. After the production build, Rsbuild will add a hash in the middle of the filename by default. If you don't need to add it, you can set [output.filenameHash](/config/output/filename-hash.md) to `false` to disable this behavior. :::tip Rsbuild will generate the final file path based on `output.filename` and [output.distPath](/config/output/dist-path.md). See [Output files](/guide/basic/output-files.md) for more information. ::: ## File types `output.filename` can be set differently for different file types. Here are the details of each `output.filename` option: * `html`: The name of the HTML files. * `js`: The name of the JavaScript files. * `css`: The name of the CSS files. * `svg`: The name of the SVG images. * `font`: The name of the font files. * `image`: The name of non-SVG images. * `media`: The name of media assets, such as video. * `assets`: The name of other static assets. Such as the assets defined in [Extend Asset Types](/guide/basic/static-assets.md#extend-asset-types). ## Example To set the name of the JavaScript files to `[name]_script.js`: ```ts title="rsbuild.config.ts" export default { output: { filename: { js: '[name]_script.js', }, }, }; ``` Set different filenames for development and production builds: ```ts title="rsbuild.config.ts" const isProd = process.env.NODE_ENV === 'production'; export default { output: { filename: { js: isProd ? '[name]_script.[contenthash:8].js' : '[name]_script.js', }, }, }; ``` :::tip Filename hash Usually, Rsbuild only set the filename hash in the production mode (i.e., when `process.env.NODE_ENV === 'production'`). If you set the filename hash in the development mode, it may cause HMR to fail (especially for CSS files). This is because every time the file content changes, the hash value changes, preventing bundler from reading the latest file content. ::: ## Template strings In the value of `output.filename`, you can use template strings to dynamically generate file names. Common template strings include: * `[name]` - entry name, which is the key of [source.entry](/config/source/entry.md). * `[contenthash]` - hash value generated based on file content. * `[contenthash:<length>]` - hash value generated based on file content, with specified hash length. * `[ext]` - file extension, including the dot. > For more template strings, refer to [Rspack - Template String](https://rspack.dev/config/output#template-string). :::tip * `filename.html` can only use certain template strings like `[name]` and `[contenthash:<length>]`. * `filename.js` and `filename.css` do not support `[ext]`. ::: ## Filename of async modules When you import a module via dynamic import, the module will be bundled into a single file, and its default naming rules are as follows: * In the development mode, the filename will be generated based on the module path, such as `dist/static/js/async/src_add_ts.js`. * In the production mode, it will be a random numeric id, such as `dist/static/js/async/798.27e3083e.js`. This is to avoid leaking the source code path in the production mode, and the number of characters is also less. ```js title="src/index.ts" const { add } = await import('./add.ts'); ``` To specify a fixed name for the async module, use the [magic comments](https://rspack.dev/api/modules#magic-comments) provided by Rspack, using `webpackChunkName ` to specify the module name: ```js title="src/index.ts" const { add } = await import( /* webpackChunkName: "my-chunk-name" */ './add.ts' ); ``` After specifying the module name as above, the generated file will be `dist/static/js/async/my-chunk-name.js`. ## Using function You can pass a function to dynamically set the filename based on the file information. The function receives two parameters: * `pathData`: An object containing file path information. * `assetInfo`: An optional object containing additional assets information. Dynamically set the filename for JavaScript files: ```ts title="rsbuild.config.ts" const isProd = process.env.NODE_ENV === 'production'; export default { output: { filename: { js: (pathData, assetInfo) => { console.log(pathData); // You can check the contents of pathData here if (pathData.chunk?.name === 'index') { return isProd ? '[name].[contenthash:8].js' : '[name].js'; } return '/some-path/[name].js'; }, }, }, }; ``` Dynamically set the filename for CSS files: ```ts title="rsbuild.config.ts" const isProd = process.env.NODE_ENV === 'production'; export default { output: { filename: { css: (pathData, assetInfo) => { if (pathData.chunk?.name === 'index') { return isProd ? '[name].[contenthash:8].css' : '[name].css'; } return '/some-path/[name].css'; }, }, }, }; ``` Dynamically set the filename for image files: ```ts title="rsbuild.config.ts" export default { output: { filename: { image: (pathData) => { if (pathData.filename?.includes('foo')) { return '/foo/[name][ext]'; } return '/bar/[name][ext]'; }, }, }, }; ``` :::tip `output.filename.html` does not support using functions yet. ::: ## Query hash To generate hash values on the URL query of assets, refer to: ```ts title="rsbuild.config.ts" const isProd = process.env.NODE_ENV === 'production'; export default { output: { filename: { js: isProd ? '[name].js?v=[contenthash:8]' : `[name].js`, css: isProd ? '[name].css?v=[contenthash:8]' : `[name].css`, }, }, }; ``` In this case, the filenames of JS and CSS will not include the hash, while the URLs in the HTML will contain a hash query. ```html <!doctype html> <html> <head> <script defer src="/static/js/index.js?v=b8565050"></script> <link href="/static/css/index.css?v=02d157ca" rel="stylesheet" /> </head> </html> ``` --- url: /config/output/inject-styles.md --- # output.injectStyles * **Type:** `boolean` * **Default:** `false` Whether to inject styles into DOM. By default, Rsbuild will extract CSS into a separate `.css` file and output it to the dist directory. When this option is set to `true`, CSS files will be inlined into JS files and inserted on the page at runtime via `<style>` tags. This feature is implemented based on [style-loader](https://npmjs.com/package/style-loader). ### Example ```ts export default { output: { injectStyles: true, }, }; ``` ## Configure style-loader When `output.injectStyles` is enabled, you can modify the options of `style-loader` through [tools.styleLoader](/config/tools/style-loader.md). ### Usage scenario It is recommended to only enable the `injectStyles` option in development mode. For production builds, it is recommended to use the default behavior of Rsbuild, which extracts CSS into separate bundles to allow browsers to load CSS and JS assets in parallel. For example: ```ts export default { output: { injectStyles: process.env.NODE_ENV === 'development', }, }; ``` --- url: /config/output/inline-scripts.md --- # output.inlineScripts * **Type:** ```ts type InlineScriptsTest = | RegExp | ((params: { size: number; name: string }) => boolean); type InlineScripts = | boolean | InlineScriptsTest | { enable?: boolean | 'auto'; test: InlineScriptsTest; }; ``` * **Default:** `false` Whether to inline output scripts files (.js files) into HTML with `<script>` tags. Note that, with this option on, the scripts files will no longer be written in dist directory, they will only exist inside the HTML file instead. ## Example By default, we have following output files: ```bash dist/html/main/index.html dist/static/css/style.css dist/static/js/main.js ``` After turn on the `output.inlineScripts` option: ```js export default { output: { inlineScripts: true, }, }; ``` The output files of production build will become: ```bash dist/html/main/index.html dist/static/css/style.css ``` And `dist/static/js/main.js` will be inlined in `index.html`: ```html <html> <head> <script> // content of dist/static/js/main.js </script> </head> </html> ``` :::tip Setting `inlineScripts: true` is equivalent to setting [inlineScripts.enable](#enable) to `'auto'`. This indicates that inline scripts will only be enabled in production mode. ::: ### Script tag position When `output.inlineScripts` is used, it is recommended to set [html.inject](/config/html/inject.md) to `'body'`. As the default injection position of the script tag is the `<head>` tag, changing the injection position to the `<body>` tag can ensure that the inlined script can access the DOM elements in `<body>`. ```ts export default { html: { inject: 'body', // [!code highlight] }, output: { inlineScripts: true, }, }; ``` ### Using RegExp To inline part of the JS files, set `inlineScripts` to a regular expression that matches the URL of the JS file that needs to be inlined. For example, to inline `main.js` into HTML, add the following configuration: ```js export default { output: { inlineScripts: /[\\/]main\.\w+\.js$/, }, }; ``` :::tip The production filename includes a hash value by default, such as `static/js/main.18a568e5.js`. Therefore, in regular expressions, `\w+` is used to match the hash. ::: ### Using function You can also set `output.inlineScripts` to a function that accepts the following parameters: * `name`: The filename, such as `static/js/main.18a568e5.js`. * `size`: The file size in bytes. For example, if we want to inline assets that are smaller than 10kB, we can add the following configuration: ```js export default { output: { inlineScripts({ size }) { return size < 10 * 1000; }, }, }; ``` ### Async chunks When you use [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) in JavaScript, Rspack will generate an async chunk. By default, `output.inlineScripts` will not inline async chunks into the HTML. To inline async chunks into the HTML, change Rspack's default behavior using the [tools.rspack](/config/tools/rspack.md) config by setting [module.parser.javascript.dynamicImportMode](https://rspack.dev/config/module#moduleparserjavascriptdynamicimportmode) to `'eager'`. In this case, Rspack will not generate separate JS files for dynamic imports. ```js export default { output: { inlineScripts: true, }, tools: { rspack: { module: { parser: { javascript: { dynamicImportMode: 'eager', }, }, }, }, }, }; ``` ## Options ### enable * **Type:** `boolean | 'auto'` * **Default:** `false` Whether to enable the inline scripts feature. If set to `'auto'`, it will be enabled when the `mode` is `'production'`. ```ts export default { output: { inlineScripts: { enable: 'auto', test: /[\\/]main\.\w+\.js$/, }, }, }; ``` ### test * **Type:** `RegExp | ((params: { size: number; name: string }) => boolean)` The regular expression or function to match the files that need to be inlined. ```ts export default { output: { inlineScripts: { enable: true, test: /[\\/]main\.\w+\.js$/, }, }, }; ``` --- url: /config/output/inline-styles.md --- # output.inlineStyles * **Type:** ```ts type InlineStylesTest = | RegExp | ((params: { size: number; name: string }) => boolean); type InlineStyles = | boolean | InlineStylesTest | { enable?: boolean | 'auto'; test: InlineStylesTest; }; ``` * **Default:** `false` Whether to inline output style files (.css files) into HTML with `<style>` tags. Note that, with this option on, the style files will no longer be written in dist directory, they will only exist inside the HTML file instead. ## Example By default, we have following output files: ```bash dist/html/main/index.html dist/static/css/style.css dist/static/js/main.js ``` After turn on the `output.inlineStyles` option: ```js export default { output: { inlineStyles: true, }, }; ``` The output files of production build will become: ```bash dist/html/main/index.html dist/static/js/main.js ``` And `dist/static/css/style.css` will be inlined in `index.html`: ```html <html> <head> <style> /* content of dist/static/css/style.css */ </style> </head> <body></body> </html> ``` :::tip Setting `inlineStyles: true` is equivalent to setting [inlineStyles.enable](#enable) to `'auto'`. This indicates that inline styles will only be enabled in production mode. ::: ### Using RegExp To inline part of the CSS files, set `inlineStyles` to a regular expression that matches the URL of the CSS file that needs to be inlined. For example, to inline `main.css` into HTML, add the following configuration: ```js export default { output: { inlineStyles: /[\\/]main\.\w+\.css$/, }, }; ``` :::tip The production filename includes a hash value by default, such as `static/css/main.18a568e5.css`. Therefore, in regular expressions, `\w+` is used to match the hash. ::: ### Using function You can also set `output.inlineStyles` to a function that accepts the following parameters: * `name`: The filename, such as `static/css/main.18a568e5.css`. * `size`: The file size in bytes. For example, if we want to inline assets that are smaller than 10kB, we can add the following configuration: ```js export default { output: { inlineStyles({ size }) { return size < 10 * 1000; }, }, }; ``` ## Options ### enable * **Type:** `boolean | 'auto'` * **Default:** `false` Whether to enable the inline styles feature. If set to `'auto'`, it will be enabled when the `mode` is `'production'`. ```ts export default { output: { inlineStyles: { enable: 'auto', test: /[\\/]main\.\w+\.css$/, }, }, }; ``` ### test * **Type:** `RegExp | ((params: { size: number; name: string }) => boolean)` The regular expression or function to match the CSS files that need to be inlined. ```ts export default { output: { inlineStyles: { enable: true, test: /[\\/]main\.\w+\.css$/, }, }, }; ``` --- url: /config/output/legal-comments.md --- # output.legalComments * **Type:** `'linked' | 'inline' | 'none'` * **Default:** `'linked'` Configure how to handle the legal comments. ## What are legal comments? A "legal comment" is considered to be any statement-level comment in JS or rule-level comment in CSS that contains @license or @preserve or that starts with //! or /\*!. These comments are preserved in output files by default since that follows the intent of the original authors of the code. For example, the `LICENSE` comment in React: ```js /** * @license React * react.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ ``` ## Optional values You can configure how to handle legal comments by using one of the following options: ### `linked` Extract all legal comments to `*.LICENSE.txt` files and link to them with a comment. ```js title="rsbuild.config.js" export default { output: { legalComments: 'linked', }, }; ``` `.LICENSE.txt` files are not loaded by the page, so they won't affect the page's performance. ### `inline` Preserve all legal comments in the original position. This may increase the size of the output bundles. ```js title="rsbuild.config.js" export default { output: { legalComments: 'inline', }, }; ``` ### `none` Remove all legal comments. ```js title="rsbuild.config.js" export default { output: { legalComments: 'none', }, }; ``` :::tip Removing license comments may violate the terms of some software licenses. Please ensure you have the right to remove these comments before using this option. ::: --- url: /config/output/manifest.md --- # output.manifest * **Type:** `string | boolean` * **Default:** `false` Configure how to generate the manifest file. * `true`: Generate a manifest file named `manifest.json` in the output directory. * `false`: Do not generate the manifest file. * `string`: Generate a manifest file with the specified filename or path. * `object`: Generate a manifest file with the specified options. The manifest file contains the information of all assets, and the mapping relationship between [entry module](/config/source/entry.md) and assets. ## Basic example Enable the asset manifest: ```ts title="rsbuild.config.ts" export default { output: { manifest: true, }, }; ``` After building, Rsbuild will generate a `dist/manifest.json` file: ```json title="dist/manifest.json" { "allFiles": [ "/static/css/index.[hash].css", "/static/js/index.[hash].js", "/static/images/logo.[hash].png", "/index.html" ], "entries": { "index": { "initial": { "js": ["/static/js/index.[hash].js"], "css": ["/static/css/index.[hash].css"] }, "assets": ["/static/images/logo.[hash].png"], "html": ["/index.html"] } } } ``` ## Manifest structure By default, the manifest file will be output in the following structure: ```ts type FilePath = string; type ManifestList = { entries: { /** The key is the entry name, from Rsbuild's source.entry config. */ [entryName: string]: { initial?: { js?: FilePath[]; css?: FilePath[]; }; async?: { js?: FilePath[]; css?: FilePath[]; }; /** HTML files related to the current entry */ html?: FilePath[]; /** other assets (e.g. png、svg、source map) related to the current entry */ assets?: FilePath[]; }; }; /** Flatten all assets */ allFiles: FilePath[]; }; ``` ## Options `output.manifest` can be an object, here are all the options: ### filename * **Type:** `string` * **Default:** `'manifest.json'` Specify the name or path of the manifest file. `filename` can be a path relative to the `dist` directory, for example, output to `dist/static/my-manifest.json`: ```ts title="rsbuild.config.ts" export default { output: { manifest: { filename: './static/my-manifest.json', }, }, }; ``` This can be simplified as: ```ts title="rsbuild.config.ts" export default { output: { manifest: './static/my-manifest.json', }, }; ``` ### generate * **Type:** ```ts type ManifestGenerate = (params: { files: FileDescriptor[]; manifestData: ManifestData; }) => Record<string, unknown>; ``` * **Default:** `undefined` * **Version:** `>= 1.2.0` With the `manifest.generate` function, you can customize the content of the manifest file. The function receives the following parameters: * `files`: The description information of all output files. * `manifestData`: The default manifest data. For example, only keep the `allAssets` field: ```ts title="rsbuild.config.ts" export default { output: { manifest: { generate: ({ manifestData }) => { return { allAssets: manifestData.allFiles, }; }, }, }, }; ``` You can also customize the content of the manifest file based on `files`. The `files` structure is as follows: ```ts interface FileDescriptor { name: string; path: string; isAsset: boolean; isChunk: boolean; isInitial: boolean; isModuleAsset: boolean; chunk?: import('@rspack/core').Chunk; } ``` Here is an example of `files`: ```ts const files = [ { name: 'index.js', path: '/static/js/index.[hash].js', isAsset: false, isChunk: true, isInitial: true, isModuleAsset: false, chunk: { // Chunk info... }, }, { name: 'index.html', path: '/index.html', isAsset: true, isChunk: false, isInitial: false, isModuleAsset: false, }, ]; ``` ### filter * **Type:** ```ts type ManifestFilter = (file: FileDescriptor) => boolean; ``` * **Default:** `file => !file.name.endsWith('.LICENSE.txt')` * **Version:** `>= 1.2.0` Allows you to filter the files included in the manifest. The function receives a `file` parameter and returns `true` to keep the file, or `false` to exclude it. By default, `*.LICENSE.txt` files are excluded from the manifest, as these license files are only used to declare open source licenses and are not used at runtime. For example, to only keep `*.js` files: ```ts title="rsbuild.config.ts" export default { output: { manifest: { filter: (file) => file.name.endsWith('.js'), }, }, }; ``` The generated manifest file will only include `*.js` files: ```json title="dist/manifest.json" { "allFiles": ["/static/js/index.[hash].js"], "entries": { "index": { "initial": { "js": ["/static/js/index.[hash].js"] } } } } ``` Or include all files: ```ts title="rsbuild.config.ts" export default { output: { manifest: { filter: () => true, }, }, }; ``` --- url: /config/output/minify.md --- # output.minify * **Type:** ```ts type Minify = | boolean | { js?: boolean; jsOptions?: Rspack.SwcJsMinimizerRspackPluginOptions; css?: boolean; cssOptions?: Rspack.LightningcssMinimizerRspackPluginOptions; }; ``` * **Default:** `true` Configure whether to enable code minification in production mode, or to configure minimizer options. By default, JS and CSS code will be automatically minimized in production mode to improve page performance. If you do not want to minify the code, you can set `minify` to `false` to disable minification for all code. Alternatively, you can control the behavior of code minification through detailed configuration of the `minify` option. Below are detailed explanations for each configuration option: :::tip Rsbuild uses [SWC](/guide/configuration/swc.md) to minify JS code and [Lightning CSS](/guide/styling/css-usage.md#lightning-css) to minify CSS code by default. ::: ## Example ### Disable minification Set `minify` to `false` to disable JS and CSS code minification: ```ts title="rsbuild.config.ts" export default { output: { minify: false, }, }; ``` :::tip This usage is usually used for debugging and troubleshooting. It is not recommended to disable code minification in production builds, as it will significantly degrade the page performance. ::: ## Options ### minify.js * **Type:** `boolean` * **Default:** `mode === 'production'` Whether to enable minification for JavaScript code. For example, disable JavaScript minification: ```ts title="rsbuild.config.ts" export default { output: { minify: { js: false, }, }, }; ``` ### minify.jsOptions * **Type:** `Rspack.SwcJsMinimizerRspackPluginOptions` * **Default:** `{}` `output.minify.jsOptions` is used to configure SWC's minification options. For detailed configurations, please refer to [SwcJsMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin). The following configuration will override the default settings, disable the mangle feature. For example, disable the mangle feature: ```ts title="rsbuild.config.ts" export default { output: { minify: { jsOptions: { minimizerOptions: { mangle: false, }, }, }, }, }; ``` > Refer to [Configure SWC](/guide/configuration/swc.md) for more details. ### minify.css * **Type:** `boolean` * **Default:** `mode === 'production'` Whether to enable minification for CSS code. For example, disable CSS minification: ```ts title="rsbuild.config.ts" export default { output: { minify: { css: false, }, }, }; ``` ### minify.cssOptions * **Type:** `Rspack.LightningcssMinimizerRspackPluginOptions` * **Default:** inherit from [tools.lightningcssLoader](/config/tools/lightningcss-loader.md) `output.minify.cssOptions` is used to configure Lightning CSS's minification options. For specific configuration items, please refer to [LightningCssMinimizerRspackPlugin Documentation](https://rspack.dev/plugins/rspack/lightning-css-minimizer-rspack-plugin). For example, disable error recovery: ```ts title="rsbuild.config.ts" export default { output: { minify: { cssOptions: { minimizerOptions: { errorRecovery: false, }, }, }, }, }; ``` :::tip When you configure some options in [tools.lightningcssLoader](/config/tools/lightningcss-loader.md), `output.minify.cssOptions` will automatically inherit these options, which ensures that the CSS code transformation behavior in the development build is consistent with that in the production build. ::: ## Switching minifier ### JS minifier If the default SWC minifier does not meet your needs, you can switch to other minifiers through the [tools.bundlerChain](/config/tools/bundler-chain.md) option. For example, use [terser-webpack-plugin](https://github.com/terser/terser-webpack-plugin) to switch to Terser or esbuild. * Use [terser](https://github.com/terser/terser) to minify JS code: ```ts title="rsbuild.config.ts" import TerserPlugin from 'terser-webpack-plugin'; export default { tools: { bundlerChain(chain, { CHAIN_ID }) { chain.optimization.minimizer(CHAIN_ID.MINIMIZER.JS).use(TerserPlugin, [ { // options }, ]); }, }, }; ``` * Use [esbuild](https://github.com/evanw/esbuild) to minify JS code, you need to install the `esbuild` package and set `esbuildMinify`: ```ts title="rsbuild.config.ts" import TerserPlugin from 'terser-webpack-plugin'; export default { tools: { bundlerChain(chain, { CHAIN_ID }) { chain.optimization.minimizer(CHAIN_ID.MINIMIZER.JS).use(TerserPlugin, [ { minify: TerserPlugin.esbuildMinify, }, ]); }, }, }; ``` :::tip When using a custom JS minifier, the `minify.jsOptions` option will no longer take effect. ::: --- url: /config/output/override-browserslist.md --- # output.overrideBrowserslist * **Type:** `string[]` * **Default:** `undefined` Specifies the range of target browsers that the project is compatible with. This value will be used by tools such as [SWC](https://github.com/swc-project/swc) and [Lightning CSS](https://github.com/parcel-bundler/lightningcss) to identify the JavaScript syntax that need to be transformed and the CSS browser prefixes that need to be added. ## Priority The `overrideBrowserslist` config will override the `.browserslistrc` config file in the project and the `browserslist` field in package.json. In most cases, it is recommended to use the `.browserslistrc` file rather than the `overrideBrowserslist` config. Because the `.browserslistrc` file is the official config file, it is more general and can be recognized by other libraries in the community. > For more details, see [Browserslist](/guide/advanced/browserslist.md). ## Default value If there is no `browserslist` configs defined in the project, nor `overrideBrowserslist` defined, then Rsbuild will set the default browserslist to: ```js ['chrome >= 87', 'edge >= 88', 'firefox >= 78', 'safari >= 14']; ``` ## Example An example of mobile web applications: ```ts title="rsbuild.config.ts" export default { output: { overrideBrowserslist: [ 'iOS >= 9', 'Android >= 4.4', 'last 2 versions', '> 0.2%', 'not dead', ], }, }; ``` Check out the [browserslist documentation](https://github.com/browserslist/browserslist) to learn more about browserslist. ## Set by environment When you build for multiple [environments](/config/environments.md), you can set different browserslist for each environment: For example, set different browserslist for `web` and `node` environments: ```ts title="rsbuild.config.ts" export default { environments: { web: { output: { target: 'web', overrideBrowserslist: ['iOS >= 9', 'Android >= 4.4'], }, }, node: { output: { target: 'node', overrideBrowserslist: ['node >= 20'], }, }, }, }; ``` --- url: /config/output/polyfill.md --- # output.polyfill * **Type:** `'entry' | 'usage' | 'off'` * **Default:** `'off'` Control the injection mode of the polyfills. > Please refer to the [Polyfill Mode](/guide/advanced/browser-compatibility.md#polyfill-mode) for more details. ## Optional value ### usage When `output.polyfill` is configured as `'usage'`, Rsbuild will inject the polyfills based on the APIs used in each file. ```ts export default { output: { polyfill: 'usage', }, }; ``` ### entry When `output.polyfill` is configured as `'entry'`, Rsbuild will inject the polyfills in each entry file. ```ts export default { output: { polyfill: 'entry', }, }; ``` ### off When `output.polyfill` is configured as `'off'`, Rsbuild will not inject the polyfills, and developers need to ensure code compatibility themselves. ```ts export default { output: { polyfill: 'off', }, }; ``` --- url: /config/output/source-map.md --- # output.sourceMap * **Type:** ```ts type SourceMap = | boolean | { js?: Rspack.Configuration['devtool']; css?: boolean; }; ``` * **Default:** ```ts const defaultSourceMap = { js: mode === 'development' ? 'cheap-module-source-map' : false, css: false, }; ``` Used to set whether to generate source map files, and which format of source map to generate. :::tip What is a source map Source map is an information file that saves the source code mapping relationship. It records each location of the compiled code and the corresponding pre-compilation location. With source map, you can directly view the source code when debugging the compiled code. ::: ## Default behavior By default, the source map generation rules for Rsbuild are as follows: * In development mode, source maps for JS files are generated for development debugging, while source maps for CSS files are not generated. * In production mode, no source maps for JS and CSS files are generated to improve build performance. ## Boolean value If `output.sourceMap` is `true`, the source map will be generated according to the [mode](/config/mode.md), equivalent to: ```js export default { output: { sourceMap: { js: mode === 'development' ? 'cheap-module-source-map' : 'source-map', css: true, }, }, }; ``` If `output.sourceMap` is `false`, no source map will be generated, equivalent to: ```js export default { output: { sourceMap: { js: false, css: false, }, }, }; ``` ## JS source map The source map for JS files is controlled by `sourceMap.js` and can be configured by passing in all the source map formats supported by Rspack's [devtool](https://rspack.dev/config/devtool) option. Setting it to `false` will disable the source map. For example, if you need to generate high-quality source maps in all environments, you can set it as follows: ```js export default { output: { sourceMap: { js: 'source-map', }, }, }; ``` You can also set different source map formats based on the environment. ```js export default { output: { sourceMap: { js: process.env.NODE_ENV === 'production' ? // Use a high quality source map format for production 'source-map' : // Use a more performant source map format for development 'cheap-module-source-map', }, }, }; ``` ## CSS source map The source map for CSS files is controlled by `sourceMap.css`. Setting it to `true` will enable the source map, while setting it to `false` will disable it. For example, if you need to generate a source map for CSS files, you can set it as follows: ```js export default { output: { sourceMap: { css: true, }, }, }; ``` In production builds, it is not recommended to enable both [output.injectStyles](/config/output/inject-styles.md) and `output.sourceMap.css`, as `output.injectStyles` will inject the source map into the JS bundles, which will increase the file size and slow down the page loading speed. You can only enable the CSS file source map in the development mode: ```js export default { output: { injectStyles: true, sourceMap: { css: process.env.NODE_ENV === 'development', }, }, }; ``` --- url: /config/output/target.md --- # output.target * **Type:** ```ts type RsbuildTarget = 'web' | 'node' | 'web-worker'; ``` * **Default:** `'web'` * **Version:** `>= 1.0.0` Setting the build target of Rsbuild. Rsbuild supports multiple build targets for running in different environments. After setting the target type, the default configuration of Rsbuild will change accordingly. ## Default target By default, the target is set to 'web' and will build outputs for running in the browser. Rsbuild will read the [Browserslist config](https://github.com/browserslist/browserslist) in the project to determine the range of browsers. ## Optional values In addition to `'web'`, `target` can also be set to the following values: * `'node'`: Build for Node.js environment, usually used in SSR or other scenarios. * `'web-worker'`: Build for Web Workers environment. For example, to build for the Node.js environment: ```ts export default { output: { target: 'node', }, }; ``` ## Parallel builds You can use [environments](/config/environments.md) to build multiple targets in parallel. For example, to build `web` outputs and `node` outputs at the same time: ```ts export default { environments: { web: { output: { target: 'web', }, }, node: { output: { target: 'node', }, }, }, }; ``` ## Node target Refers to the build target running in the Node.js environment, usually used in scenarios such as SSR. When `target` is set to `'node'`, Rsbuild will: * Set Rspack's [target](https://rspack.dev/config/target) to `'node'`. * No HTML files will be generated, and HTML-related logic will not be executed, since HTML is not required by the Node.js environment. * The default code split strategy will be disabled, but dynamic import can still work. * Disable the HMR. * Set the default value of Browserslist to `['node >= 16']`. * Set the default value of [output.emitCss](/config/output/emit-css.md) to `false`. This means that CSS code will not be extracted to separate files, but the id information of CSS Modules will be included in the bundle. ### Node addons When `target` is set to `'node'`, Rsbuild allows you to import Node.js [Addons](https://nodejs.org/api/addons.html) in JavaScript files. For example: ```js title="src/index.js" import addon from './addon.node'; addon.doSomething(); ``` The referenced addons file will be output to the `dist` directory: ``` dist/index.js dist/addon.node ``` ## Web Workers target Refers to the build target running in the [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) environment. When `target` is set to `'web-worker'`, Rsbuild will: * Set Rspack's [target](https://rspack.dev/config/target) to `'webworker'`. * No HTML files will be generated, and HTML-related logic will not be executed, since HTML is not required by the Web Worker environment. * CSS code will not be bundled or extracted, but the id information of CSS Modules will be included in the bundle (the default value of [output.emitCss](/config/output/emit-css.md) is `false`). * The default code split strategy will be disabled, and **dynamic import can not work**, because the Web Worker only runs a single JavaScript file. * Set the default value of [output.emitCss](/config/output/emit-css.md) to `false`. This means that CSS code will not be extracted to separate files, but the id information of CSS Modules will be included in the bundle. * Disable the HMR. For more information, please refer to: [Using Web Workers](/guide/basic/web-workers.md). ## Other targets [Rspack](https://rspack.dev/config/target) supports other target types, such as `electron-main` and `electron-renderer`. Rsbuild currently does not support these targets. You can configure these targets using [tools.rspack](/config/tools/rspack.md). For example, setting the `target` to `'electron-main'` will override the default `'web'` set by Rsbuild. ```js export default { tools: { rspack: { target: 'electron-main', }, }, }; ``` --- url: /config/html/app-icon.md --- # html.appIcon * **Type:** ```ts type AppIconItem = { src: string; size: number; target?: 'apple-touch-icon' | 'web-app-manifest'; }; type AppIcon = { name?: string; icons: AppIconItem[]; filename?: string; }; ``` * **Default:** `undefined` Set the web application icons to display when added to the home screen of a mobile device: * Generate the web app manifest file and its `icons` field. * Generate the `apple-touch-icon` and `manifest` tags in the HTML file. :::tip Refer to the following documents for more information: * [MDN - Web app manifests](https://developer.mozilla.org/en-US/docs/Web/Manifest) * [How to Favicon: Six files that fit most needs](https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs) ::: ## Example For display on different devices, you will need to prepare several icons of different sizes. The most commonly used icon sizes are `192x192` and `512x512`, and you can customize the icon sizes and quantities to suit your needs. ```js export default { html: { appIcon: { name: 'My Website', icons: [ { src: './src/assets/icon-192.png', size: 192 }, { src: './src/assets/icon-512.png', size: 512 }, ], }, }, }; ``` After compilation, the following tags will be automatically generated in the HTML: ```html <link rel="manifest" href="/manifest.webmanifest" /> <link rel="apple-touch-icon" sizes="180x180" href="/static/image/icon-192.png" /> ``` Here, `manifest.webmanifest` is a JSON file that contains information about the application's name, icons, and other details. ```json { "name": "My Website", "icons": [ { "src": "/static/image/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/static/image/icon-512.png", "sizes": "512x512", "type": "image/png" } ] } ``` :::tip Icon size For Chromium, you must provide at least a 192x192 pixel icon and a 512x512 pixel icon. If only those two icon sizes are provided, Chrome automatically scales the icons to fit the device. If you'd prefer to scale your own icons, and adjust them for pixel-perfection, provide icons in increments of `48dp`. ::: ## name * **Type:** `string` * **Default:** `undefined` The name of the application that will be displayed when it is added to the home screen of the mobile device. If not set, the `manifest.webmanifest` file will not be generated. > For more details, see [Web app manifests - name](https://developer.mozilla.org/en-US/docs/Web/Manifest/name). ## icons * **Type:** `AppIconItem[]` * **Default:** `undefined` The list of icons: * `src` is the path of the icon, which can be a URL, an absolute file path, or a relative path to the project [root](/config/root.md). * `size` is the size of the icon in pixels. * `target` refers to the intended target for the icon, which can be either `apple-touch-icon` or `web-app-manifest`. If `target` is not set, by default, the manifest file will include all icons, while the `apple-touch-icon` tags will only include icons smaller than `200x200`. ### Example `src` can be set to an absolute path: ```js import path from 'node:path'; export default { html: { appIcon: { name: 'My Website', icons: [ { src: path.resolve(__dirname, './assets/icon-192.png'), size: 192 }, { src: path.resolve(__dirname, './assets/icon-512.png'), size: 512 }, ], }, }, }; ``` Use `target` to specify the target for the icon: ```js export default { html: { appIcon: { name: 'My Website', icons: [ { src: './src/assets/icon-180.png', size: 180, target: 'apple-touch-icon', }, { src: './src/assets/icon-192.png', size: 192, target: 'web-app-manifest', }, { src: './src/assets/icon-512.png', size: 512, target: 'web-app-manifest', }, ], }, }, }; ``` ### filename * **Type:** `string` * **Default:** `'manifest.webmanifest'` The filename of the manifest file. ```js export default { html: { appIcon: { filename: 'manifest.json', }, }, }; ``` --- url: /config/html/crossorigin.md --- # html.crossorigin * **Type:** `boolean | 'anonymous' | 'use-credentials'` * **Default:** `false` Set the [crossorigin](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin) attribute of the `<script>` and `<style>` tags. * If `true` is passed, it will automatically be set to `crossorigin="anonymous"`. * If `false` is passed, it will not set the `crossorigin` attr. ## Example ```js export default { html: { crossorigin: 'anonymous', }, output: { assetPrefix: 'https://example.com', }, }; ``` After compilation, the `<script>` tag in HTML becomes: ```html <script defer src="https://example.com/static/js/main.js" crossorigin="anonymous" ></script> ``` The `<style>` tag becomes: ```html <link href="https://example.com/static/css/main.css" rel="stylesheet" crossorigin="anonymous" /> ``` :::tip If the domain of static assets is the same as the current page, Rsbuild will not add the crossorigin="anonymous" attribute, as this attribute is not required for non-cross-domain scenario. ::: ## Optional values `crossorigin` can the set to the following values: * `anonymous`: Request uses CORS headers and credentials flag is set to 'same-origin'. There is no exchange of user credentials via cookies, client-side SSL certificates or HTTP authentication, unless destination is the same origin. * `use-credentials`: Request uses CORS headers, credentials flag is set to 'include' and user credentials are always included. --- url: /config/html/favicon.md --- # html.favicon * **Type:** `string | Function` * **Default:** `undefined` Set the favicon icon path for all pages, can be set as: * a URL. * an absolute file path. * a relative path relative to the project [root](/config/root.md). After config this option, the favicon will be automatically copied to the dist directory during the compilation, and the corresponding `link` tag will be added to the HTML. :::tip Rsbuild also provides [html.appIcon](/config/html/app-icon.md) to set the icon of the web application. ::: ## Example Set as a relative path: ```js export default { html: { favicon: './src/assets/icon.png', }, }; ``` Set to an absolute path: ```js import path from 'node:path'; export default { html: { favicon: path.resolve(__dirname, './src/assets/icon.png'), }, }; ``` Set to a URL: ```js import path from 'node:path'; export default { html: { favicon: 'https://foo.com/favicon.ico', }, }; ``` After recompiling, the following tags are automatically generated in the HTML: ```html <link rel="icon" href="/favicon.ico" /> ``` ## Function usage * **Type:** ```ts type FaviconFunction = ({ value: string; entryName: string }) => string | void; ``` When `html.favicon` is of type Function, the function receives an object as input, with the following properties: * `value`: the default favicon configuration for Rsbuild. * `entryName`: the name of the current entry. In the context of MPA (Multi-Page Application), you can return different `favicon` based on the entry name, thus generating different tags for each page: ```js export default { html: { favicon({ entryName }) { const icons = { foo: 'https://example.com/foo.ico', bar: 'https://example.com/bar.ico', }; return icons[entryName] || 'https://example.com/default.ico'; }, }, }; ``` --- url: /config/html/inject.md --- # html.inject * **Type:** `'head' | 'body' | boolean | Function` * **Default:** `'head'` Set the inject position of the `<script>` tag. Can be set to the following values: * `'head'`: The `<script>` tag will be inject inside the `<head>` tag. * `'body'`: The `<script>` tag is inject at the end of the `<body>` tag. * `true`: Automatic judgement based on the [html.scriptLoading](/config/html/script-loading.md), if set to 'blocking', it will inject into the `<body>` tag, otherwise it will inject into the `<head>` tag. * `false`: `<script>` tags will not be injected. ## Default inject position The `<script>` tag is inside the head tag by default: ```html <html> <head> <title>
``` ## Inject into body Add the following config to inject ` ``` ## Function usage * **Type:** ```ts type InjectFunction = ({ value: ScriptInject; entryName: string }) => string | void; ``` When `html.inject` is of type Function, the function receives an object as its parameter, with the following properties: * `value`: the default inject configuration of Rsbuild. * `entryName`: the name of the current entry. In the context of MPA (Multi-Page Application), you can set different `inject` behaviors based on the entry name: ```js export default { html: { inject({ entryName }) { return entryName === 'foo' ? 'body' : 'head'; }, }, }; ``` ## Manual injection When `html.inject` is set to `false`, Rsbuild will not inject tags into the HTML, and the tags defined in [html.tags](/config/html/tags.md) will not take effect. At this time, you can access all the tags to be injected through the `htmlPlugin.tags` template parameter, and manually inject them into the specified position. For example, insert the ` <%= htmlPlugin.tags.headTags %>
<%= htmlPlugin.tags.bodyTags %> ``` --- url: /config/html/meta.md --- # html.meta * **Type:** `Object | Function` * **Default:** ```ts const defaultMeta = { // charset: { charset: 'UTF-8', }, // viewport: 'width=device-width, initial-scale=1.0', }; ``` Configure the `` tag of the HTML. :::tip If the HTML template used in the current project already contains the charset or viewport meta tags, then the tags in the HTML template take precedence. ::: ## String type * **Type:** ```ts type MetaOptions = { [name: string]: string; }; ``` When the `value` of a `meta` object is a string, the `key` of the object is automatically mapped to `name`, and the `value` is mapped to `content`. For example to set description: ```js export default { html: { meta: { description: 'a description of the page', }, }, }; ``` The generated `meta` tag in HTML is: ```html ``` ## Object type * **Type:** ```ts type MetaOptions = { [name: string]: | string | false | { [attr: string]: string | boolean; }; }; ``` When the `value` of a `meta` object is an object, the `key: value` of the object is mapped to the attribute of the `meta` tag. In this case, the `name` and `content` properties will not be set by default. For example to set `charset`: ```js export default { html: { meta: { charset: { charset: 'UTF-8', }, }, }, }; ``` The `meta` tag in HTML is: ```html ``` ## Function usage * **Type:** ```ts type MetaFunction = ({ value: MetaOptions, entryName: string, }) => MetaOptions | void; ``` When `html.meta` is of type `Function`, the function receives an object as an argument with the following properties: * `value`: the default meta configuration of Rsbuild. * `entryName`: the name of the current entry. You can directly modify the configuration object and not return anything, or you can return an object as the final configuration. For example, you can directly modify the built-in `meta` configuration object: ```js export default { html: { meta({ value }) { value.description = 'this is my page'; return value; }, }, }; ``` In the MPA (Multi-Page Application) scenario, you can return different `meta` configurations based on the entry name, thus generating different `meta` tags for each page: ```js export default { html: { meta({ entryName }) { switch (entryName) { case 'foo': return { description: 'this is foo page', }; case 'bar': return { description: 'this is bar page', }; default: return { description: 'this is other pages', }; } }, }, }; ``` ## Remove default value Setting the `value` of the `meta` object to `false` and the meta tag will not be generated. For example to remove the `viewport`: ```ts export default { html: { meta: { viewport: false, }, }, }; ``` --- url: /config/html/mount-id.md --- # html.mountId * **Type:** `string` * **Default:** `'root'` By default, the `root` element is included in the HTML template for component mounting, and the element id can be modified through `mountId`. ```html
``` ## Example Set the `id` to `app`: ```js export default { html: { mountId: 'app', }, }; ``` After compilation: ```html
``` ## Notes ### Update relevant code After modifying `mountId`, if there is logic in your code to obtain the `root` root node, please update the corresponding value: ```ts const domNode = document.getElementById('root'); // [!code --] const domNode = document.getElementById('app'); // [!code ++] ReactDOM.createRoot(domNode).render(); ``` ### Custom templates If you customized the HTML template, please make sure that the template contains `
`, otherwise the `mountId` config will not take effect. --- url: /config/html/output-structure.md --- # html.outputStructure * **Type:** `'flat' | 'nested'` * **Default:** `'flat'` Define the directory structure of the HTML output files. ## Example By default, the structure of HTML files in the `dist` directory is `flat`: ```bash /dist └── [name].html ``` You can set `html.outputStructure` to `nested`: ```js export default { html: { outputStructure: 'nested', }, }; ``` After rebuild, the directory structure of the HTML files is: ```bash /dist └── [name] └── index.html ``` > If you want to set the parent path of the HTML files, use the `output.distPath.html` config. --- url: /config/html/script-loading.md --- # html.scriptLoading * **Type:** `'defer' | 'blocking' | 'module'` * **Default:** `'defer'` Used to set how ` ``` :::tip When the browser encounters a ` ``` ### module When `scriptLoading` is set to `module`, the script can support ES modules syntax, and the browser will automatically delay the execution of these scripts by default, which is similar to `defer`. ```js export default { html: { scriptLoading: 'module', }, }; ``` ```html ``` --- url: /config/html/tags.md --- # html.tags * **Type:** ```ts type TagsConfig = HtmlTag | HtmlTagHandler | Array; ``` * **Default:** `undefined` Modifies the tags that are injected into the HTML page. ## Tag object ```ts type HtmlTag = { tag: string; attrs?: Record; children?: string; /** @default false */ hash?: boolean | string | ((url: string, hash: string) => string); /** @default true */ publicPath?: boolean | string | ((url: string, publicPath: string) => string); /** * Sets the insertion position of the current tag relative to the original tags. * If set to `true` it will be inserted after the original tags, if set to `false` it will be inserted before the original tags. * @default true */ append?: boolean; /** * Whether to add tags to head * Enable by default only for elements that are allowed to be included in the `head` tag. * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head#see_also} */ head?: boolean; }; ``` A tag object can be used to describe the tag to be injected and the location of the injection can be controlled by the parameters. ```js export default { output: { assetPrefix: 'https://example.com/', }, html: { tags: [ { tag: 'script', attrs: { src: 'a.js' }, head: true, append: true, publicPath: true, hash: true, }, ], }, }; ``` It will add a `script` tag to the end of the `head` of the HTML: ```html ``` Fields in the tag that indicate the path to the external assets are affected by the `publicPath` and `hash` options. These fields include `src` for the `script` tag and `href` for the `link` tag. Enabling `publicPath` will splice the [output.assetPrefix](/config/output/asset-prefix.md) field before the attribute representing the path in the tag. And the `hash` field causes the filename to be followed by an additional hash query to control browser caching, with the same hash string as the HTML file product. You can also pass functions to those fields to control the path joining. ### Set tag insertion position The final insertion position of the tag is determined by the `head` and `append` options, and two elements with the same configuration will be inserted into the same area and hold their relative positions to each other. * `append`: used to describe whether the tag is added to the end or beginning of the original tags * `head`: used to describe whether to add this tag to the HTML `` The final insertion position on the page is as follows: ```html ``` ## Tags handler ```ts type HtmlTagContext = { hash: string; entryName: string; outputName: string; publicPath: string; }; type HtmlTagHandler = ( tags: HtmlTag[], context: HtmlTagContext, ) => HtmlTag[] | void; ``` `html.tags` can also accept functions that can arbitrarily modify tags by writing logic to the callback, often used to ensure the relative position of tags while inserting them. The callback function accepts a tag list as an argument and needs to modify or return a new tag array directly. ```ts export default { html: { tags: [ (tags) => [{ tag: 'script', attrs: { src: 'a.js' } }, ...tags], (tags) => { // Modify 'a.js' tag const target = tags.find((tag) => tag.attrs?.src === 'a.js'); if (target) { target.attrs ||= {}; target.attrs.defer = true; } }, (tags) => { // Insert 'b.js' after 'a.js' const targetIndex = tags.findIndex((tag) => tag.attrs?.src === 'a.js'); tags.splice(targetIndex + 1, 0, { tag: 'script', attrs: { src: 'd.js' }, }); }, ], }, }; ``` The HTML file will look like: ```html ``` ## Limitation This configuration is used to modify the content of HTML files after Rsbuild completes building, and does not resolve or parse new modules. It cannot be used to import un-compiled source code files. Also cannot replace configurations such as [source.preEntry](/config/source/pre-entry.md). For example, for the following project: ``` web-app ├── src │ ├── index.tsx │ └── polyfill.ts └── rsbuild.config.ts ``` ```ts title="rsbuild.config.ts" export default { output: { assetPrefix: 'https://example.com/', }, html: { tags: [{ tag: 'script', attrs: { src: './src/polyfill.ts' } }], }, }; ``` The tag object here will be directly added to the HTML file after processing, but the `polyfill.ts` will not be transpiled or bundled, so there will be a 404 error when processing this script in the application. ```html ``` Reasonable use cases include: * Injecting static assets with **determined paths** on CDN. * Injecting inline scripts that need to be loaded on the first screen. For example, the usage of the following example: ``` web-app ├── src │ └── index.tsx ├── public │ └── service-worker.js └── rsbuild.config.ts ``` ```ts title="rsbuild.config.ts" function report() { fetch('https://www.example.com/report'); } export default { html: { output: { assetPrefix: 'https://example.com/', }, tags: [ // Inject asset from the `public` directory. { tag: 'script', attrs: { src: 'service-worker.js' } }, // Inject asset from other CDN url. { tag: 'script', publicPath: false, attrs: { src: 'https://cdn.example.com/foo.js' }, }, // Inject inline script. { tag: 'script', children: report.toString() + '\nreport()', }, ], }, }; ``` The result will seems like: ```html ``` --- url: /config/html/template-parameters.md --- # html.templateParameters * **Type:** `Record | Function` * **Default:** ```ts type DefaultParameters = { mountId: string; // the value of `html.mountId` config entryName: string; // entry name assetPrefix: string; // the value of dev.assetPrefix or output.assetPrefix configs compilation: Compilation; // Compilation object of Rspack rspackConfig: Rspack.Configuration; // Rspack config object // generated by html-rspack-plugin htmlPlugin: { tags: { headTags: HtmlTagObject[]; bodyTags: HtmlTagObject[]; }; files: { publicPath: string; js: Array; css: Array; favicon?: string; }; }; }; ``` Define the parameters in the HTML template, see [HTML Template - Template Parameters](/guide/basic/html-template.md#template-parameters) for detailed usage. ## Object usage If the value of `templateParameters` is an object, it will be merged with the default parameters using `Object.assign`. For example, if you need to use the `foo` parameter in an HTML template, you can add the following settings: ```js export default { html: { templateParameters: { foo: 'bar', }, }, }; ``` Then, you can read the parameter in the HTML template using `<%= foo %>`: ```html ``` The compiled HTML code will be: ```html ``` ## Function usage * **Type:** ```ts type TemplateParametersFunction = ( defaultValue: Record, utils: { entryName: string }, ) => Record | void; ``` When `html.templateParameters` is of type Function, the function receives two parameters: * `value`: Default `templateParameters` configuration of Rsbuild. * `utils`: An object containing the `entryName` field, corresponding to the name of the current entry. In the context of a multi-page application (MPA), you can set different `templateParameters` based on the entry name: ```js export default { html: { templateParameters(defaultValue, { entryName }) { const params = { foo: { ...defaultValue, type: 'Foo', }, bar: { ...defaultValue, type: 'Bar', hello: 'world', }, }; return params[entryName] || defaultValue; }, }, }; ``` --- url: /config/html/template.md --- # html.template * **Type:** `string | Function` Specifies the file path for the HTML template, which can be a relative or absolute path. If `template` is not specified, the built-in HTML template of Rsbuild will be used by default: ```html
``` ## String usage For example, to replace the default HTML template with the `static/index.html` file, you can add the following configuration: ```js export default { html: { template: './static/index.html', }, }; ``` ## Function usage * **Type:** ```ts type TemplateFunction = ({ value: string; entryName: string }) => string | void; ``` When `html.template` is of type Function, the function receives an object as an argument, with the following properties: * `value`: the default template configuration of Rsbuild. * `entryName`: the name of the current entry. In the MPA (multi-page application) scenario, you can return different `template` paths based on the entry name, thus setting different templates for each page: ```js export default { html: { template({ entryName }) { const templates = { foo: './static/foo.html', bar: './static/bar.html', }; return templates[entryName] || './static/index.html'; }, }, }; ``` --- url: /config/html/title.md --- # html.title * **Type:** `string | Function` * **Default:** `'Rsbuild App'` Set the title tag of the HTML page. :::tip If the HTML template used in the current project already includes the `` tag, the `html.title` will not take effect. ::: ## String usage `html.title` can be directly set as a string: ```js export default { html: { title: 'Example', }, }; ``` The `title` tag generated in HTML will be: ```html <title>Example ``` ## Function usage * **Type:** ```ts type TitleFunction = ({ value: string; entryName: string }) => string | void; ``` When `html.title` is of type Function, the function receives an object as the argument, and the object's values include: * `value`: the default title configuration of Rsbuild. * `entryName`: the name of the current entry. In the MPA (multi-page application) scenario, you can return different `title` strings based on the entry name, thus generating different `title` tags for each page: ```js export default { html: { title({ entryName }) { const titles = { foo: 'Foo Page', bar: 'Bar Page', }; return titles[entryName] || 'Other Page'; }, }, }; ``` ## Unset `` tag When `html.title` is set to an empty string, Rsbuild will not inject the `<title>` tag: ```js export default { html: { title: '', }, }; ``` --- url: /config/server/base.md --- # server.base * **Type:** `string` * **Default:** `/` * **Version:** `>= 1.0.10` `server.base` is used to configure the [base path](/guide/basic/server.md#base-path) of the server. ## Example By default, the Rsbuild server's base path is `/`. You can access output files like `index.html` and assets in the [public folder](/guide/basic/static-assets.md#public-folder) through `http://localhost:3000/`. If you want to access `index.html` through `http://localhost:3000/foo/`, you can change `server.base` to `/foo`. ```ts export default { server: { base: '/foo', }, }; ``` ## URL prefix of assets By default, [dev.assetPrefix](/config/dev/asset-prefix.md) and [output.assetPrefix](/config/output/asset-prefix.md) will read the value of `server.base` as the default value. When `server.base` is `/foo`, the default resource URL loaded in the browser is as follows: ```html <script defer src="/foo/static/js/index.js"></script> ``` Then, `index.html` and static assets can be accessed through `http://localhost:3000/foo/`. If you do not want to use this default behavior, you can override it by explicitly setting `dev.assetPrefix` / `output.assetPrefix` : ```ts export default { dev: { assetPrefix: '/', }, output: { assetPrefix: 'https://cdn.example.com/assets/', }, server: { base: '/foo', }, }; ``` --- url: /config/server/compress.md --- # server.compress * **Type:** `boolean` * **Default:** `true` Configure whether to enable [gzip compression](https://developer.mozilla.org/en-US/docs/Glossary/gzip_compression) for static assets served by the dev server or preview server. ## Disable To disable the gzip compression, set `compress` to `false`: ```ts title="rsbuild.config.ts" export default { server: { compress: false, }, }; ``` ## Compression level Rsbuild dev server uses [zlib.constants.Z\_BEST\_SPEED](https://nodejs.org/api/zlib.html#constants) as the default compression level, which provides the best compression performance. The preview server sets `level` to `6` by default. Note that in actual production environments, web servers like Nginx or Apache are commonly used, which may utilize different compression levels. Therefore, you might observe differences between the file sizes after gzip compression in your local environment compared to production. --- url: /config/server/cors.md --- # server.cors * **Type:** `boolean | import('cors').CorsOptions` ```ts const defaultCorsOptions = { // Default allowed: // - localhost // - 127.0.0.1 // - [::1] origin: /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/, }; ``` * **Version:** `>= 1.1.11` Configure [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) options for the dev server or preview server, based on the [cors](https://github.com/expressjs/cors) middleware. * `object`:Enable CORS with the specified options. * `true`:Enable CORS with default options (allow all origins, not recommended). * `false`:Disable CORS. :::warning Using `cors: true` or `cors.origin: '*'` exposes your dev server to all origins, potentially compromising your source code security. It is recommended to use [origin](#origin) option to specify an allowlist of trusted origins instead. ::: ## Example * Enable CORS for a specific origin: ```ts title="rsbuild.config.ts" export default { server: { cors: { // Configures the `Access-Control-Allow-Origin` CORS response header origin: 'https://example.com', }, }, }; ``` * Only enable CORS for the dev server: ```ts title="rsbuild.config.ts" const isDev = process.env.NODE_ENV === 'development'; export default { server: { cors: isDev ? { origin: 'https://example.com' } : false, }, }; ``` * Disable CORS: ```ts title="rsbuild.config.ts" export default { server: { cors: false, }, }; ``` * Enable CORS for all origins (not recommended): ```ts title="rsbuild.config.ts" export default { server: { // Equivalent to `{ origin: '*' }` cors: true, }, }; ``` ## Options The `cors` option can be an object, which is the same as the [cors](https://github.com/expressjs/cors) middleware options. The default configuration is the equivalent of: ```js const defaultOptions = { origin: '*', methods: 'GET,HEAD,PUT,PATCH,POST,DELETE', preflightContinue: false, optionsSuccessStatus: 204, }; ``` ### origin * **Type:** ```ts type StaticOrigin = | boolean | string | RegExp | Array<boolean | string | RegExp>; type CustomOrigin = ( requestOrigin: string | undefined, callback: (err: Error | null, origin?: StaticOrigin) => void, ) => void; type Origin = StaticOrigin | CustomOrigin; ``` The `origin` option is used to configure the `Access-Control-Allow-Origin` header: ```ts title="rsbuild.config.ts" export default { server: { cors: { origin: 'https://example.com', }, }, }; ``` Specify multiple allowed origins using an array: ```ts title="rsbuild.config.ts" export default { server: { cors: { origin: [ /^https?:\/\/(?:(?:[^:]+\.)?localhost|127\.0\.0\.1|\[::1\])(?::\d+)?$/, 'https://example.com', ], }, }, }; ``` Use a regular expression to allow all matching origins: ```ts title="rsbuild.config.ts" export default { server: { cors: { origin: /\.example\.com$/, }, }, }; ``` Setting `origin` to a function allows you to dynamically determine the allowed origin, the function receives two parameters: * `origin`:The origin of the incoming request, `undefined` if no origin is present. * `callback`:A function to set the allowed origin. ```ts title="rsbuild.config.ts" export default { server: { cors: { origin: (origin, callback) => { // loadMyOrigins is an example call to load a list of origins loadMyOrigins((error, origins) => { callback(error, origins); }); }, }, }, }; ``` --- url: /config/server/headers.md --- # server.headers * **Type:** `Record<string, string | string[]>` * **Default:** `undefined` Adds headers to all responses sent from Rsbuild server. This configuration directly leverages Node.js [response.setHeader()](https://nodejs.org/api/http.html#responsesetheadername-value) method under the hood. If the header already exists in the to-be-sent headers, its value will be overwritten. :::tip To set CORS headers like `Access-Control-Allow-Origin`, use [server.cors](/config/server/cors.md) option. If both `server.headers` and `server.cors` are used, `server.headers` will override `server.cors`. ::: ## Usage The `server.headers` option accepts an object where: * Keys are header names (case-insensitive) * Values are either a string or an array of strings ```ts title="rsbuild.config.ts" export default { server: { headers: { 'X-Custom-Foo': 'bar', }, }, }; ``` ## Multiple values Use an array of strings to send multiple headers with the same name. ```ts title="rsbuild.config.ts" export default { server: { headers: { // Multiple Set-Cookie headers 'Set-Cookie': ['type=ninja', 'language=javascript'], }, }, }; ``` --- url: /config/server/history-api-fallback.md --- # server.historyApiFallback * **Type:** `boolean | ConnectHistoryApiFallbackOptions` * **Default:** `false` When Rsbuild's default [page routing](/guide/basic/server.md#page-routing) behavior cannot meet your needs, for example, if you want to be able to access `main.html` when accessing `/`, you can achieve this through the `server.historyApiFallback` configuration. ## Example `server.historyApiFallback` is implemented based on [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback), and setting `server.historyApiFallback` to `true` is equivalent to using the default options of `connect-history-api-fallback`. ```ts title="rsbuild.config.ts" export default { server: { historyApiFallback: true, }, }; ``` By default, `connect-history-api-fallback` will redirect all HTML GET requests to `index.html`. ## Options `server.historyApiFallback` also supports passing an object to configure the behavior of `connect-history-api-fallback`. Here are some commonly used options, and more options and detailed information can be found in the [connect-history-api-fallback](https://github.com/bripkens/connect-history-api-fallback) documentation. ### index * **Type:** `string` * **Default:** `'index.html'` By setting `historyApiFallback.index` to `main.html`, when accessing the root path `/` or other routes that may result in a 404, the page will automatically redirect to `main.html`. ```ts title="rsbuild.config.ts" export default { source: { entry: { main: './src/index.ts', }, }, server: { htmlFallback: false, historyApiFallback: { index: '/main.html', }, }, }; ``` ### rewrites * **Type:** ```ts type Rewrites = Array<{ from: RegExp; to: string | RegExp | ((context: HistoryApiFallbackContext) => string); }>; ``` * **Default:** `[]` When your application contains multiple entries, you may need to redirect different paths to different pages. In this case, you can configure more flexible redirection rules through the `rewrites` option: ```ts title="rsbuild.config.ts" export default { server: { historyApiFallback: { rewrites: [ { from: /^\/$/, to: '/views/landing.html' }, { from: /^\/subpage/, to: '/views/subpage.html' }, { from: /./, to: '/views/404.html' }, ], }, }, }; ``` --- url: /config/server/host.md --- # server.host * **Type:** `string` * **Default:** `0.0.0.0` Specify the host that the Rsbuild server listens to. By default, the Rsbuild server will listen to `0.0.0.0`, which means listening to all IPv4 network interfaces, including `localhost` and public network addresses. You can use `server.host` or the `--host` CLI param to set the host (The priority of `--host` option is higher than `server.host`). If you want the Rsbuild server to listen only on `localhost`, you can set it to: ```ts export default { server: { host: 'localhost', }, }; ``` ## IPv6 Support If you want the Rsbuild server to listen all IPv6 network interfaces, you can set it to: ```ts export default { server: { host: '::', }, }; ``` If you want the Rsbuild server to listen a specified IPv6 host, you can set it to: ```ts export default { server: { host: '::1', }, }; ``` At this point, you can access the page via `http://[::1]:3000/`. --- url: /config/server/html-fallback.md --- # server.htmlFallback * **Type:** `false | 'index'` * **Default:** `'index'` Whether to enable HTML fallback. ## Default behavior By default, when the request meets the following conditions and the corresponding resource is not found, it will fallback to `index.html`: * The request is a `GET` or `HEAD` request * Which accepts `text/html` (the request header accept type is `text/html` or `*/*`) ```ts title="rsbuild.config.ts" export default { server: { htmlFallback: 'index', }, }; ``` ## Disable If you don't want to enable HTML fallback, you can set `server.htmlFallback` to `false`. ```ts title="rsbuild.config.ts" export default { server: { htmlFallback: false, }, }; ``` ## Customize If `server.htmlFallback` cannot meet your needs, you can use [server.historyApiFallback](/config/server/history-api-fallback.md) for more flexible settings. --- url: /config/server/https.md --- # server.https * **Type:** ```ts import type { ServerOptions } from 'node:https'; import type { SecureServerSessionOptions } from 'node:http2'; type Https = ServerOptions | SecureServerSessionOptions; ``` * **Default:** `undefined` Configure HTTPS options to enable HTTPS server. When enabled, HTTP server will be disabled. HTTP: ``` ➜ Local: http://localhost:3000/ ➜ Network: http://192.168.0.1:3000/ ``` HTTPS: ``` ➜ Local: https://localhost:3000/ ➜ Network: https://192.168.0.1:3000/ ``` :::tip Rsbuild enables HTTP/2 server by default. However, when you use [server.proxy](/config/server/proxy.md), the server will downgrade to HTTP/1, because the underlying `http-proxy` does not support HTTP/2. ::: ## Set certificate You can manually pass in the certificate and the private key required in the `server.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](https://nodejs.org/api/https.html#https_https_createserver_options_requestlistener). ```ts import fs from 'node:fs'; export default { server: { https: { key: fs.readFileSync('certificates/private.pem'), cert: fs.readFileSync('certificates/public.pem'), }, }, }; ``` :::tip The certificates used for local development are typically generated using [mkcert](https://github.com/FiloSottile/mkcert). Please read ["How to use HTTPS for local development"](https://web.dev/articles/how-to-use-local-https?hl=en) to learn how to use it. ::: ## Self-signed Certificate For basic configuration requirements, you can add the [@rsbuild/plugin-basic-ssl](https://github.com/rspack-contrib/rsbuild-plugin-basic-ssl) plugin, which will automatically create a self-signed certificate and set `server.https` option by default. ```ts import { pluginBasicSsl } from '@rsbuild/plugin-basic-ssl'; export default { plugins: [pluginBasicSsl()], }; ``` --- url: /config/server/middleware-mode.md --- # server.middlewareMode * **Type:** `boolean` * **Default:** `false` * **Version:** `>= 1.2.12` Whether to create Rsbuild's server in middleware mode, which is useful for integrating with other servers. When this option is enabled, Rsbuild will not create an HTTP server. This option is usually only needed when using the JavaScript API of Rsbuild. ## Example A typical use case is that you want to integrate the Rsbuild server into a custom server. You can achieve this by combining `server.middlewareMode` and [rsbuild.createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver). ```ts import { createRsbuild } from '@rsbuild/core'; import express from 'express'; async function startDevServer() { // Initialize Rsbuild in middleware mode 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 middlewares app.use(rsbuildServer.middlewares); } ``` > See [Integrate with custom server](/api/javascript-api/dev-server-api.md#integrate-with-custom-server) for more details. --- url: /config/server/open.md --- # server.open * **Type:** ```ts type Open = | boolean | string | string[] | { target?: string | string[]; before?: () => Promise<void> | void; }; ``` * **Default:** `undefined` `server.open` is used to configure a set of page URLs that Rsbuild will automatically open in the browser after starting the server. > You can also use the [--open](/guide/basic/cli.md#opening-page) option of Rsbuild CLI to open the pages. When using `server.open` and `--open` at the same time, `--open` takes precedence. ## Example `server.open` can be set to the following values. * Open the project's default preview page, which defaults to `http://localhost:<port>`. If [server.host](/config/server/host.md) is configured, it defaults to `http://<host>:<port>`. ```ts title="rsbuild.config.ts" export default { server: { open: true, }, }; ``` * Open the specified page: ```ts title="rsbuild.config.ts" export default { server: { open: 'http://localhost:3000', }, }; ``` * Open the specified path, equivalent to `http://localhost:<port>/home`: ```ts title="rsbuild.config.ts" export default { server: { open: '/home', }, }; ``` * Open multiple pages: ```ts title="rsbuild.config.ts" export default { server: { open: ['/', '/about'], }, }; ``` * Open a non-localhost URL (used with proxy): ```ts title="rsbuild.config.ts" export default { server: { open: 'http://www.example.com', }, }; ``` ## Port placeholder The port number that Rsbuild server listens on may change. For example, if the port is in use, Rsbuild will automatically increment the port number until it finds an available port. To avoid `server.open` becoming invalid due to port changes, you can use one of the following methods: * Enable [server.strictPort](/config/server/strict-port.md). * Use the `<port>` placeholder to refer to the current port number. Rsbuild will replace the placeholder with the actual port number it is listening on. ```ts title="rsbuild.config.ts" export default { server: { open: 'http://localhost:<port>/home', }, }; ``` ## Specify browser Rsbuild opens pages in the system default browser by default, and also supports specifying which browser to use when starting the dev server through the `BROWSER` environment variable. ### Browser name Rsbuild uses the [open](https://github.com/sindresorhus/open) library to open browsers, and supports opening Chrome, Edge, and Firefox: ```bash # Chrome BROWSER=chrome npx rsbuild dev # Edge BROWSER=edge npx rsbuild dev # Firefox BROWSER=firefox npx rsbuild dev ``` On Windows, use [cross-env](https://npmjs.com/package/cross-env) to set environment variables: ```bash npm i cross-env -D cross-env BROWSER=chrome npx rsbuild dev ``` You can also refer to the [app option](https://github.com/sindresorhus/open?tab=readme-ov-file#app) of `open` to configure more special `BROWSER` values, such as some OS-specific browser names: ```bash # macOS BROWSER="google chrome" npx rsbuild dev # Linux BROWSER="google-chrome" npx rsbuild dev ``` ### Browser arguments Pass browser arguments through `BROWSER_ARGS`, with multiple arguments separated by spaces: ```bash BROWSER=chrome BROWSER_ARGS="--incognito" npx rsbuild dev ``` ### AppleScript On macOS, Rsbuild also supports opening the browser through AppleScript, which allows you to reuse existing browser tabs to open pages. The following are the browser names supported by AppleScript: * Google Chrome Canary * Google Chrome Dev * Google Chrome Beta * Google Chrome * Microsoft Edge * Brave Browser * Vivaldi * Chromium For example: ```bash BROWSER="Google Chrome Canary" npx rsbuild dev ``` ### Configure env variable You can set the `BROWSER` environment variable in the local [.env.local](/guide/advanced/env-vars.md#env-file) file, so you don't need to manually set the environment variable every time you start the dev server, and it also avoids affecting other developers in the project. ```bash # .env.local BROWSER=chrome ``` ## Callback By using `open.before`, you can trigger a callback function before opening the page. ```ts title="rsbuild.config.ts" export default { server: { open: { before: async () => { await doSomeThing(); }, }, }, }; ``` When using `open.before`, the page URLs can be configured via `open.target`. ```ts title="rsbuild.config.ts" export default { server: { open: { target: ['/', '/about'], before: async () => { await doSomeThing(); }, }, }, }; ``` --- url: /config/server/port.md --- # server.port * **Type:** `number` * **Default:** `3000` Specify a port number for Rsbuild server to listen. By default, Rsbuild server listens on port `3000` and automatically increments the port number when the port is occupied. If you enable the [server.strictPort](/config/server/strict-port.md) config, Rsbuild server will throw an error instead of incrementing the port number when the port is occupied. Rsbuild CLI provides the [--port](/guide/basic/cli.md#rsbuild-dev) option to set the port number, and the `--port` option has higher priority than `server.port` config. ```bash npx rsbuild dev --port 8080 ``` ## Example Set the port to `8080`: ```ts export default { server: { port: 8080, }, }; ``` Set different port numbers for development and preview servers: ```ts export default { server: { port: process.env.NODE_ENV === 'development' ? 3000 : 8080, }, }; ``` --- url: /config/server/print-urls.md --- # server.printUrls * **Type:** ```ts type Routes = Array<{ entryName: string; pathname: string; }>; type PrintUrls = | boolean | ((params: { urls: string[]; port: number; routes: Routes; protocol: string; }) => string[] | void); ``` * **Default:** `true` Controls whether and how server URLs are printed when the server starts. By default, when you start the dev server or preview server, Rsbuild will print the following logs: ``` ➜ Local: http://localhost:3000 ➜ Network: http://192.168.0.1:3000 ``` ## Custom logging `server.printUrls` can be set to a function, with parameters including `port`, `protocol`, `urls` and `routes`. ### Modify URL If the `printUrls` function returns an URLs array, Rsbuild prints these URLs to the terminal in the default format: ```ts title="rsbuild.config.ts" export default { server: { printUrls({ urls }) { return urls.map((url) => `${url}/base/`); }, }, }; ``` Output: ``` ➜ Local: http://localhost:3000/base/ ➜ Network: http://192.168.0.1:3000/base/ ``` ### Fully customizable If the `printUrls` function does not return a value, Rsbuild will not print the server's URL addresses. You can customize the log content based on the parameters and output it to the terminal yourself. ```ts title="rsbuild.config.ts" export default { server: { printUrls({ urls, port, protocol }) { console.log(urls); // ['http://localhost:3000', 'http://192.168.0.1:3000'] console.log(port); // 3000 console.log(protocol); // 'http' or 'https' }, }, }; ``` ### MPA output If the current project contains multiple pages, you can generate a separate URL for each page based on the `routes` parameter. For example, when the project contains two pages, `index` and `detail`, the content of the `routes` would be: ```ts title="rsbuild.config.ts" export default { server: { printUrls({ routes }) { /** * [ * { entryName: 'index', pathname: '/' }, * { entryName: 'detail', pathname: '/detail' } * ] */ console.log(routes); }, }, }; ``` ## Disable output Setting `server.printUrls` to `false` will prevent Rsbuild from printing the server URLs. ```ts title="rsbuild.config.ts" export default { server: { printUrls: false, }, }; ``` ### HTML disabled If [tools.htmlPlugin](/config/tools/html-plugin.md) is set to `false`, Rsbuild will not generate HTML files or output the server URL. However, you can still print the server URLs using the `server.printUrls` function, which has a higher priority. ```ts title="rsbuild.config.ts" export default { tools: { htmlPlugin: false, }, server: { printUrls: ({ port }) => [`http://localhost:${port}`], }, }; ``` Output: ``` ➜ Local: http://localhost:3000 ``` --- url: /config/server/proxy.md --- # server.proxy * **Type:** `Record<string, string> | Record<string, ProxyOptions> | ProxyOptions[] | ProxyOptions` * **Default:** `undefined` Configure proxy rules for the dev server or preview server to proxy requests to the specified service. ## Example ### Basic usage ```js export default { server: { proxy: { // http://localhost:3000/api -> http://localhost:3000/api // http://localhost:3000/api/foo -> http://localhost:3000/api/foo '/api': 'http://localhost:3000', }, }, }; ``` A request to `/api/users` will now proxy the request to http://localhost:3000/api/users. You can also proxy to an online domain name, such as: ```js export default { server: { proxy: { // http://localhost:3000/api -> https://nodejs.org/api // http://localhost:3000/api/foo -> https://nodejs.org/api/foo '/api': 'https://nodejs.org', }, }, }; ``` ### Path rewrite If you don't want `/api` to be passed along, we need to rewrite the path: ```js export default { server: { proxy: { // http://localhost:3000/api -> http://localhost:3000 // http://localhost:3000/api/foo -> http://localhost:3000/foo '/api': { target: 'http://localhost:3000', pathRewrite: { '^/api': '' }, }, }, }, }; ``` ### Proxy WebSocket To proxy WebSocket requests, you can enable it through set `ws` to `true`: ```js export default { server: { proxy: { '/rsbuild-hmr': { target: 'http://localhost:3000', // will proxy to ws://localhost:3000/rsbuild-hmr ws: true, }, }, }, }; ``` ## Options The Rsbuild server proxy makes use of the [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware/tree/2.x) package. Check out its documentation for more advanced usages. The full type definition of Rsbuild server proxy is: ```ts import type { Options as HttpProxyOptions } from 'http-proxy-middleware'; type Filter = string | string[] | ((pathname: string, req: Request) => boolean); type ProxyOptions = HttpProxyOptions & { bypass?: ( req: IncomingMessage, res: ServerResponse, proxyOptions: ProxyOptions, ) => MaybePromise<string | undefined | null | boolean>; context?: Filter; }; type ProxyConfig = | ProxyOptions | ProxyOptions[] | Record<string, string> | Record<string, ProxyOptions>; ``` In addition to the `http-proxy-middleware` option, Rsbuild also support the `bypass` and `context` options. ### bypass Sometimes you don't want to proxy everything. It is possible to bypass the proxy based on the return value of a `bypass` function. In the function, you get access to the request, response, and proxy options. * Return `null` or `undefined` to continue processing the request with proxy. * Return `true` to continue processing the request without proxy. * Return `false` to produce a 404 error for the request. * Return a path to serve from, instead of continuing to proxy the request. * Return a Promise to handle the request asynchronously. E.g. for a browser request, you want to serve an HTML page, but for an API request, you want to proxy it. You could configure like this: ```ts title="rsbuild.config.ts" export default { server: { proxy: { '/api': { target: 'http://localhost:3000', bypass(req, res, proxyOptions) { if (req.headers.accept.indexOf('html') !== -1) { console.log('Skipping proxy for browser request.'); return '/index.html'; } }, }, }, }, }; ``` ### context Used to proxy multiple specified paths to the same target. ```js export default { server: { proxy: [ { context: ['/auth', '/api'], target: 'http://localhost:3000', }, ], }, }; ``` --- url: /config/server/public-dir.md --- # server.publicDir * **Type:** ```ts type PublicDirOptions = { name?: string; copyOnBuild?: boolean | 'auto'; watch?: boolean; }; type PublicDir = false | PublicDirOptions | PublicDirOptions[]; ``` * **Default:** ```js const defaultValue = { name: 'public', copyOnBuild: 'auto', watch: false, }; ``` By default, Rsbuild will use the `public` directory as the directory for serving public assets, files in this directory will be served at [server.base](/config/server/base.md) path (default `/`). > Related document: [Public Folder](/guide/basic/static-assets.md#public-folder). ## Options ### name * **Type:** `string` * **Default:** `'public'` The name of the public directory. The value of `name` can be set to a relative path or an absolute path. Relative path will be resolved relative to the project root directory. * Relative path example: ```ts export default { server: { publicDir: { name: '../some-public', }, }, }; ``` * Absolute path example: ```ts import path from 'node:path'; export default { server: { publicDir: { name: path.join(__dirname, '../some-public'), }, }, }; ``` ### copyOnBuild * **Type:** `boolean | 'auto'` * **Default:** `'auto'` Whether to copy files from the public directory to the dist directory on production build. * `true`: copy files. * `false`: do not copy files. * `'auto'`: if [output.target](/config/output/target.md) is not `'node'`, copy files, otherwise do not copy. :::tip During dev builds, if you need to copy some static assets to the output directory, you can use the [output.copy](/config/output/copy.md) option instead. ::: #### Disable For example, disable `copyOnBuild`: ```ts export default { server: { publicDir: { copyOnBuild: false, }, }, }; ``` Note that setting the value of `copyOnBuild` to false means that when you run `rsbuild preview` for a production preview, you will not be able to access the corresponding static resources. #### Node target By default, when [output.target](/config/output/target.md) is `'node'`, Rsbuild will not copy files from the public directory. You can set `copyOnBuild` to `true` to copy files for the `node` target: ```ts export default { output: { target: 'node', }, server: { publicDir: { copyOnBuild: true, }, }, }; ``` #### Multiple environments When performing [multi-environment builds](/guide/advanced/environments.md), Rsbuild copies files from the public directory to the output directory of each environment. If there are nested output directories, files will only be copied to the root of the output directory. For example: * The distDir of the `web` environment is `dist`, and the distDir of the `web1` environment is `dist/web1`. Due to the nested relationship between `dist` and `dist/web1`, at this time, the public directory files are only copied to the `dist` directory. * The distDir of the `esm` environment is `dist/esm`, and the distDir of the `cjs` environment is `dist/cjs`. Since there is no nesting relationship between `dist/esm` and `dist/cjs`, at this time, the public directory files will be copied to the `dist/esm` and `dist/cjs` directories respectively. ### watch * **Type:** `boolean` * **Default:** `false` Whether to watch the public directory and reload the page when the files change. Setting `watch` to `true` allows the dev server to watch changes to files in the specified public directory and reload the page when the files are changed: ```ts export default { server: { publicDir: { watch: true, }, }, }; ``` Note that the `watch` option is only valid in development mode. If [dev.hmr](/config/dev/hmr.md) and [dev.liveReload](/config/dev/live-reload.md) are both set to false, `watch` will be ignored. ## Multiple directories The `server.publicDir` can be configured as an array, allowing you to serve multiple directories as static assets folders: ```ts export default { server: { publicDir: [ { name: 'public', }, { name: 'assets', watch: false, }, ], }, }; ``` ## Disabled You can set `publicDir` to `false` to disable the static assets serving: ```ts export default { server: { publicDir: false, }, }; ``` --- url: /config/server/strict-port.md --- # server.strictPort * **Type:** `boolean` * **Default:** `false` When a port is occupied, Rsbuild will automatically increment the port number until an available port is found. Set `strictPort` to `true` and Rsbuild will throw an exception when the port is occupied. ## Example ```ts export default { server: { strictPort: true, }, }; ``` --- url: /config/security/nonce.md --- # security.nonce * **Type:** ```ts type Nonce = string; ``` * **Default:** `undefined` Adding a `nonce` attribute to the scripts resources introduced for HTML. This allows the browser to determine whether the script can be executed when it parses inline scripts with matching nonce values. ## What is nonce The nonce mechanism plays a crucial role in Content Security Policy (CSP), enhancing webpage security. It allows developers to define a unique and random string value, i.e., nonce, for inline `<script>` tags and `<style>` tags within CSP. When the browser parses inline scripts with matching nonce values, it allows them to be executed or applied, otherwise CSP will prevent them from running. This effectively prevents potential Cross-Site Scripting (XSS) attacks. It's worth noting that a new nonce value should be generated each time the page is accessed. For more information about nonce, you can refer to: * [nonce - MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/nonce) * [webpack - Content Security Policies](https://webpack.js.org/guides/csp/) ## Example By default, `nonce` is not enabled by Rsbuild, you can define this value based on your needs: ```js export default { security: { nonce: 'CSP_NONCE_PLACEHOLDER', }, }; ``` Typically, we can define a fixed value in the project, and replace it with a random value on downstream servers such as Nginx, Web Server, gateway, etc. ## Scope of effect The `security.nonce` config adds the nonce attribute to the following tags: * All `<script>` tags generated by Rsbuild * All `<style>` tags generated by Rsbuild * All [`<link rel="preload" as="script">`](/config/performance/preload.md) tags generated by Rsbuild * Dynamic `<script>` tags generated by Rspack (implemented by the [\_\_webpack\_nonce\_\_](https://rspack.dev/api/runtime-api/module-variables#__webpack_nonce__) variable) For `<script>` or `<style>` tags that already exist in the HTML template file, Rsbuild will not modify them. You can directly add the `nonce` attribute in the template. For `<script>` or `<style>` tags inserted dynamically via JavaScript, you also need to set the `nonce` attribute yourself. --- url: /config/security/sri.md --- # security.sri * **Type:** ```ts type SriOptions = { enable?: 'auto' | boolean; algorithm?: 'sha256' | 'sha384' | 'sha512'; }; ``` * **Default:** `undefined` Adding an `integrity` attribute to `<script>` and `<link>` tags introduced by HTML allows the browser to verify the integrity of the introduced resource, thus preventing tampering with the downloaded resource. > `security.sri` is implemented based on Rspack's [SubresourceIntegrityPlugin](https://rspack.dev/plugins/rspack/subresource-integrity-plugin) ## What is SRI Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match. For `<script>` tags, the result is to refuse to execute the code; for CSS links, the result is not to load the styles. For more on subresource integrity, see [Subresource Integrity - MDN](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity). ## Example When using SRI, you need to enable [html.crossorigin](/config/html/crossorigin.md), which ensures that resources can be properly validated with SRI during cross-origin loading. ```ts export default { security: { sri: { enable: 'auto', }, }, html: { crossorigin: 'anonymous', }, }; ``` :::tip If you do not set `html.crossorigin`, Rsbuild will automatically set it to `anonymous`. ::: After enabling `security.sri`, the `<script>` and `<link>` tags generated by Rsbuild will include the `integrity` and `crossorigin` attributes: ```html <script defer src="https://cdn.com/static/js/index.js" crossorigin="anonymous" integrity="sha384-d8fhhhTWXaPPIEMw+POJ9hqCIRvsFbegq/oef7k9R8Rpb8Dy95B2THPOECdZoLDF" ></script> <link href="https://cdn.com/static/css/index.css" rel="stylesheet" crossorigin="anonymous" integrity="sha384-8U9HYzsHbf55cFZyiWIE29+QPYQ9WO+U5uT/ViFw0TOwM2Fbbb74ZegzRV/nvwrD" /> ``` ## Note The `security.sri` in Rsbuild will only apply to the tags generated by Rspack and Rsbuild and will not apply to: * The original tags in the HTML template. * The tags inserted through client JavaScript code. Rsbuild will handle the following `<link>` tags: * `<link rel="preload">` * `<link rel="stylesheet">` * `<link rel="modulepreload">` ## Options ### enable * **Type:** `'auto' | boolean` * **Default:** `false` Whether to enable SRI. `'auto'` means it's enabled in production mode and disabled in development mode. ```ts export default { security: { sri: { enable: 'auto', }, }, }; ``` > Typically, you do not need to enable SRI in development mode. ### algorithm * **Type:** `'sha256' | 'sha384' | 'sha512'` * **Default:** `'sha384'` Specifies the algorithm used to compute the integrity hash. For example, set to `sha512`: ```ts export default { security: { sri: { algorithm: 'sha512', }, }, }; ``` The generated value of integrity attribute will be prefixed with `sha512-`: ```html <script defer src="https://cdn.com/static/js/index.js" crossorigin="anonymous" integrity="sha512-ShExVSs5q/j3ZBI/PeS0niJ4mBxh6tc08QN1uofI1dmGAx7ETMh8/VDddGRewxXQhjCgdgAnaiY3BfnWrUSmZA==" ></script> ``` > Reference: [Cryptographic hash functions](https://www.w3.org/TR/SRI/#cryptographic-hash-functions). --- url: /config/tools/bundler-chain.md --- # tools.bundlerChain * **Type:** ```ts type BundlerChainFn = ( chain: RspackChain, utils: ModifyBundlerChainUtils, ) => Promise<void> | void; ``` * **Default:** `undefined` You can use rspack-chain to modify the default Rspack config through `tools.bundlerChain`. Its value is a function that takes two arguments: * The first argument is a `rspack-chain` instance, which you can use to modify the Rspack config. * The second argument is an utils object, including `env`, `isProd`, `CHAIN_ID`, etc. > `tools.bundlerChain` will be executed earlier than [tools.rspack](/config/tools/rspack.md), so it will be overridden by `tools.rspack`. :::tip The built-in Rspack config in Rsbuild may change with iterations, and these changes won't be reflected in semver. Therefore, your custom config may become invalid when you upgrade Rsbuild. ::: ## Examples Please refer to: [RspackChain examples](/guide/configuration/rspack.md#use-rspack-chain). ## Utils ### env * **Type:** `'development' | 'production' | 'test'` The `env` parameter can be used to determine whether the current environment is development, production or test. For example: ```js export default { tools: { bundlerChain: (chain, { env }) => { if (env === 'development') { chain.devtool('cheap-module-eval-source-map'); } }, }, }; ``` ### isDev * **Type:** `boolean` Used to determine whether the current build is a development build, such as: ```js export default { tools: { bundlerChain: (config, { isDev }) => { if (isDev) { config.devtool = 'eval-cheap-source-map'; } return config; }, }, }; ``` ### isProd * **Type:** `boolean` Used to determine whether the current build is a production build, such as: ```js export default { tools: { bundlerChain: (chain, { isProd }) => { if (isProd) { chain.devtool('source-map'); } }, }, }; ``` ### target * **Type:** `'web' | 'node' | 'web-worker'` The `target` parameter can be used to determine the build target environment. For example: ```js export default { tools: { bundlerChain: (chain, { target }) => { if (target === 'node') { // ... } }, }, }; ``` ### isServer * **Type:** `boolean` Determines whether the target environment is `node`, equivalent to `target === 'node'`. ```js export default { tools: { bundlerChain: (chain, { isServer }) => { if (isServer) { // ... } }, }, }; ``` ### isWebWorker * **Type:** `boolean` Determines whether the target environment is `web-worker`, equivalent to `target === 'web-worker'`. ```js export default { tools: { bundlerChain: (chain, { isWebWorker }) => { if (isWebWorker) { // ... } }, }, }; ``` ### rspack * **Type:** `Rspack` The Rspack instance. For example: ```js export default { tools: { bundlerChain: (chain, { rspack }) => { chain.plugin('extra-define').use(rspack.DefinePlugin, [ { 'process.env': { NODE_ENV: JSON.stringify(process.env.NODE_ENV), }, }, ]); }, }, }; ``` ### HtmlPlugin * **Type:** `typeof import('html-rspack-plugin')` The default export of [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). ```js export default { tools: { bundlerChain: (chain, { HtmlPlugin }) => { console.log(HtmlPlugin); }, }, }; ``` ## CHAIN\_ID Some common Chain IDs are predefined in the Rsbuild, and you can use these IDs to locate the built-in Rule or Plugin. :::tip Please note that some of the rules or plugins listed below are not available by default. They will only be included in the Rspack or webpack configuration when you enable specific options or register certain plugins. For example, the `RULE.STYLUS` rule exists only when the Stylus plugin is registered. ::: ### CHAIN\_ID.RULE | ID | Description | | ------------- | ------------------------------------------------------------------------- | | `RULE.JS` | Rule for `js` and `ts` | | `RULE.SVG` | Rule for `svg` | | `RULE.CSS` | Rule for `css` | | `RULE.LESS` | Rule for `less` | | `RULE.SASS` | Rule for `sass` | | `RULE.YAML` | Rule for `yaml` | | `RULE.WASM` | Rule for `WASM` | | `RULE.FONT` | Rule for `font` | | `RULE.IMAGE` | Rule for `image` | | `RULE.MEDIA` | Rule for `media` | | `RULE.VUE` | Rule for `vue` (requires [Vue plugin](/plugins/list/plugin-vue.md)) | | `RULE.SVELTE` | Rule for `svelte` (requires [Svelte plugin](/plugins/list/plugin-svelte.md)) | | `RULE.STYLUS` | Rule for `stylus` (requires [Stylus plugin](/plugins/list/plugin-stylus.md)) | ### CHAIN\_ID.ONE\_OF `ONE_OF.[ID]` can match a certain type of rule in the rule array. | ID | Description | | ------------------- | ------------------------------------------------------------------ | | `ONE_OF.SVG_URL` | Rules for SVG, output as a separate file | | `ONE_OF.SVG_INLINE` | Rules for SVG, inlined into bundles as data URIs | | `ONE_OF.SVG_ASSETS` | Rules for SVG, automatic choice between data URI and separate file | ### CHAIN\_ID.USE `USE.[ID]` can match a certain loader. | ID | Description | | ----------------- | -------------------------------------------------------------------------------------- | | `USE.SWC` | correspond to `builtin:swc-loader` | | `USE.STYLE` | correspond to `style-loader` | | `USE.POSTCSS` | correspond to `postcss-loader` | | `USE.LESS` | correspond to `less-loader` (requires [Less plugin](/plugins/list/plugin-less.md)) | | `USE.SASS` | correspond to `sass-loader` (requires [Sass plugin](/plugins/list/plugin-sass.md)) | | `USE.RESOLVE_URL` | correspond to `resolve-url-loader` (requires [Sass plugin](/plugins/list/plugin-sass.md)) | | `USE.VUE` | correspond to `vue-loader` (requires [Vue plugin](/plugins/list/plugin-vue.md)) | | `USE.SVGR` | correspond to `svgr-loader` (requires [Svgr plugin](/plugins/list/plugin-svgr.md)) | | `USE.BABEL` | correspond to `babel-loader` (requires [Babel plugin](/plugins/list/plugin-babel.md)) | | `USE.SVELTE` | correspond to `svelte-loader` (requires [Svelte plugin](/plugins/list/plugin-svelte.md)) | | `USE.STYLUS` | correspond to `stylus-loader` (requires [Stylus plugin](/plugins/list/plugin-stylus.md)) | ### CHAIN\_ID.PLUGIN `PLUGIN.[ID]` can match a certain Rspack or webpack plugin. | ID | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `PLUGIN.HTML` | correspond to [HtmlRspackPlugin](https://rspack.dev/plugins/rspack/html-rspack-plugin), you need to concat the entry name when using: `${PLUGIN.HTML}-${entryName}` | | `PLUGIN.SUBRESOURCE_INTEGRITY` | correspond to [SubresourceIntegrityPlugin](https://rspack.dev/plugins/rspack/subresource-integrity-plugin) | | `PLUGIN.BUNDLE_ANALYZER` | correspond to [BundleAnalyzerPlugin](https://github.com/webpack-contrib/webpack-bundle-analyzer) | ### CHAIN\_ID.MINIMIZER `MINIMIZER.[ID]` can match a certain minimizer. | ID | Description | | --------------- | -------------------------------------------------------------------------------------------------------------------------- | | `MINIMIZER.JS` | correspond to [SwcJsMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/swc-js-minimizer-rspack-plugin) | | `MINIMIZER.CSS` | correspond to [LightningCssMinimizerRspackPlugin](https://rspack.dev/plugins/rspack/lightning-css-minimizer-rspack-plugin) | --- url: /config/tools/css-extract.md --- # tools.cssExtract * **Type:** ```ts import type { CssExtractRspackPluginOptions, CssExtractRspackLoaderOptions, } from '@rspack/core'; type CSSExtractOptions = { pluginOptions?: CssExtractRspackPluginOptions; loaderOptions?: CssExtractRspackLoaderOptions; }; ``` * **Default:** ```js const defaultOptions = { pluginOptions: { ignoreOrder: true, // The default value is determined by the output.distPath and output.filename options of Rsbuild filename: 'static/css/[name].css', chunkFilename: 'static/css/async/[name].css', }, loaderOptions: {}, }; ``` * **Version:** `>= 0.7.0` Rsbuild uses the CssExtractRspackPlugin plugin by default to extract CSS into separate files. The options for [CssExtractRspackPlugin](https://rspack.dev/plugins/rspack/css-extract-rspack-plugin) can be changed through `tools.cssExtract`. ## pluginOptions * **Type:** `CssExtractRspackPluginOptions` * **Example:** ```js export default { tools: { cssExtract: { pluginOptions: { ignoreOrder: false, }, }, }, }; ``` ## loaderOptions * **Type:** `CssExtractRspackLoaderOptions` * **Example:** ```js export default { tools: { cssExtract: { loaderOptions: { esModule: false, }, }, }, }; ``` > Please refer to the [CssExtractRspackPlugin](https://rspack.dev/plugins/rspack/css-extract-rspack-plugin) plugin documentation to learn about all available options. --- url: /config/tools/css-loader.md --- # tools.cssLoader * **Type:** `Object | Function` ```js const defaultOptions = { modules: rsbuildConfig.output.cssModules, sourceMap: rsbuildConfig.output.sourceMap.css, }; ``` Rsbuild uses [css-loader](https://github.com/webpack-contrib/css-loader) by default to handle CSS resources. You can modify the options of css-loader through `tools.cssLoader`. :::tip To modify the options related to CSS Modules, it is recommended to use the [output.cssModules](/config/output/css-modules.md) config first. ::: ### Object type When this value is an Object, it is merged with the default config via deep merge. For example: ```js export default { tools: { cssLoader: { modules: { exportOnlyLocals: true, }, }, }, }; ``` ### Function type When the value is a Function, the default config is passed in as the first parameter. You can modify the config object directly, or return an object as the final config. For example: ```js export default { tools: { cssLoader: (config) => { config.modules.exportOnlyLocals = true; return config; }, }, }; ``` --- url: /config/tools/html-plugin.md --- # tools.htmlPlugin * **Type:** `boolean | Object | Function` * **Default:** ```js const defaultOptions = { meta, // Corresponds to `html.meta` config title, // Corresponds to `html.title` config inject, // Corresponds to `html.inject` config favicon, // Corresponds to `html.favicon` config template, // Corresponds to `html.template` config filename, // Generated based on `output.distPath` and `entryName` templateParameters, // Corresponds to `html.templateParameters` config chunks: [entryName], }; ``` The configs of [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin) can be modified through `tools.htmlPlugin`. Rsbuild internally implements HTML-related features based on [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). It is a fork of [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin), with the same features and options. :::tip If you need to modify options such as `title`, `template`, `templateParameters`, `meta`, it is recommended to use the corresponding HTML configurations provided by Rsbuild first, such as [html.title](/config/html/title.md), [html .template](/config/html/template.md) etc. This is because Rsbuild provides some internal optimization processing for these HTML configurations. For example, if the HTML template used by the current project already contains the `<title>` tag, then `html.title` will not take effect. ::: ## Object type When `tools.htmlPlugin` is `Object` type, the value will be merged with the default config via `Object.assign`. ```js export default { tools: { htmlPlugin: { scriptLoading: 'blocking', }, }, }; ``` ## Function type When `tools.htmlPlugin` is a Function: * The first parameter is the default config, which can be modified directly. * The second parameter is also an object, containing the entry name and the entry value. * The Function can return a new object as the final config. ```js export default { tools: { htmlPlugin(config, { entryName, entryValue }) { if (entryName === 'main') { config.scriptLoading = 'blocking'; } }, }, }; ``` ## Disable HTML Setting `tools.htmlPlugin` to `false` can disable the built-in `html-rspack-plugin` in Rsbuild, and no HTML files will be generated. ```js export default { tools: { htmlPlugin: false, }, }; ``` ## Example ### Modify HTML file name The `filename` option can be used to modify the file name of the HTML output. For example, in production mode, a `hash` can be added to the file name: ```js export default { tools: { htmlPlugin(config, { entryName }) { if (process.env.NODE_ENV === 'production') { config.filename = `${entryName}.[contenthash:8].html`; } }, }, }; ``` ## HTML minification Rsbuild currently does not minify HTML files. To minify HTML files, use the [rsbuild-plugin-html-minifier-terser plugin](https://github.com/rspack-contrib/rsbuild-plugin-html-minifier-terser). --- url: /config/tools/lightningcss-loader.md --- # tools.lightningcssLoader * **Type:** `Rspack.LightningcssLoaderOptions | Function | boolean` * **Default:** ```ts const defaultOptions = { errorRecovery: true, // use current project's browserslist config targets: browserslist, // minify is enabled when output.injectStyles is true and in production mode minify: config.mode === 'production' && config.output.injectStyles, }; ``` You can set the options for [builtin:lightningcss-loader](https://rspack.dev/guide/features/builtin-lightningcss-loader) through `tools.lightningcssLoader`. ## Object type When `tools.lightningcssLoader` is an object, it will be merged with the default configuration using `Object.assign`. For example, you can disable the addition of vendor prefixes through `tools.lightningcssLoader.exclude`. In this case, you can use PostCSS's autoprefixer plugin to add vendor prefixes. ```js export default { tools: { lightningcssLoader: { exclude: { vendorPrefixes: false, }, }, }, }; ``` ## Function type When `tools.lightningcssLoader` is a function, the default options will be passed in as the first parameter. You can directly modify this object or return a new object as the final options to be used. For example: ```js export default { tools: { lightningcssLoader: (config) => { config.exclude = { vendorPrefixes: false, }; return config; }, }, }; ``` ## Disable loader Set `tools.lightningcssLoader` to `false` to disable the built-in `lightningcss-loader` in Rsbuild: ```js export default { tools: { lightningcssLoader: false, }, }; ``` :::tip Set `tools.lightningcssLoader` to `false` only disables the `lightningcss-loader`. If you need to disable the full functionality of Lightning CSS, please refer to [Disabling Lightning CSS](/guide/styling/css-usage.md#disabling-lightning-css). ::: --- url: /config/tools/postcss.md --- # tools.postcss * **Type:** `Object | Function` * **Default:** ```js const defaultOptions = { postcssOptions: { config: false, sourceMap: rsbuildConfig.output.sourceMap.css, }, }; ``` Rsbuild integrates PostCSS by default, you can configure [postcss-loader](https://github.com/webpack-contrib/postcss-loader) through `tools.postcss`. ## Function type When `tools.postcss` is a function, the default options will be passed in as the first parameter. You can directly modify this object or return a new object as the final options to be used. For example: For example, to add a PostCSS plugin, you can call the [addPlugins](#addplugins) utility function: ```ts export default { tools: { postcss: (opts, { addPlugins }) => { addPlugins(require('postcss-px-to-viewport')); }, }, }; ``` To pass parameters to the PostCSS plugin, call the PostCSS plugin as a function: ```js export default { tools: { postcss: (opts, { addPlugins }) => { const viewportPlugin = require('postcss-px-to-viewport')({ viewportWidth: 375, }); addPlugins(viewportPlugin); }, }, }; ``` You can also modify the default `postcss-loader` options: ```ts export default { tools: { postcss: (opts) => { opts.sourceMap = false; }, }, }; ``` `tools.postcss` can return a config object and completely replace the default config: ```js export default { tools: { postcss: () => { return { postcssOptions: { plugins: [require('postcss-px-to-viewport')], }, }; }, }, }; ``` ## Object type When `tools.postcss` is an object, it will be merged with the default configuration using `Object.assign`. Note that `Object.assign` is a shallow copy and will completely overwrite the built-in `presets` or `plugins` array, please use it with caution. ```js export default { tools: { postcss: { // As `Object.assign` is used, the default postcssOptions will be overwritten. postcssOptions: { plugins: [require('postcss-px-to-viewport')], }, }, }, }; ``` ## Utils ### addPlugins * **Type:** `(plugins: PostCSSPlugin | PostCSSPlugin[]) => void` For adding additional PostCSS plugins, You can pass in a single PostCSS plugin, or an array of PostCSS plugins. ```js export default { tools: { postcss: (config, { addPlugins }) => { // Add a PostCSS Plugin addPlugins(require('postcss-preset-env')); // Add multiple PostCSS Plugins addPlugins([require('postcss-preset-env'), require('postcss-import')]); }, }, }; ``` ## Practice ### Multiple PostCSS options `tools.postcss.postcssOptions` can be set to a function, which receives the Rspack's `loaderContext` as a parameter. This allows you to use different PostCSS options for different file paths. For example, use `postcss-plugin-a` for file paths containing `foo`, and use `postcss-plugin-b` for other file paths: ```js export default { tools: { postcss: { postcssOptions: (loaderContext) => { if (/foo/.test(loaderContext.resourcePath)) { return { plugins: [require('postcss-plugin-a')], }; } return { plugins: [require('postcss-plugin-b')], }; }, }, }, }; ``` :::tip If the project contains a `postcss.config.*` config file, its content will be merged with `tools.postcss.postcssOptions`, and the latter's priority is higher. The `plugins` array will be merged into a single array. ::: ## Notes ### PostCSS version Rsbuild uses the PostCSS v8. When you use third-party PostCSS plugins, please pay attention to whether the PostCSS version is compatible. Some legacy plugins may not work in PostCSS v8. ### PostCSS config loading Rsbuild uses [postcss-load-config](https://github.com/postcss/postcss-load-config) to load PostCSS config files and merge them with the default config. Rsbuild internally sets the `postcss-loader`'s `postcssOptions.config` option to `false` to avoid loading config files repeatedly. --- url: /config/tools/rspack.md --- # tools.rspack * **Type:** `Rspack.Configuration | Function | undefined` * **Default:** `undefined` `tools.rspack` is used to configure [Rspack](https://rspack.dev/config/index). :::tip The built-in Rspack config in Rsbuild may change with iterations, and these changes won't be reflected in semver. Therefore, your custom config may become invalid when you upgrade Rsbuild. ::: ## Object type `tools.rspack` can be configured as an object to be deep merged with the built-in Rspack configuration through [webpack-merge](https://github.com/survivejs/webpack-merge). For example, add `resolve.alias` configuration: ```js export default { tools: { rspack: { resolve: { alias: { '@util': 'src/util', }, }, }, }, }; ``` When merging configurations, `webpack-merge` will automatically concatenate arrays such as `plugins`, `module.rules`, `resolve.extensions`, etc. ```js export default { tools: { rspack: { resolve: { // merged with the built-in resolve.extensions extensions: ['.foo'], }, }, }, }; ``` If you need to override a configuration rather than merge it with the default value, you can use the function type of `tools.rspack`. ## Function type `tools.rspack` can be configured as a function. The first parameter of this function is the built-in Rspack configuration object, you can modify this object, and then return it. For example: ```js export default { tools: { rspack: (config) => { config.resolve ||= {}; config.resolve.alias ||= {}; config.resolve.alias['@util'] = 'src/util'; return config; }, }, }; ``` :::tip The object returned by the `tools.rspack` function is used directly as the final Rspack configuration and is not merged with the built-in Rspack configuration. ::: `tools.rspack` can also be an async function: ```js export default { tools: { rspack: async (config) => { const { default: ESLintPlugin } = await import('eslint-webpack-plugin'); config.plugins?.push(new ESLintPlugin()); return config; }, }, }; ``` ## Utils The second parameter of this function is an object, which contains some utility functions and properties, as follows: ### env * **Type:** `'development' | 'production' | 'test'` The `env` parameter can be used to determine whether the current environment is development, production or test. For example: ```js export default { tools: { rspack: (config, { env }) => { if (env === 'development') { config.devtool = 'cheap-module-eval-source-map'; } return config; }, }, }; ``` ### isDev * **Type:** `boolean` Used to determine whether the current build is a development build, such as: ```js export default { tools: { rspack: (config, { isDev }) => { if (isDev) { config.devtool = 'eval-cheap-source-map'; } return config; }, }, }; ``` ### isProd * **Type:** `boolean` Used to determine whether the current build is a production build, such as: ```js export default { tools: { rspack: (chain, { isProd }) => { if (isProd) { chain.devtool('source-map'); } }, }, }; ``` ### target * **Type:** `'web' | 'node' | 'web-worker'` The `target` parameter can be used to determine the build target environment. For example: ```js export default { tools: { rspack: (config, { target }) => { if (target === 'node') { // ... } return config; }, }, }; ``` ### isServer * **Type:** `boolean` Determines whether the target environment is `node`, equivalent to `target === 'node'`. ```js export default { tools: { rspack: (config, { isServer }) => { if (isServer) { // ... } return config; }, }, }; ``` ### isWebWorker * **Type:** `boolean` Determines whether the target environment is `web-worker`, equivalent to `target === 'web-worker'`. ```js export default { tools: { rspack: (config, { isWebWorker }) => { if (isWebWorker) { // ... } return config; }, }, }; ``` ### rspack * **Type:** `Rspack` The Rspack instance. For example: ```js export default { tools: { rspack: (config, { rspack }) => { config.plugins?.push(new rspack.BannerPlugin()); return config; }, }, }; ``` ### HtmlPlugin * **Type:** `typeof import('html-rspack-plugin')` The default export of [html-rspack-plugin](https://github.com/rspack-contrib/html-rspack-plugin). ```js export default { tools: { rspack: (config, { HtmlPlugin }) => { console.log(HtmlPlugin); }, }, }; ``` ### addRules * **Type:** `(rules: RuleSetRule | RuleSetRule[]) => void` Add additional [Rspack rules](https://rspack.dev/config/module#modulerules) to the head of the internal Rspack module rules array. It should be noted that Rspack loaders will be executed in right-to-left order. If you want the loader you added to be executed before other loaders (Normal Phase), you should use [appendRules](#appendrules) to add the rule to the end. For example: ```ts export default { tools: { rspack: (config, { addRules }) => { // add a single rule addRules({ test: /\.foo/, loader: require.resolve('foo-loader'), }); // Add multiple rules as an array addRules([ { test: /\.foo/, loader: require.resolve('foo-loader'), }, { test: /\.bar/, loader: require.resolve('bar-loader'), }, ]); }, }, }; ``` ### appendRules * **Type:** `(rules: RuleSetRule | RuleSetRule[]) => void` Add additional [Rspack rules](https://rspack.dev/config/module#modulerules) to the end of the internal Rspack module rules array. For example: ```ts export default { tools: { rspack: (config, { appendRules }) => { // add a single rule appendRules({ test: /\.foo/, loader: require.resolve('foo-loader'), }); // Add multiple rules as an array appendRules([ { test: /\.foo/, loader: require.resolve('foo-loader'), }, { test: /\.bar/, loader: require.resolve('bar-loader'), }, ]); }, }, }; ``` ### prependPlugins * **Type:** `(plugins: BundlerPluginInstance | BundlerPluginInstance[]) => void` Add additional plugins to the head of the internal Rspack plugins array, and the plugin will be executed first. ```ts export default { tools: { rspack: (config, { prependPlugins }) => { // add a single plugin prependPlugins(new PluginA()); // Add multiple plugins prependPlugins([new PluginA(), new PluginB()]); }, }, }; ``` ### appendPlugins * **Type:** `(plugins: BundlerPluginInstance | BundlerPluginInstance[]) => void` Add additional plugins at the end of the internal Rspack plugins array, the plugin will be executed last. ```ts export default { tools: { rspack: (config, { appendPlugins }) => { // add a single plugin appendPlugins([new PluginA()]); // Add multiple plugins appendPlugins([new PluginA(), new PluginB()]); }, }, }; ``` ### removePlugin * **Type:** `(name: string) => void` Remove the internal Rspack plugin, the parameter is the `constructor.name` of the plugin. For example, remove the internal [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer): ```ts export default { tools: { rspack: (config, { removePlugin }) => { removePlugin('BundleAnalyzerPlugin'); }, }, }; ``` ### mergeConfig * **Type:** `(...configs:Rspack.Configuration[]) =>Rspack.Configuration` Used to merge multiple Rspack configs, same as [webpack-merge](https://github.com/survivejs/webpack-merge). ```ts export default { tools: { rspack: (config, { mergeConfig }) => { return mergeConfig(config, { devtool: 'eval', }); }, }, }; ``` :::tip The mergeConfig method will create a new config object without modifying the original config object, so you need to return the result of mergeConfig. ::: --- url: /config/tools/style-loader.md --- # tools.styleLoader * **Type:** `Object | Function` * **Default:** `{}` The config of [style-loader](https://github.com/webpack-contrib/style-loader) can be set through `tools.styleLoader`. It is worth noting that Rsbuild does not enable `style-loader` by default. You can use [output.injectStyles](/config/output/inject-styles.md) config to enable it. ## Object type When `tools.styleLoader` is an object, it will be merged with the default configuration using `Object.assign`. ```js export default { tools: { styleLoader: { insert: 'head', }, }, }; ``` ## Function type When `tools.styleLoader` is a function, the default options will be passed in as the first parameter. You can directly modify this object or return a new object as the final options to be used. For example: ```js export default { tools: { styleLoader: (config) => { config.insert = 'head'; return config; }, }, }; ``` --- url: /config/tools/swc.md --- # tools.swc * **Type:** `Object | Function` * **Default:** ```js const defaultOptions = { jsc: { externalHelpers: true, parser: { tsx: false, syntax: 'typescript', decorators: true, }, }, isModule: 'unknown', // ...some other conditional options }; ``` You can set the options of [builtin:swc-loader](https://rspack.dev/guide/features/builtin-swc-loader) through `tools.swc`. > Refer to [Configure SWC](/guide/configuration/swc.md) for more details. ## Object type `tools.swc` can be configured as an object, this object will be deeply merged with the built-in `builtin:swc-loader` option. ```js export default { tools: { swc: { jsc: { externalHelpers: false, }, }, }, }; ``` ## Function type `tools.swc` can also be configured as a function, this function takes one argument, which is the built-in `builtin:swc-loader` option. You can modify this object then return a new config. For example: ```js export default { tools: { swc: (config) => { config.jsc ||= {}; config.jsc.externalHelpers = false; return config; }, }, }; ``` :::tip The object returned by the `tools.swc` function will be used directly as the final `builtin:swc-loader` option, and will not be merged with the built-in `builtin:swc-loader` option anymore. ::: --- url: /config/performance/build-cache.md --- # performance.buildCache * **Type:** ```ts type BuildCacheConfig = | boolean | { cacheDirectory?: string; cacheDigest?: Array<string | undefined>; buildDependencies?: string[]; }; ``` * **Default:** `false` * **Version:** `>= 1.2.5` To enable or configure persistent build cache. When enabled, Rspack will store the build snapshots in the cache directory. In subsequent builds, if the cache is hit, Rspack can reuse the cached results instead of rebuilding from scratch, which can reduce the build time. :::tip Rspack's persistent cache is [experimental](https://rspack.dev/config/experiments#experimentscache) and may change in the future. ::: ## Enable cache Setting `performance.buildCache` to `true` will enable the persistent build cache: ```ts title="rsbuild.config.ts" export default { performance: { buildCache: true, }, }; ``` Or only enable cache in development mode: ```ts title="rsbuild.config.ts" const isDev = process.env.NODE_ENV === 'development'; export default { performance: { buildCache: isDev, }, }; ``` ## Options ### cacheDirectory * **Type:** `string` * **Default:** `node_modules/.cache` Set the output directory of the cache files. ```ts title="rsbuild.config.ts" import path from 'node:path'; export default { performance: { buildCache: { cacheDirectory: path.resolve(__dirname, 'node_modules/.my-cache'), }, }, }; ``` ### cacheDigest * **Type:** `Array<string | undefined>` * **Default:** `undefined` Add additional cache digests, the previous build cache will be invalidated when any value in the array changes. `cacheDigest` can be used to add some variables that will affect the build result, for example `process.env.SOME_ENV`. ```ts title="rsbuild.config.ts" export default defineConfig({ performance: { buildCache: { cacheDigest: [process.env.SOME_ENV], }, }, }); ``` ### buildDependencies * **Type:** `string[]` * **Default:** `undefined` `buildDependencies` is an arrays of additional code dependencies for the build. Rspack will use a hash of each of these items and all dependencies to invalidate the filesystem cache. Rsbuild will use the following configuration files as the default build dependencies: * `package.json` * `tsconfig.json` * `rsbuild.config.*` * `.browserslistrc` * `tailwindcss.config.*` When using Rsbuild CLI, it will also automatically add `.env` and `.env.*` files to the build dependencies. When you add other build dependencies, Rsbuild merges these custom dependencies with the default dependencies and passes them to Rspack. ```ts title="rsbuild.config.ts" export default { performance: { buildCache: { buildDependencies: [__filename], }, }, }; ``` --- url: /config/performance/bundle-analyze.md --- # performance.bundleAnalyze * **Type:** `Object | undefined` Used to enable the [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) plugin to analyze the size of the output. By default, Rsbuild does not enable `webpack-bundle-analyzer`. When this feature is enabled, the default configuration is as follows: ```js const defaultConfig = { analyzerMode: 'static', openAnalyzer: false, // Distinguish by environment names, such as `web`, `node`, etc. reportFilename: `report-${environment}.html`, }; ``` ## Enable bundle analyze You have two ways to enable `webpack-bundle-analyzer` to analyze the size of the output files. ### Via environment variable Add the environment variable `BUNDLE_ANALYZE=true`, for example: ```json title="package.json" { "scripts": { "build:analyze": "BUNDLE_ANALYZE=true rsbuild build" } } ``` As Windows does not support the above usage, you can also use [cross-env](https://npmjs.com/package/cross-env) to set environment variables. This ensures compatibility across different systems: ```json title="package.json" { "scripts": { "build:analyze": "cross-env BUNDLE_ANALYZE=true rsbuild build" }, "devDependencies": { "cross-env": "^7.0.0" } } ``` ### Via configuration Configure `performance.bundleAnalyze` to enable it permanently: ```js export default { performance: { bundleAnalyze: {}, }, }; ``` ### Analysis result After enabling it, Rsbuild will generate an HTML file that analyzes the size of the output files, and print the following log in the Terminal: ```bash Webpack Bundle Analyzer saved report to /Project/my-project/dist/report-web.html ``` You can manually open the file in the browser and view the detail of the bundle size. When an area is larger, it indicates that its corresponding bundle size is larger. ![](https://assets.rspack.dev/rsbuild/assets/bundle-analyzer-example.png) ## Override default configuration You can override the default configuration through `performance.bundleAnalyze`, such as enabling the server mode: ```js export default { performance: { bundleAnalyze: process.env.BUNDLE_ANALYZE ? { analyzerMode: 'server', openAnalyzer: true, } : {}, }, }; ``` ## Size types In the `webpack-bundle-analyzer` panel, you can control size types in the upper left corner (default is `Parsed`): * `Stat`: The size obtained from the `stats` object of the bundler, which reflects the size of the code before minification. * `Parsed`: The size of the file on the disk, which reflects the size of the code after minification. * `Gzipped`: The file size requested in the browser reflects the size of the code after minification and gzip. ## Generate stats.json By setting `generateStatsFile` to true, stats JSON file will be generated in bundle output directory. ```js export default { performance: { bundleAnalyze: { generateStatsFile: true, }, }, }; ``` In the output directory, you will see `stats.json` and `report-web.html` files. ``` └── dist ├── stats.json └── report-web.html ``` If you don't need the `report-web.html`, you can set `analyzerMode` to `disabled`. ```js export default { performance: { bundleAnalyze: { analyzerMode: 'disabled', generateStatsFile: true, }, }, }; ``` ## Notes 1. Enabling the server mode will cause the `build` process to not exit normally. 2. Enabling `bundleAnalyzer` will reduce build speed. Therefore, this configuration should not be enabled during daily development, and it is recommended to enable it on demand through the `BUNDLE_ANALYZE` environment variable. 3. Since no code minification and other optimizations are performed in the `dev` phase, the real output size cannot be reflected, so it is recommended to analyze the output size in the `build` phase. 4. If the bundleAnalyzer is enabled during the `dev` phase, in order to ensure that webpack-bundle-analyzer can access the contents of static assets, Rsbuild will automatically enable the [dev.writeToDisk](/config/dev/write-to-disk.md) option. --- url: /config/performance/chunk-split.md --- # performance.chunkSplit * **Type:** `ChunkSplit` * **Default:** `{ strategy: 'split-by-experience' }` `performance.chunkSplit` is used to configure the chunk splitting strategy. The type of `ChunkSplit` is as follows: ::: tip Please refer to the [Code Splitting](/guide/optimization/code-splitting.md) for the detailed usage. ::: ## chunkSplit.strategy Rsbuild supports the following chunk splitting strategies: * `split-by-experience`: an empirical splitting strategy, automatically splits some commonly used npm packages into chunks of moderate size. * `split-by-module`: split by NPM package granularity, each NPM package corresponds to a chunk. * `split-by-size`: automatically split according to module size. * `all-in-one`: bundle all codes into one chunk. * `single-vendor`: bundle all NPM packages into a single chunk. * `custom`: custom chunk splitting strategy. ## Type definition The type of `performance.chunkSplit` is as follows: ```ts type ForceSplitting = RegExp[] | Record<string, RegExp>; interface BaseChunkSplit { strategy?: | 'split-by-module' | 'split-by-experience' | 'all-in-one' | 'single-vendor'; override?: Rspack.OptimizationSplitChunksOptions; forceSplitting?: ForceSplitting; } interface SplitBySize extends BaseSplitRules { strategy: 'split-by-size'; minSize?: number; maxSize?: number; } interface SplitCustom extends BaseSplitRules { strategy: 'custom'; splitChunks?: SplitChunks; } type ChunkSplit = BaseChunkSplit | SplitBySize | SplitCustom; ``` ### Default strategy By default, Rsbuild uses the `split-by-experience` strategy. To use other chunk splitting strategies, specify them through the `strategy` option, for example: ```js export default { performance: { chunkSplit: { strategy: 'all-in-one', }, }, }; ``` ## chunkSplit.minSize * **Type:** `number` * **Default:** `10000` When `chunkSplit.strategy` is `split-by-size`, you can specify the minimum size of a chunk via `chunkSplit.minSize`, the unit is bytes. The default value is `10000`. For example: ```js export default { performance: { chunkSplit: { strategy: 'split-by-size', minSize: 20000, }, }, }; ``` ## chunkSplit.maxSize * **Type:** `number` * **Default:** `Number.POSITIVE_INFINITY` When `chunkSplit.strategy` is `split-by-size`, you can specify the maximum size of a chunk via `chunkSplit.maxSize`, the unit is bytes. The default value is `Number.POSITIVE_INFINITY`. For example: ```js export default { performance: { chunkSplit: { strategy: 'split-by-size', maxSize: 50000, }, }, }; ``` ## chunkSplit.forceSplitting * **Type:** `RegExp[] | Record<string, RegExp>` * **Default:** `[]` Via `chunkSplit.forceSplitting`, you can specify the NPM packages that need to be forced to split. For example, split the `axios` library under node\_modules into `axios.js`: ```js export default { performance: { chunkSplit: { forceSplitting: { axios: /node_modules[\\/]axios/, }, }, }, }; ``` This is an easier way than configuring Rspack's [splitChunks](https://rspack.dev/config/optimization#optimizationsplitchunks) directly. :::tip Chunks split using the `forceSplitting` configuration will be inserted into the HTML file as resources requested for the initial screen using `<script>` tags. Therefore, please split them appropriately based on the actual scenario to avoid excessive size of initial screen resources. ::: ## chunkSplit.splitChunks When `chunkSplit.strategy` is `custom`, you can specify the custom Rspack chunk splitting config via `chunkSplit.splitChunks`. This config will be merged with the Rspack splitChunks config (the `cacheGroups` config will also be merged). For example: ```js export default { performance: { chunkSplit: { strategy: 'custom', splitChunks: { cacheGroups: { react: { test: /node_modules[\\/](react|react-dom)[\\/]/, name: 'react', chunks: 'all', }, }, }, }, }, }; ``` ## chunkSplit.override When `chunkSplit.strategy` is `split-by-experience`, `split-by-module`, `split-by-size` or `single-vendor`, you can specify the custom Rspack chunk splitting config via `chunkSplit.override`. This config will be merged with the Rspack splitChunks config (the `cacheGroups` config will also be merged). For example: ```js export default { performance: { chunkSplit: { override: { cacheGroups: { react: { test: /node_modules[\\/](react|react-dom)[\\/]/, name: 'react', chunks: 'all', }, }, }, }, }, }; ``` ## Targets `performance.chunkSplit` only works when [output.target](/config/output/target.md) is `web`. This means that when `output.target` is `node` or `web-worker`, `performance.chunkSplit` will not take effect. Typically, Node bundles do not need to be split to optimize loading performance, if you need to split Node bundles, you can use the [tools.rspack](/config/tools/rspack.md) configuration to configure Rspack's [optimization.splitChunks](https://rspack.dev/plugins/webpack/split-chunks-plugin#optimizationsplitchunks) option: ```ts export default { tools: { rspack: { optimization: { splitChunks: { // options }, }, }, }, }; ``` --- url: /config/performance/dns-prefetch.md --- # performance.dnsPrefetch * **Type:** `string[] | undefined` * **Default:** `undefined` Injects [`<link rel="dns-prefetch">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/dns-prefetch) tags into the HTML file. ## When to use When a browser requests a resource from a (third party) server, that cross-origin's domain name must be resolved to an IP address before the browser can issue the request. This process is known as DNS resolution. While DNS caching can help to reduce this latency, DNS resolution can add significant latency to requests. Configuring `dns-prefetch` can resolve the domain before requesting resources, reducing request latency and improving loading performance. For more information, please refer to: [Using dns-prefetch](https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch). ## Example ```js export default { performance: { dnsPrefetch: ['https://example.com'], }, }; ``` The generated HTML tag in HTML is: ```html <link rel="dns-prefetch" href="https://example.com" /> ``` ## Notes In general, a website should not configure more than 10 DNS prefetches. Using too many DNS prefetches can lead to performance issues because browsers have limits on the number of DNS requests they can maintain. Excessive DNS prefetching, or prefetching for domains that are not ultimately used can cause resource contention and may reduce browser efficiency. For more details, refer to [What Is a DNS Prefetch?](https://www.splunk.com/en_us/blog/learn/dns-prefetch.html). --- url: /config/performance/preconnect.md --- # performance.preconnect * **Type:** ```ts type Preconnect = | Array< | string | { href: string; crossorigin?: boolean; } > | undefined; ``` * **Default:** `undefined` Injects [`<link rel="preconnect">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/preconnect) tags into the HTML file. ## When to use The `preconnect` keyword for the rel attribute of the `<link>` element is a hint to browsers that the user is likely to need resources from the target resource's origin, and therefore the browser can likely improve the user experience by preemptively initiating a connection to that origin. Preconnecting speeds up future loads from a given origin by preemptively performing part or all of the handshake (DNS+TCP for HTTP, and DNS+TCP+TLS for HTTPS origins). `<link rel="preconnect">` will provide a benefit to any future cross-origin HTTP request, navigation or subresource. It has no benefit on same-origin requests because the connection is already open. If a page needs to make connections to many third-party domains, preconnecting them all can be counterproductive. The `<link rel="preconnect">` hint is best used for only the most critical connections. For the others, just use [`<link rel="dns-prefetch">`](/config/performance/dns-prefetch.md) to save time on the first step — the DNS lookup. ## Example ```js export default { performance: { preconnect: ['https://example.com/'], }, }; ``` The generated HTML tag is: ```html <link ref="preconnect" href="https://example.com" /> ``` ## Options ### href * **Type:** `string` * **Default:** `undefined` Specify the URL to preconnect to. ```js export default { performance: { // Equivalent to `preconnect: ['https://example.com/'],` preconnect: [ { href: 'https://example.com/', }, ], }, }; ``` ### crossorigin * **Type:** `boolean` * **Default:** `false` Specify whether to add the `crossorigin` attribute. ```js export default { performance: { preconnect: [ { href: 'https://example.com/', crossorigin: true, }, ], }, }; ``` The generated HTML tag is: ```html <link rel="preconnect" href="https://example.com" crossorigin /> ``` :::tip Refer to this [link](https://webmasters.stackexchange.com/questions/89466/when-should-i-use-the-crossorigin-attribute-on-a-preconnect-link) to understand the use cases of the `crossorigin` attribute. ::: --- url: /config/performance/prefetch.md --- # performance.prefetch * **Type:** `undefined | true | PrefetchOptions` ```ts interface PrefetchOptions { type?: ResourceHintsIncludeType; include?: ResourceHintsFilter; exclude?: ResourceHintsFilter; } ``` * **Default:** `undefined` Inject the [`<link rel="prefetch">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/prefetch) tags for the static assets generated by Rsbuild. ## What is prefetch The prefetch keyword for the rel attribute of the `<link>` element provides a hint to browsers that the user is likely to need the target resource for future navigation, and therefore the browser can likely improve the user experience by preemptively fetching and caching the resource. ## Enable prefetch When `performance.prefetch` is set to `true`, Rsbuild will use the following default options to prefetch resources. This means prefetching all async resources on the current page, including async JS and its associated CSS, image, font, and other resources. ```js const defaultOptions = { type: 'async-chunks', }; ``` For example, if you dynamically import other modules in the entry file: ```js title="index.js" import('./foo'); import('./bar'); ``` The tags injected in HTML are as follows: ```html <html> <head> <title>Rsbuild App ``` ## Inject manually The `performance.prefetch` can only inject the prefetch tags for static resources generated by Rsbuild. If you need to prefetch other resources, you can manually add tags through [html.tags](/config/html/tags.md) : ```ts title="rsbuild.config.ts" export default { html: { tags: [ { tag: 'link', attrs: { rel: 'prefetch', href: 'https://example.com/some-script.js', }, }, ], }, }; ``` The injected HTML tag is as follows: ```html ``` ## Options `performance.prefetch` can be set to an object to specify the options. ### prefetch.type * **Type:** ` 'async-chunks' | 'initial' | 'all-assets' | 'all-chunks'` * **Default:** `'async-chunks'` Specify which types of resources will be included. Currently supported values are as follows: * `async-chunks`: Includes all async resources on the current page, such as async JS chunks, and its associated CSS, images, fonts, and other static resources. * `initial`: Includes all non-async resources on the current page. * `all-chunks`: Includes all async and non-async resources on the current page. * `all-assets`: Includes all resources from all pages. For example, to include all png images on the current page, configure it as follows: ```ts title="rsbuild.config.ts" export default { performance: { prefetch: { type: 'all-chunks', include: [/\.png$/], }, }, }; ``` :::tip If a script has been directly referenced via HTML ` ``` ## Inject manually The `performance.preload` can only inject the preload tags for static resources generated by Rsbuild. If you need to preload other resources, you can manually add tags through [html.tags](/config/html/tags.md) : ```ts title="rsbuild.config.ts" export default { html: { tags: [ { tag: 'link', attrs: { rel: 'preload', as: 'script', href: 'https://example.com/some-script.js', }, }, ], }, }; ``` The injected HTML tag is as follows: ```html ``` ## Options `performance.preload` can be set to an object to specify the options. ### preload.type * **Type:** ` 'async-chunks' | 'initial' | 'all-assets' | 'all-chunks'` * **Default:** `'async-chunks'` Specify which types of resources will be included. Currently supported values are as follows: * `async-chunks`: Includes all async resources on the current page, such as async JS chunks, and its associated CSS, images, fonts, and other static resources. * `initial`: Includes all non-async resources on the current page. * `all-chunks`: Includes all async and non-async resources on the current page. * `all-assets`: Includes all resources from all pages. For example, to include all png images on the current page, configure it as follows: ```ts title="rsbuild.config.ts" export default { performance: { preload: { type: 'all-chunks', include: [/\.png$/], }, }, }; ``` ### preload.include * **Type:** ```ts type ResourceHintsFilter = | string | RegExp | ((filename: string) => boolean) | Array boolean)>; ``` * **Default:** `undefined` A extra filter to determine which resources to include. * When `include` is a regular expression, it will be used directly to match the filename: ```ts title="rsbuild.config.ts" export default { performance: { preload: { // Match all .png files include: /\.png$/, }, }, }; ``` * When `include` is a string, it will be converted to a regular expression to match the filename: ```ts title="rsbuild.config.ts" export default { performance: { preload: { include: '\\.png', // equivalent to `new RegExp('\\.png')` }, }, }; ``` * When `include` is a function, it will be called with the filename as an argument: ```ts title="rsbuild.config.ts" export default { performance: { preload: { include: (filename) => filename.endsWith('.png'), }, }, }; ``` * When `include` is an array, it can contain multiple filters, and the filename only needs to match one of the filters to be included: ```ts title="rsbuild.config.ts" export default { performance: { preload: { include: [/\.png$/, '\\.jpg'], }, }, }; ``` ### preload.exclude * **Type:** ```ts type ResourceHintsFilter = | string | RegExp | ((filename: string) => boolean) | Array boolean)>; ``` * **Default:** `undefined` A extra filter to determine which resources to exclude, the usage is similar to `include`. ### preload.dedupe * **Type:** `boolean` * **Default:** `true` Whether to preload script resources that already exist in the current HTML content. By default, if a resource has been added to the current HTML via a script tag, it will not be preloaded additionally. ```ts title="rsbuild.config.ts" export default { performance: { preload: { dedupe: false, }, }, }; ``` --- url: /config/performance/print-file-size.md --- # performance.printFileSize * **Type:** ```ts type PrintFileSizeOptions = | boolean | { total?: boolean; detail?: boolean; compressed?: boolean; include?: (asset: PrintFileSizeAsset) => boolean; }; ``` * **Default:** `true` Whether to print the file sizes after production build. ## Default outputs The default output log is as follows: ``` File (web) Size Gzip dist/static/js/lib-react.b0714b60.js 140.4 kB 45.0 kB dist/static/js/index.f3fde9c7.js 1.9 kB 0.97 kB dist/index.html 0.39 kB 0.25 kB dist/static/css/index.2960ac62.css 0.35 kB 0.26 kB Total: 143.0 kB 46.3 kB ``` ## Disable outputs If you don't want to print any information, you can disable it by setting `printFileSize` to `false`: ```ts export default { performance: { printFileSize: false, }, }; ``` ## Options You can customize the output format through the options. ### total * **Type:** `boolean` * **Default:** `true` Whether to output the total size of all static assets. ```ts export default { performance: { printFileSize: { total: false, }, }, }; ``` :::tip If the current build only generates one static asset, the total size will not be printed. ::: ### detail * **Type:** `boolean` * **Default:** `true` Whether to output the size of each static asset. If you don't need to view the size of each static asset, you can set `detail` to false. In this case, only the total size will be output: ```ts export default { performance: { printFileSize: { detail: false, }, }, }; ``` ### compressed * **Type:** `boolean` * **Default:** `false` when [output.target](/config/output/target.md) is `node`, otherwise `true` Whether to output the gzip-compressed size of each static asset. If you don't need to view the gzipped size, you can set `compressed` to false. This can save some gzip computation time for large projects: ```ts export default { performance: { printFileSize: { compressed: false, }, }, }; ``` :::tip * This data is only for reference to the size after gzip compression. Rsbuild does not enable gzip compression for static assets. Usually, you need to enable gzip compression on the server side, for example, using the [gzip module](https://nginx.org/en/docs/http/ngx_http_gzip_module.html) of nginx. * For non-compressible assets (such as images), the gzip size will not be shown in the detailed list, but their original size will be included in the total gzip size calculation. ::: ### include * **Type:** ```ts type PrintFileSizeAsset = { /** * The name of the static asset. * @example 'index.html', 'static/js/index.[hash].js' */ name: string; /** * The size of the static asset in bytes. */ size: number; }; type Include = (asset: PrintFileSizeAsset) => boolean; ``` * **Default:** `undefined` A filter function to determine which static assets to print. If returned `false`, the static asset will be excluded and not included in the total size or detailed size. For example, only output static assets larger than 10kB: ```ts export default { performance: { printFileSize: { include: (asset) => asset.size > 10 * 1000, }, }, }; ``` Or only output `.js` files larger than 10kB: ```ts export default { performance: { printFileSize: { include: (asset) => /\.js$/.test(asset.name) && asset.size > 10 * 1000, }, }, }; ``` ### exclude * **Type:** ```ts type Exclude = (asset: PrintFileSizeAsset) => boolean; ``` * **Default:** `(asset) => /\.(?:map|LICENSE\.txt|d\.ts)$/.test(asset.name)` A filter function to determine which static assets to exclude. If both `include` and `exclude` are set, `exclude` will take precedence. Rsbuild defaults to excluding source map, license files, and `.d.ts` type files, as these files do not affect page load performance. For example, exclude `.html` files in addition to the default: ```ts export default { performance: { printFileSize: { exclude: (asset) => /\.(?:map|LICENSE\.txt)$/.test(asset.name) || /\.html$/.test(asset.name), }, }, }; ``` --- url: /config/performance/profile.md --- # performance.profile * **Type:** `boolean` * **Default:** `false` Whether capture timing information for each module, same as the [profile](https://rspack.dev/config/other-options#profile) config of Rspack. After enabled: * Rsbuild will auto-generate `dist/stats.json` file through [bundle analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer). * Rspack will include the build time information when generating stats.json or other statistics files. ## Example ```js export default { performance: { profile: true, }, }; ``` When enabled, Rspack generates a JSON file with some statistics about the module that includes information about timing information for each module. ## Guide Please refer to the [Build profiling](/guide/debug/build-profiling.md) page for more methods to analyze build performance. --- url: /config/performance/remove-console.md --- # performance.removeConsole * **Type:** `boolean | ConsoleType[]` * **Default:** `false` Whether to remove `console.[methodName]` in production build. ## Remove all When `removeConsole` is set to `true`, all types of `console.[methodName]` are removed: ```ts export default { performance: { removeConsole: true, }, }; ``` ## Specific type You can also specify to remove only certain types of `console.[methodName]`, such as `console.log` and `console.warn`: ```ts export default { performance: { removeConsole: ['log', 'warn'], }, }; ``` The following types of console are currently supported: ```ts type ConsoleType = 'log' | 'info' | 'warn' | 'error' | 'table' | 'group'; ``` --- url: /config/performance/remove-moment-locale.md --- # performance.removeMomentLocale * **Type:** `boolean` * **Default:** `false` Whether to remove the locales of [moment.js](https://momentjs.com/). `moment.js` contains a lot of locales by default, which will increase the bundle size. When `moment.js` is used in the project, it is recommended to enable this option to automatically exclude all locales: ```js export default { performance: { removeMomentLocale: true, }, }; ``` Once enabled, you can load a specific locale via: ```js import moment from 'moment'; import 'moment/locale/zh-cn'; moment.locale('zh-cn'); ``` --- url: /config/module-federation/options.md --- # moduleFederation.options * **Type:** [Rspack.ModuleFederationPluginOptions](https://rspack.dev/plugins/webpack/module-federation-plugin#options) * **Default:** `undefined` Used to configure the Rspack's Module Federation plugin (Module Federation v1.5). :::tip There are several versions of Module Federation implementations. Before using `moduleFederation.options`, please read the [Module Federation guide](/guide/advanced/module-federation.md) to understand the differences between different versions and how to make choices. ::: ## Introduction When using Module Federation, it is recommended that you use the `moduleFederation.options` option provided by Rsbuild. This option will automatically adjust some related configurations to ensure that the module federation application can run correctly. When you set the `moduleFederation.options` option, Rsbuild will take the following actions: * Automatically register the [ModuleFederationPlugin](https://rspack.dev/plugins/webpack/module-federation-plugin) plugin, and pass the value of `options` to the plugin. * Set the default value of the provider's [dev.assetPrefix](/config/dev/asset-prefix.md) configuration to `true`. This will ensure that the static asset URL is correct for remote modules. * Set the default value of Rspack's [output.uniqueName](https://rspack.dev/config/output#outputuniquename) configuration to `moduleFederation.options.name`, this allows HMR to work as expected. * Turn off the `split-by-experience` rules in Rsbuild's [performance.chunkSplit](/config/performance/chunk-split.md) as it may conflict with shared modules, refer to [#3161](https://github.com/module-federation/module-federation-examples/issues/3161). * Turn off the splitChunks rule of remote entry. ## Usage The type of `moduleFederation.options` is exactly the same as the ModuleFederationPlugin plugin of Rspack: ```ts title="rsbuild.config.ts" export default defineConfig({ moduleFederation: { options: { name: 'remote', // other options }, }, }); ``` Please refer to the [ModuleFederationPlugin](https://rspack.dev/plugins/webpack/module-federation-plugin) document for all available options. ## Example Here is a minimal example: * Remote App ```ts title="remote/rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ server: { port: 3002, }, moduleFederation: { options: { name: 'remote', exposes: { './Button': './src/Button', }, filename: 'remoteEntry.js', }, }, }); ``` * Host App ```ts title="host/rsbuild.config.ts" import { defineConfig } from '@rsbuild/core'; export default defineConfig({ server: { port: 3002, }, moduleFederation: { options: { name: 'host', remotes: { remote: 'remote@http://localhost:3002/remoteEntry.js', }, }, }, }); ``` For more examples, please see: * [Rsbuild - module-federation example](https://github.com/rspack-contrib/rstack-examples/tree/main/rsbuild/module-federation) * [module-federation/module-federation-examples](https://github.com/module-federation/module-federation-examples) --- url: /plugins/dev/index.md --- # Plugin system Rsbuild provides a lightweight yet powerful plugin system to implement most of its functionality and allows for user extension. Plugins written by developers can modify the default behavior of Rsbuild and add various additional features, including but not limited to: * Get context information * Register lifecycle hooks * Transform module source code * Modify Rspack configuration * Modify Rsbuild configuration * ... ## Comparison Before developing a Rsbuild plugin, you may have been familiar with the plugin systems of tools such as webpack, Vite, esbuild, etc. Generally, Rsbuild's plugin API is similar to esbuild, and compared with webpack or Rspack plugins, Rsbuild's plugin API is more simple and easier to get started with. ```ts // esbuild plugin const esbuildPlugin = { name: 'example', setup(build) { build.onEnd(() => console.log('done')); }, }; // Rsbuild plugin const rsbuildPlugin = () => ({ name: 'example', setup(api) { api.onAfterBuild(() => console.log('done')); }, }); // Rspack plugin class RspackExamplePlugin { apply(compiler) { compiler.hooks.done.tap('RspackExamplePlugin', () => { console.log('done'); }); } } ``` From a functional perspective, Rsbuild's plugin API mainly revolves around Rsbuild's operation process and build configuration and provides some hooks for extension. On the other hand, Rspack's plugin API is more complex and rich, capable of modifying every aspect of the bundling process. Rspack plugins can be integrated into Rsbuild plugins. If the hooks provided by Rsbuild do not meet your requirements, you can also implement the functionality using Rspack plugin and register Rspack plugins in the Rsbuild plugin: ```ts const rsbuildPlugin = () => ({ name: 'example', setup(api) { api.modifyRspackConfig((config) => { config.plugins?.push(new RspackExamplePlugin()); }); }, }); ``` ## Developing plugins Plugins provide a function similar to `(options?: PluginOptions) => RsbuildPlugin` as an entry point. ### Plugin example ```ts title="pluginFoo.ts" import type { RsbuildPlugin } from '@rsbuild/core'; export type PluginFooOptions = { message?: string; }; export const pluginFoo = (options: PluginFooOptions = {}): RsbuildPlugin => ({ name: 'plugin-foo', setup(api) { api.onAfterStartDevServer(() => { const msg = options.message || 'hello!'; console.log(msg); }); }, }); ``` Registering the plugin: ```ts title="rsbuild.config.ts" import { pluginFoo } from './pluginFoo'; export default { plugins: [pluginFoo({ message: 'world!' })], }; ``` ### Plugin structure Function-based plugins can **accept an options object** and **return a plugin instance**, managing internal state through closures. The roles of each part are as follows: * The `name` property is used to label the plugin's name. * `setup` serves as the main entry point for the plugin logic. * The `api` object contains various hooks and utility functions. ### Naming convention The naming convention for plugins is as follows: * The function of the plugin is named `pluginAbc` and exported by name. * The `name` of the plugin follows the format `scope:foo-bar` or `plugin-foo-bar`, adding `scope:` can avoid naming conflicts with other plugins. Here is an example: ```ts title="pluginFooBar.ts" import type { RsbuildPlugin } from '@rsbuild/core'; export const pluginFooBar = (): RsbuildPlugin => ({ name: 'scope:foo-bar', setup() {}, }); ``` :::tip The `name` of official Rsbuild plugins uniformly uses `rsbuild:` as a prefix, for example, `rsbuild:react` corresponds to `@rsbuild/plugin-react`. ::: ### Template repository [rsbuild-plugin-template](https://github.com/rspack-contrib/rsbuild-plugin-template) is a minimal Rsbuild plugin template repository that you can use as a basis for developing your Rsbuild plugin. ### Environment plugin Rsbuild supports building outputs for multiple environments at the same time, and supports [add plugins for specified environment](/guide/advanced/environments.md#add-plugins-for-specified-environment). If you want the plugin you develop to support use as an Environment plugin, you need to pay attention to the following points: 1. Each environment has its own Rsbuild config: * Use [environment context](/guide/advanced/environments.md#environment-context) instead of `getRsbuildConfig` to get environment information. * When modifying the Rsbuild config for a specific environment, prioritize using [modifyEnvironmentConfig](/plugins/dev/hooks.md#modifyenvironmentconfig) instead of [modifyRsbuildConfig](/plugins/dev/hooks.md#modifyrsbuildconfig) to avoid affecting other environments. 2. Be aware of side effects, your plugin code may be executed multiple times: * When the same plugin is registered multiple times in different environments, it will be regarded as multiple Rsbuild plugins (even if they point to the same plugin instance), because they have different Rsbuild environment contexts. Here is an example: ```ts title="pluginFoo.ts" import type { RsbuildPlugin } from '@rsbuild/core'; export type PluginFooOptions = { title?: string; }; export const pluginFoo = (options: PluginFooOptions = {}): RsbuildPlugin => ({ name: 'plugin-foo', setup(api) { api.modifyEnvironmentConfig((config) => { config.html.title = options.title || 'My Default Title'; }); api.modifyBundlerChain((chain, { environment }) => { chain.name(environment.config.html.title); }); }, }); ``` ### Reference other plugins Rsbuild's [plugins](/config/plugins.md) config supports passing a nested array, which means you can reference and register other Rsbuild plugins within your plugin. For example, register `pluginBar` within `pluginFoo`: ```ts import { pluginBar } from 'rsbuild-plugin-bar'; export const pluginFoo = (): RsbuildPlugin => { const foo = { name: 'plugin-foo', setup(api) { // ... }, }; return [foo, pluginBar()]; }; ``` ## Lifetime hooks Rsbuild uses lifetime planning work internally, and plugins can also register hooks to take part in any stage of the workflow and implement their own features. The full list of Rsbuild's lifetime hooks can be found in the [API References](/plugins/dev/hooks.md). The Rsbuild does not take over the hooks of the underlying Rspack, whose documents can be found here: [Rspack Plugin API](https://rspack.dev/api/plugin-api). ## Use Rsbuild config Custom plugins can usually get config from function parameters, just define and use it at your pleasure. But sometimes you may need to read and change the public config of the Rsbuild. To begin with, you should understand how the Rsbuild generates and uses its config: * Read, parse config and merge with default values. * Plugins modify the config by `api.modifyRsbuildConfig(...)`. * Normalize the config and provide it to consume, then the config can no longer be modified. Refer to this tiny example: ```ts export const pluginUploadDist = (): RsbuildPlugin => ({ name: 'plugin-upload-dist', setup(api) { api.modifyRsbuildConfig((config) => { // try to disable minimize. config.output ||= {}; config.output.minify = false; // but also can be enable by other plugins... }); api.onBeforeBuild(() => { // use the normalized config. const config = api.getNormalizedConfig(); if (config.output.minify !== false) { // let it crash when enable minimize. throw new Error( 'You must disable minimize to upload readable dist files.', ); } }); api.onAfterBuild(() => { const config = api.getNormalizedConfig(); const distRoot = config.output.distPath.root; // upload all files in `distRoot`... }); }, }); ``` There are 3 ways to use Rsbuild config: * register callback with `api.modifyRsbuildConfig(config => {})` to modify config. * use `api.getRsbuildConfig()` to get Rsbuild config. * use `api.getNormalizedConfig()` to get finally normalized config. When normalized, it will again merge the config object with the default values and make sure the optional properties exist. So for PluginUploadDist, part of its type looks like: ```ts api.modifyRsbuildConfig((config: RsbuildConfig) => {}); api.getRsbuildConfig() as RsbuildConfig; type RsbuildConfig = { output?: { minify?: boolean; distPath?: { root?: string }; }; }; api.getNormalizedConfig() as NormalizedConfig; type NormalizedConfig = { output: { minify: boolean; distPath: { root: string }; }; }; ``` The return value type of `getNormalizedConfig()` is slightly different from that of `RsbuildConfig` and is narrowed compared to the types described elsewhere in the documentation. You don't need to fill in the defaults when you use it. Therefore, the best way to use configuration options is to * **Modify the config** with `api.modifyRsbuildConfig(config => {})` * Read `api.getNormalizedConfig()` as the **actual config used by the plugin** in the further lifetime. ## Modify Rspack configuration Rsbuild plugin allows you to modify the built-in Rspack configuration, including: * [api.modifyRspackConfig](/plugins/dev/hooks.md#modifyrspackconfig): Modify the Rspack configuration object. * [api.modifyBundlerChain](/plugins/dev/hooks.md#modifybundlerchain): Modify the Rspack configuration through [rspack-chain](https://github.com/rspack-contrib/rspack-chain). ### Example For example, register [eslint-rspack-plugin](https://github.com/rspack-contrib/eslint-rspack-plugin) via Rsbuild plugin: ```ts import type { RsbuildPlugin } from '@rsbuild/core'; import ESLintRspackPlugin from 'eslint-rspack-plugin'; export const pluginEslint = (options?: Options): RsbuildPlugin => ({ name: 'plugin-eslint', setup(api) { api.modifyRspackConfig((config) => { config.plugins?.push( new ESLintRspackPlugin({ // plugins options }), ); }); }, }); ``` --- url: /plugins/list/index.md --- # Plugin list ## Plugin system You can read about the functionality of Rsbuild plugins and how to develop an Rsbuild plugin in the [Plugin System](/plugins/dev/index.md) documentation. ## Using plugins You can register Rsbuild plugins in the `rsbuild.config.ts` file using the `plugins` option. For more details, refer to [plugins](/config/plugins.md). If you are using Rsbuild's JavaScript API, you can register the plugin using the [addPlugins](/api/javascript-api/instance.md#rsbuildaddplugins) method. ## Official plugins The following are official plugins that can be used in Rsbuild. ### React Plugins available for the React: * [@rsbuild/plugin-react](/plugins/list/plugin-react.md): Provides support for React. * [@rsbuild/plugin-svgr](/plugins/list/plugin-svgr.md): Support convert SVG to React components. * [@rsbuild/plugin-styled-components](https://github.com/rsbuild-contrib/rsbuild-plugin-styled-components): Provide compile-time support for styled-components. ### Vue Plugins available for the Vue: * [@rsbuild/plugin-vue](/plugins/list/plugin-vue.md): Provides support for Vue 3 SFC (Single File Components). * [@rsbuild/plugin-vue-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx): Provides support for Vue 3 JSX / TSX syntax. * [@rsbuild/plugin-vue2](https://github.com/rspack-contrib/rsbuild-plugin-vue2): Provides support for Vue 2 SFC (Single File Components). * [@rsbuild/plugin-vue2-jsx](https://github.com/rspack-contrib/rsbuild-plugin-vue2-jsx): Provides support for Vue 2 JSX / TSX syntax. ### Preact Plugins available for the Preact: * [@rsbuild/plugin-preact](/plugins/list/plugin-preact.md): Provides support for Preact. ### Svelte Plugins available for the Svelte: * [@rsbuild/plugin-svelte](/plugins/list/plugin-svelte.md): Provides support for Svelte components (`.svelte` files). ### Solid Plugins available for the Solid: * [@rsbuild/plugin-solid](/plugins/list/plugin-solid.md): Provides support for Solid. ### Common The following are common framework-agnostic plugins: * [@rsbuild/plugin-assets-retry](https://github.com/rspack-contrib/rsbuild-plugin-assets-retry): Used to automatically resend requests when static assets fail to load. * [@rsbuild/plugin-babel](/plugins/list/plugin-babel.md): Provides support for Babel transpilation capabilities. * [@rsbuild/plugin-sass](/plugins/list/plugin-sass.md): Use Sass as the CSS preprocessor. * [@rsbuild/plugin-less](/plugins/list/plugin-less.md): Use Less as the CSS preprocessor. * [@rsbuild/plugin-stylus](/plugins/list/plugin-stylus.md): Use Stylus as the CSS preprocessor. * [@rsbuild/plugin-basic-ssl](https://github.com/rspack-contrib/rsbuild-plugin-basic-ssl): Generate an untrusted, self-signed certificate for the HTTPS server. * [@rsbuild/plugin-eslint](https://github.com/rspack-contrib/rsbuild-plugin-eslint): Run ESLint checks during the compilation. * [@rsbuild/plugin-type-check](https://github.com/rspack-contrib/rsbuild-plugin-type-check): Run TypeScript type checker on a separate process. * [@rsbuild/plugin-image-compress](https://github.com/rspack-contrib/rsbuild-plugin-image-compress): Compress the image assets. * [@rsbuild/plugin-mdx](https://github.com/rspack-contrib/rsbuild-plugin-mdx): Provide support for MDX. * [@rsbuild/plugin-node-polyfill](https://github.com/rspack-contrib/rsbuild-plugin-node-polyfill): Used to inject polyfills of Node core modules in the browser side. * [@rsbuild/plugin-source-build](https://github.com/rspack-contrib/rsbuild-plugin-source-build): This plugin is designed for the monorepo scenario. It supports referencing source code from other subdirectories and performs build and hot update. * [@rsbuild/plugin-check-syntax](https://github.com/rspack-contrib/rsbuild-plugin-check-syntax): Check the syntax compatibility of output files and determine if there are any advanced syntaxes that could cause compatibility issues. * [@rsbuild/plugin-css-minimizer](https://github.com/rspack-contrib/rsbuild-plugin-css-minimizer): Used to customize CSS minimizer, switch to [cssnano](https://github.com/cssnano/cssnano) or other tools for CSS compression. * [@rsbuild/plugin-typed-css-modules](https://github.com/rspack-contrib/rsbuild-plugin-typed-css-modules): Generate TypeScript declaration file for CSS Modules. * [@rsbuild/plugin-pug](https://github.com/rspack-contrib/rsbuild-plugin-pug): Provides support for the Pug template engine. * [@rsbuild/plugin-rem](https://github.com/rspack-contrib/rsbuild-plugin-rem): Implements the rem adaptive layout for mobile pages. * [@rsbuild/plugin-umd](https://github.com/rspack-contrib/rsbuild-plugin-umd): Generate outputs in UMD format. * [@rsbuild/plugin-yaml](https://github.com/rspack-contrib/rsbuild-plugin-yaml): Import YAML files and convert them into JavaScript objects. * [@rsbuild/plugin-toml](https://github.com/rspack-contrib/rsbuild-plugin-toml): Import TOML files and convert them into JavaScript objects. :::tip You can find the source code of all official plugins in [web-infra-dev/rsbuild](https://github.com/web-infra-dev/rsbuild) and [rspack-contrib](https://github.com/rspack-contrib). ::: ## Community plugins You can check out the Rsbuild plugins provided by the community at [awesome-rspack - Rsbuild Plugins](https://github.com/web-infra-dev/awesome-rspack?tab=readme-ov-file#rsbuild-plugins). You can also discover more Rsbuild plugins on npm by searching for the keyword [rsbuild-plugin](https://npmjs.com/search?q=rsbuild-plugin\&ranking=popularity). ### React * [rsbuild-plugin-react-router](https://github.com/rspack-contrib/rsbuild-plugin-react-router): Provides seamless integration with React Router. ### Angular * [@ng-rsbuild/plugin-angular](https://github.com/nrwl/angular-rspack): Allows you to build Angular applications easily. --- url: /plugins/list/plugin-react.md --- # React plugin The React plugin provides support for React, integrating features such as JSX compilation and React Refresh. ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginReact } from '@rsbuild/plugin-react'; export default { plugins: [pluginReact()], }; ``` After registering the plugin, you can directly develop React. ## Options ### swcReactOptions Configure the behavior of SWC to transform React code, the same as SWC's [jsc.transform.react](https://swc.rs/docs/configuration/compilation#jsctransformreact) option. * **Type:** ```ts interface SwcReactOptions { pragma?: string; pragmaFrag?: string; throwIfNamespace?: boolean; development?: boolean; useBuiltins?: boolean; refresh?: boolean; runtime?: 'automatic' | 'classic'; importSource?: string; } ``` * **Default:** ```ts const isDev = process.env.NODE_ENV === 'development'; const defaultOptions = { development: isDev, refresh: isDev, runtime: 'automatic', }; ``` ### swcReactOptions.runtime * **Type:** `'automatic' | 'classic'` * **Default:** `'automatic'` By default, Rsbuild uses the [new JSX runtime](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) introduced in React 17, which is `runtime: 'automatic'`. If your current React version is lower than 16.14.0, you can set `runtime` to `'classic'`: ```ts pluginReact({ swcReactOptions: { runtime: 'classic', }, }); ``` > React 16.14.0 can use the new JSX runtime. When using the classic JSX runtime, you need to manually import React in your code: ```jsx import React from 'react'; function App() { return

Hello World

; } ``` ### swcReactOptions.importSource * **Type:** `string` * **Default:** `'react'` When `runtime` is `'automatic'`, you can specify the import path of the JSX runtime through `importSource`. For example, when using [Emotion](https://emotion.sh/), you can set `importSource` to `'@emotion/react'`: ```ts pluginReact({ swcReactOptions: { importSource: '@emotion/react', }, }); ``` > See [Customize JSX](/guide/framework/react.md#customize-jsx) for more details. ### swcReactOptions.refresh * **Type:** `boolean` * **Default:** based on [fastRefresh](#fastrefresh) and [dev.hmr](/config/dev/hmr.md) Whether to enable [React Fast Refresh](https://npmjs.com/package/react-refresh). Most of the time, you should use the plugin's [fastRefresh](#fastrefresh) option to enable or disable Fast Refresh. ### splitChunks When [chunkSplit.strategy](/config/performance/chunk-split.md) set to `split-by-experience`, Rsbuild will automatically split `react` and `router` related packages into separate chunks by default: * `lib-react.js`: includes react, react-dom, and react's sub-dependencies (scheduler). * `lib-router.js`: includes react-router, react-router-dom, and react-router's sub-dependencies (history, @remix-run/router). This option is used to control this behavior and determine whether the `react` and `router` related packages need to be split into separate chunks. * **Type:** ```ts type SplitReactChunkOptions = { react?: boolean; router?: boolean; }; ``` * **Default:** ```ts const defaultOptions = { react: true, router: true, }; ``` * **Example:** ```ts pluginReact({ splitChunks: { react: false, router: false, }, }); ``` ### enableProfiler * **Type:** `boolean` * **Default:** `false` When set to `true`, enables the React Profiler for performance analysis in production builds. Use the React DevTools to examine profiling results and identify potential performance optimizations. Profiling adds a slight overhead, so it's disabled by default in production mode. ```ts title="rsbuild.config.ts" pluginReact({ // Only enable the profiler when REACT_PROFILER is true, // as the option will increase the build time and adds some small additional overhead. enableProfiler: process.env.REACT_PROFILER === 'true', }); ``` Set `REACT_PROFILER=true` when running build script: ```json title="package.json" { "scripts": { "build:profiler": "REACT_PROFILER=true rsbuild build" } } ``` As Windows does not support the above usage, you can also use [cross-env](https://npmjs.com/package/cross-env) to set environment variables. This ensures compatibility across different systems: ```json title="package.json" { "scripts": { "build:profiler": "cross-env REACT_PROFILER=true rsbuild build" }, "devDependencies": { "cross-env": "^7.0.0" } } ``` > See the [React docs](https://legacy.reactjs.org/docs/optimizing-performance.html#profiling-components-with-the-devtools-profiler) for details about profiling using the React DevTools. ### reactRefreshOptions * **Type:** ```ts type ReactRefreshOptions = { include?: string | RegExp | (string | RegExp)[] | null; exclude?: string | RegExp | (string | RegExp)[] | null; library?: string; forceEnable?: boolean; }; ``` * **Default:** ```js const defaultOptions = { include: [/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/], exclude: [/[\\/]node_modules[\\/]/], }; ``` Set the options for [@rspack/plugin-react-refresh](https://rspack.dev/guide/tech/react#rspackplugin-react-refresh). The passed value will be shallowly merged with the default value. * **Example:** ```js pluginReact({ reactRefreshOptions: { exclude: [/some-module-to-exclude/, /[\\/]node_modules[\\/]/], }, }); ``` ### fastRefresh * **Type:** `boolean` * **Default:** `true` Whether to enable [React Fast Refresh](https://npmjs.com/package/react-refresh) in development mode. If `fastRefresh` is set to `true`, `@rsbuild/plugin-react` will automatically register the [@rspack/plugin-react-refresh](https://npmjs.com/package/@rspack/plugin-react-refresh) plugin. To disable Fast Refresh, set it to `false`: ```ts pluginReact({ fastRefresh: false, }); ``` --- url: /plugins/list/plugin-svgr.md --- # SVGR plugin By default, Rsbuild will treat SVG files as static assets. For processing rules, please refer to: [Static assets](/guide/basic/static-assets.md). With SVGR plugin, Rsbuild supports transform SVG to React components via [SVGR](https://react-svgr.com/). ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginReact } from '@rsbuild/plugin-react'; import { pluginSvgr } from '@rsbuild/plugin-svgr'; export default { plugins: [pluginReact(), pluginSvgr()], }; ``` ## Example ### Default usage After registering the plugin, when import an SVG in a JS file, if the imported path contains the `?react` suffix, Rsbuild will call SVGR to transform the SVG into a React component. ```jsx title="App.jsx" import Logo from './logo.svg?react'; export const App = () => ; ``` If the imported path does not contain the `?react` suffix, then the SVG will be treated as a normal static asset and you will get a URL string or base64 URL, see [Static assets](/guide/basic/static-assets.md). ```js import logoURL from './static/logo.svg'; console.log(logoURL); // => "/static/logo.6c12aba3.png" ``` ### Named import `@rsbuild/plugin-svgr` supports named imports for `ReactComponent` when using SVGR. You need to set [svgrOptions.exportType](#svgroptionsexporttype) to `'named'`: ```js pluginSvgr({ svgrOptions: { exportType: 'named', }, }); ``` ```jsx title="App.jsx" import { ReactComponent as Logo } from './logo.svg'; export const App = () => ; ``` `@rsbuild/plugin-svgr` also supports default imports and mixed imports: * Enable default imports by setting [svgrOptions.exportType](#svgroptionsexporttype) to `'default'`. * Enable mixed imports by setting the [mixedImport](#mixedimport) option to use both default and named imports at the same time. ## Options To customize the compilation behavior of Svgr, use the following options. * **Type:** ```ts type PluginSvgrOptions = { /** * Configure SVGR options. */ svgrOptions?: import('@svgr/core').Config; /** * Whether to allow the use of default import and named import at the same time. * @default false */ mixedImport?: boolean; }; ``` ### svgrOptions Modify the options of SVGR, the passed object will be deep merged with the default value. See [SVGR - Options](https://react-svgr.com/docs/options/) for details. * **Type:** `import('@svgr/core').Config` * **Default:** ```ts const defaultSvgrOptions = { svgo: true, svgoConfig: { plugins: [ { name: 'preset-default', params: { overrides: { removeViewBox: false, }, }, }, 'prefixIds', ], }, }; ``` * **Example:** ```ts pluginSvgr({ svgrOptions: { svgoConfig: { datauri: 'base64', }, }, }); ``` When you set `svgoConfig.plugins`, the configuration for plugins with the same name is automatically merged. For example, the following configuration will be merged with the built-in `preset-default`: ```ts pluginSvgr({ svgrOptions: { svgoConfig: { plugins: [ { name: 'preset-default', params: { overrides: { cleanupIds: false, }, }, }, ], }, }, }); ``` The merged `svgoConfig` will be: ```ts const mergedSvgoConfig = { plugins: [ { name: 'preset-default', params: { overrides: { removeViewBox: true, cleanupIds: false, }, }, }, 'prefixIds', ], }; ``` ### svgrOptions.exportType Set the export type of SVG React components. * **Type:** `'default' | 'named'` * **Default:** `undefined` `exportType` can be set as: * `default`: use default export. * `named`: use `ReactComponent` named export. For example, set the default export of SVG file as a React component: ```ts pluginSvgr({ svgrOptions: { exportType: 'default', }, }); ``` Then import the SVG, you'll get a React component instead of a URL: ```ts import Logo from './logo.svg'; console.log(Logo); // => React Component ``` At this time, you can also specify the `?url` query to import the URL, for example: ```ts import logo from './logo.svg?url'; console.log(logo); // => asset url ``` :::tip When `svgrOptions.exportType` is set to `'default'`, the named imports (ReactComponent) cannot be used. ::: ### mixedImport * **Type:** `boolean` * **Default:** `false` Whether to enable mixed import, allowing to use default import and named import at the same time. Mixed import is usually used with `svgrOptions.exportType: 'named'`, for example: ```ts pluginSvgr({ mixedImport: true, svgrOptions: { exportType: 'named', }, }); ``` At this time, the imported SVG file will export both URL and the React component: ```js import logoUrl, { ReactComponent as Logo } from './logo.svg'; console.log(logoUrl); // -> string console.log(Logo); // -> React component ``` #### Limitations It is recommended to use `?react` to transform SVG to React component instead of using mixed import. Because mixed import has the following limitations: 1. Increased bundle size: Mixed import causes a single SVG module to be compiled into two types of code (even if some exports are not used), which will increase the bundle size. 2. Slow down compiling: Mixed import will cause extra compilation overhead. Even if the ReactComponent export is not used in the code, the SVG file will still be compiled by SVGR. And SVGR is based on Babel, which has a high performance overhead. ### query * **Type:** `RegExp` * **Default:** `/react/` Used to custom the query suffix to match SVGR transformation. For example, if you need to match import paths with the `?svgr` suffix: ```ts pluginSvgr({ query: /svgr/, }); ``` ```jsx title="App.jsx" import Logo from './logo.svg?svgr'; export const App = () => ; ``` ### exclude * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `undefined` Exclude some SVG files, they will not be transformed by SVGR. For example, if a project includes `a.svg` and `b.svg`, you can add `b.svg` to exclude: ```ts pluginSvgr({ svgrOptions: { exportType: 'default', }, exclude: /b\.svg/, }); ``` When imported, `a.svg` will be transformed into a React component, while `b.svg` will be treated as a regular static asset: ```ts title="src/index.ts" import component from './a.svg'; import url from './b.svg'; console.log(component); // => React component console.log(url); // => resource url ``` ### excludeImporter * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `undefined` Exclude some modules, the SVGs imported by these modules will not be transformed by SVGR. For example, if your project contains `page-a/index.ts` and `page-b/index.ts`, you can add `page-b` to excludeImporter: ```ts pluginSvgr({ svgrOptions: { exportType: 'default', }, excludeImporter: /\/page-b\/index\.ts/, }); ``` * SVGs referenced in page-a will be transformed to React components: ```ts title="page-a/index.ts" import Logo from './logo.svg'; console.log(Logo); // => React component ``` * SVGs referenced in page-b will be treated as static assets: ```ts title="page-b/index.ts" import url from './logo.svg'; console.log(url); // => Resource url ``` :::tip The query in the module path has a higher priority than `exclude` and `excludeImporter`. For example, if a module is excluded, adding `?react` can still make it transformed by SVGR. ::: ## Type declaration 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, please create a `src/env.d.ts` file, and add the type declaration. * By default, you can add the following type declarations: ```ts declare module '*.svg' { const content: string; export default content; } declare module '*.svg?react' { const ReactComponent: React.FunctionComponent>; export default ReactComponent; } ``` * If the value of `svgrOptions.exportType` is `'default'`, set the type declaration to: ```ts declare module '*.svg' { const ReactComponent: React.FunctionComponent>; export default ReactComponent; } declare module '*.svg?react' { const ReactComponent: React.FunctionComponent>; export default ReactComponent; } ``` * If the value of `svgrOptions.exportType` is `'named'`, set the type declaration to: ```ts declare module '*.svg' { export const ReactComponent: React.FunctionComponent< React.SVGProps >; } declare module '*.svg?react' { const ReactComponent: React.FunctionComponent>; export default ReactComponent; } ``` * If the value of `svgrOptions.exportType` is `'named'`, and `mixedImport` is enabled, set the type declaration to: ```ts declare module '*.svg' { export const ReactComponent: React.FunctionComponent< React.SVGProps >; const content: string; export default content; } declare module '*.svg?react' { const ReactComponent: React.FunctionComponent>; export default ReactComponent; } ``` After adding the type declarations, if the type error still exists, you can try to restart the IDE, or adjust the directory where `env.d.ts` is located, making sure the TypeScript can correctly identify the type definition. --- url: /plugins/list/plugin-vue.md --- # Vue plugin The Vue plugin provides support for Vue 3 SFC (Single File Components). The plugin internally integrates [vue-loader](https://vue-loader.vuejs.org/) v17. :::tip For Vue 3 JSX / TSX syntax, please use the [Vue JSX plugin](https://github.com/rspack-contrib/rsbuild-plugin-vue-jsx). ::: ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginVue } from '@rsbuild/plugin-vue'; export default { plugins: [pluginVue()], }; ``` After registering the plugin, you can import `*.vue` SFC files in your code. ## Options To customize the compilation behavior of Vue, use the following options. ### vueLoaderOptions Options passed to `vue-loader`, please refer to the [vue-loader documentation](https://vue-loader.vuejs.org/) for detailed usage. * **Type:** `VueLoaderOptions` * **Default:** ```js const defaultOptions = { compilerOptions: { preserveWhitespace: false, }, experimentalInlineMatchResource: true, }; ``` * **Example:** ```ts pluginVue({ vueLoaderOptions: { hotReload: false, }, }); ``` ### splitChunks When [chunkSplit.strategy](/config/performance/chunk-split.md) set to `split-by-experience`, Rsbuild will automatically split `vue` and `router` related packages into separate chunks by default: * `lib-vue.js`: includes vue, vue-loader, and vue's sub-dependencies (@vue/shared, @vue/reactivity, @vue/runtime-dom, @vue/runtime-core). * `lib-router.js`: includes vue-router. This option is used to control this behavior and determine whether the `vue` and `router` related packages need to be split into separate chunks. * **Type:** ```ts type SplitVueChunkOptions = { vue?: boolean; router?: boolean; }; ``` * **Default:** ```ts const defaultOptions = { vue: true, router: true, }; ``` * **Example:** ```ts pluginVue({ splitChunks: { vue: false, router: false, }, }); ``` ## FAQ ### /deep/ selector causes compilation error `/deep/` is a deprecated usage as of Vue v2.7. Since it is not a valid CSS syntax, CSS compilation tools like Lightning CSS will fail to compile it. You can use `:deep()` instead. See [Vue - Deep Selectors](https://vuejs.org/api/sfc-css-features.html#deep-selectors) for more details. ```html ``` > You can also refer to [Vue - RFC 0023](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0023-scoped-styles-changes.md) for more details. --- url: /plugins/list/plugin-preact.md --- # Preact plugin The Preact plugin provides support for Preact, integrating features such as JSX compilation and React aliasing. ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginPreact } from '@rsbuild/plugin-preact'; export default { plugins: [pluginPreact()], }; ``` After registering the plugin, you can directly develop Preact. ## Options ### reactAliasesEnabled Whether to aliases `react`, `react-dom` to `preact/compat`. * **Type:** `boolean` * **Default:** `true` * **Example:** Disable aliases. ```ts pluginPreact({ reactAliasesEnabled: false, }); ``` ### prefreshEnabled Whether to inject [Prefresh](https://github.com/preactjs/prefresh) for HMR. * **Type:** `boolean` * **Default:** `true` * **Version:** `>= v1.1.0` * **Example:** Disable Prefresh. ```ts pluginPreact({ prefreshEnabled: false, }); ``` ### include Include files to be processed by the [@rspack/plugin-preact-refresh](https://github.com/rspack-contrib/rspack-plugin-preact-refresh) plugin. The value is the same as the `rule.test` option in Rspack. * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/` * **Version:** `>= v1.1.0` ```ts pluginPreact({ include: [/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/, /some-other-module/], }); ``` ### exclude Exclude files from being processed by the [@rspack/plugin-preact-refresh](https://github.com/rspack-contrib/rspack-plugin-preact-refresh) plugin. The value is the same as the `rule.exclude` option in Rspack. * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `/[\\/]node_modules[\\/]/` * **Version:** `>= v1.1.0` ```ts pluginPreact({ exclude: [/[\\/]node_modules[\\/]/, /some-other-module/], }); ``` --- url: /plugins/list/plugin-svelte.md --- # Svelte plugin The Svelte plugin provides support for Svelte components (`.svelte` files). The plugin internally integrates [svelte-loader](https://github.com/sveltejs/svelte-loader). ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginSvelte } from '@rsbuild/plugin-svelte'; export default { plugins: [pluginSvelte()], }; ``` After registering the plugin, you can import `*.svelte` files in your code. ## Options To customize the compilation behavior of Svelte, use the following options. ### svelteLoaderOptions Options passed to `svelte-loader`, please refer to the [svelte-loader documentation](https://github.com/sveltejs/svelte-loader) for detailed usage. * **Type:** `SvelteLoaderOptions` * **Default:** ```js const defaultOptions = { compilerOptions: { dev: isDev, }, preprocess: require('svelte-preprocess')(), emitCss: isProd && !rsbuildConfig.output.injectStyles, hotReload: isDev && rsbuildConfig.dev.hmr, }; ``` * **Example:** ```ts pluginSvelte({ svelteLoaderOptions: { preprocess: null, }, }); ``` ### preprocessOptions Options passed to `svelte-preprocess`, please refer to the [svelte-preprocess documentation](https://github.com/sveltejs/svelte-preprocess/blob/c2107e529da9438ea5b8060aa471119940896e40/docs/preprocessing.md) for detailed usage. * **Type:** `AutoPreprocessOptions` * **Default:** `undefined` ```ts interface AutoPreprocessOptions { globalStyle: { ... }, replace: { ... }, typescript: { ... }, scss: { ... }, sass: { ... }, less: { ... }, stylus: { ... }, babel: { ... }, postcss: { ... }, coffeescript: { ... }, pug: { ... }, } ``` * **Example:** ```ts pluginSvelte({ preprocessOptions: { aliases: [ ['potato', 'potatoLanguage'], ['pot', 'potatoLanguage'], ], /** Add a custom language preprocessor */ potatoLanguage({ content, filename, attributes }) { const { code, map } = require('potato-language').render(content); return { code, map }; }, }, }); ``` ## Notes Currently, `svelte-loader` does not support HMR for Svelte v5, see [svelte-loader - Hot Reload](https://github.com/sveltejs/svelte-loader?tab=readme-ov-file#hot-reload). --- url: /plugins/list/plugin-solid.md --- # Solid plugin The Solid plugin provides support for Solid features. The plugin internally integrates [babel-preset-solid](https://github.com/solidjs/solid/tree/main/packages/babel-preset-solid). :::tip The Solid plugin relies on Babel transpilation and requires an additional [Babel Plugin](/plugins/list/plugin-babel.md). At the same time, adding the Babel plugin will cause additional compilation overhead. ::: ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginBabel } from '@rsbuild/plugin-babel'; import { pluginSolid } from '@rsbuild/plugin-solid'; export default { plugins: [ pluginBabel({ include: /\.(?:jsx|tsx)$/, }), pluginSolid(), ], }; ``` After registering the plugin, you can directly develop Solid. :::tip Since the Solid JSX relies on Babel for compilation, you need to additionally add the [Babel plugin](/plugins/list/plugin-babel.md). Babel compilation will introduce extra overhead, in the example above, we use `include` to match `.jsx` and `.tsx` files, thereby reducing the performance cost brought by Babel. ::: ## Options To customize the compilation behavior of Solid, use the following options. ### solidPresetOptions Options passed to `babel-preset-solid`, please refer to the [babel-preset-solid documentation](https://npmjs.com/package/babel-preset-solid) for detailed usage. * **Type:** `SolidPresetOptions` * **Default:** `{}` * **Example:** ```ts pluginSolid({ solidPresetOptions: { generate: 'ssr', hydratable: true, }, }); ``` --- url: /plugins/list/plugin-babel.md --- # Babel plugin Rsbuild uses SWC transpilation by default. When existing functions cannot meet the requirements, and some Babel presets or plugins need to be added for additional processing, you can use Rsbuild's Babel Plugin. ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginBabel } from '@rsbuild/plugin-babel'; export default { plugins: [pluginBabel()], }; ``` ## Compilation cache After using the Babel plugin, Rsbuild will perform the Babel transpilation in addition to the standard SWC transpilation, which adds additional compilation overhead. This can cause a noticeable decrease in build speed. To reduce the overhead of Babel transpilation, the `@rsbuild/plugin-babel` enables Babel compilation cache by default. If you want to disable the cache, you can set `performance.buildCache` to `false`: ```ts title="rsbuild.config.ts" export default { performance: { buildCache: false, }, }; ``` ## Options ### babelLoaderOptions Options passed to `babel-loader`, please refer to the [babel-loader documentation](https://github.com/babel/babel-loader) for detailed usage. * **Type:** `Object | Function` * **Default:** ```ts const defaultOptions = { babelrc: false, compact: false, configFile: false, plugins: [ ['@babel/plugin-proposal-decorators', config.source.decorators], ...(isLegacyDecorators ? ['@babel/plugin-transform-class-properties'] : []), ], presets: [ [ '@babel/preset-typescript', { allExtensions: true, allowDeclareFields: true, allowNamespaces: true, isTSX: true, optimizeConstEnums: true, }, ], ], }; ``` #### Function type When configuration is of type `Function`, the default Babel configuration will be passed as the first parameter. You can directly modify the configuration object or return an object as the final `babel-loader` configuration. ```js pluginBabel({ babelLoaderOptions: (config) => { // Add a Babel plugin // note: the plugin have been added to the default config to support antd load on demand config.plugins ||= []; config.plugins.push([ 'babel-plugin-import', { libraryName: 'my-components', libraryDirectory: 'es', style: true, }, ]); }, }); ``` The second parameter of the function provides some more convenient utility functions. Please continue reading the documentation below. :::tip The above example is just for reference, usually you don't need to manually configure `babel-plugin-import`, because the Rsbuild already provides a more general `source.transformImport` configuration. ::: #### Object type When configuration's type is `Object`, the config will be shallow merged with default config by `Object.assign`. :::caution Note that `Object.assign` is a shallow copy and will completely overwrite the built-in `presets` or `plugins` array, please use it with caution. ::: ```js pluginBabel({ babelLoaderOptions: { plugins: [ [ 'babel-plugin-import', { libraryName: 'my-components', libraryDirectory: 'es', style: true, }, ], ], }, }); ``` #### Util functions When configuration is a Function, the tool functions available for the second parameter are as follows: ##### addPlugins * **Type:** `(plugins: BabelPlugin[]) => void` Add some Babel plugins. For example: ```js pluginBabel({ babelLoaderOptions: (config, { addPlugins }) => { addPlugins([ [ 'babel-plugin-import', { libraryName: 'my-components', libraryDirectory: 'es', style: true, }, ], ]); }, }); ``` ##### addPresets * **Type:** `(presets: BabelPlugin[]) => void` Add Babel preset configuration. (No need to add presets in most cases) ```js pluginBabel({ babelLoaderOptions: (config, { addPresets }) => { addPresets(['@babel/preset-env']); }, }); ``` ##### removePlugins * **Type:** `(plugins: string | string[]) => void` To remove the Babel plugin, just pass in the name of the plugin to be removed, you can pass in a single string or an array of strings. ```js pluginBabel({ babelLoaderOptions: (config, { removePlugins }) => { removePlugins('babel-plugin-import'); }, }); ``` ##### removePresets * **Type:** `(presets: string | string[]) => void` To remove the Babel preset configuration, pass in the name of the preset to be removed, you can pass in a single string or an array of strings. ```js pluginBabel({ babelLoaderOptions: (config, { removePresets }) => { removePresets('@babel/preset-env'); }, }); ``` ### include * **Type:** `string | RegExp | (string | RegExp)[]` * **Default:** `undefined` Used to specify the files that need to be compiled by Babel. Due to the performance overhead of Babel compilation, matching only certain files through `include` can reduce the number of modules compiled by Babel, thereby improving build performance. For example, to only compile `.custom.js` files and ignore files under `node_modules`: ```js pluginBabel({ include: /\.custom\.js$/, // recommended to exclude the node_modules to improve build performance exclude: /[\\/]node_modules[\\/]/, }); ``` :::tip When you configure the `include` or `exclude` options, Rsbuild will create a separate Rspack rule to apply babel-loader and swc-loader. This separate rule is completely independent of the SWC rule built into Rsbuild and is not affected by [source.include](/config/source/include.md) and [source.exclude](/config/source/exclude.md). ::: ### exclude * **Type:** `string | RegExp | (string | RegExp)[]` * **Default:** `undefined` Used to specify the files that do not need to be compiled by Babel. Due to the performance overhead of Babel compilation, excluding certain files through `exclude` can reduce the number of modules compiled by Babel, thereby improving build performance. ## Execution order After using `@rsbuild/plugin-babel`, Rsbuild will use both `babel-loader` and `builtin:swc-loader` to compile JavaScript files, with Babel running before SWC. This means that if you are using some new ECMAScript features in your code, you may need to add Babel plugins to ensure that Babel can correctly compile these new features. For example, add the [@babel/plugin-transform-private-methods](https://www.npmjs.com/package/@babel/plugin-transform-private-methods) plugin to enable Babel to correctly compile [private properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_properties): ```ts pluginBabel({ babelLoaderOptions: { plugins: ['@babel/plugin-transform-private-methods'], }, }); ``` ## Debugging configs After modifying the `babel-loader` configuration, you can view the final generated configuration in [Rsbuild debug mode](/guide/debug/debug-mode.md). First, enable debug mode by using the `DEBUG=rsbuild` option: ```bash # Debug development mode DEBUG=rsbuild pnpm dev # Debug production mode DEBUG=rsbuild pnpm build ``` Then open the generated `rspack.config.web.mjs` file and search for the `babel-loader` keyword to see the complete `babel-loader` configuration. ## FAQ ### Compilation freezes After using the babel plugin, if the compilation progress bar is stuck, but there is no Error log on the terminal, it is usually because an exception occurred during the compilation. In some cases, when Error is caught by webpack or other modules, the error log can not be output correctly. The most common scenario is that there is an exception in the Babel config, which is caught by webpack, and webpack swallows the Error in some cases. **Solution:** If this problem occurs after you modify the Babel config, it is recommended to check for the following incorrect usages: 1. You have configured a plugin or preset that does not exist, maybe the name is misspelled, or it is not installed correctly. ```ts // wrong example pluginBabel({ babelLoaderOptions: (config, { addPlugins }) => { // The plugin has the wrong name or is not installed addPlugins('babel-plugin-not-exists'); }, }); ``` 2. Whether multiple babel-plugin-imports are configured, but the name of each babel-plugin-import is not declared in the third item of the array. ```ts // wrong example pluginBabel({ babelLoaderOptions: (config, { addPlugins }) => { addPlugins([ ['babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es' }], [ 'babel-plugin-import', { libraryName: 'antd-mobile', libraryDirectory: 'es' }, ], ]); }, }); ``` ```ts // correct example pluginBabel({ babelLoaderOptions: (config, { addPlugins }) => { addPlugins([ [ 'babel-plugin-import', { libraryName: 'antd', libraryDirectory: 'es' }, 'antd', ], [ 'babel-plugin-import', { libraryName: 'antd-mobile', libraryDirectory: 'es' }, 'antd-mobile', ], ]); }, }); ``` --- url: /plugins/list/plugin-sass.md --- # Sass plugin Use [Sass](https://sass-lang.com/) as the CSS preprocessor, implemented based on [sass-loader](https://github.com/webpack-contrib/sass-loader). ## Quick start ### Install plugin You can install the plugin using the following command: :::tip * The Sass plugin only supports @rsbuild/core versions >= 0.7.0. * If the @rsbuild/core version is lower than 0.7.0, it has builtin support for the Sass plugin, you do not need to install it. ::: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginSass } from '@rsbuild/plugin-sass'; export default { plugins: [pluginSass()], }; ``` After registering the plugin, you can import `*.scss`, `*.sass`, `*.module.scss` or `*.module.sass` files into the code without adding other configs. ## Options To customize the compilation behavior of Sass, use the following options. ### sassLoaderOptions Modify the config of [sass-loader](https://github.com/webpack-contrib/sass-loader). * **Type:** `Object | Function` * **Default:** ```js const defaultOptions = { api: 'modern-compiler', implementation: require.resolve('sass-embedded'), sourceMap: rsbuildConfig.output.sourceMap.css, sassOptions: { quietDeps: true, silenceDeprecations: ['legacy-js-api', 'import'], }, }; ``` * **Example:** If `sassLoaderOptions` is an object, it is merged with the default config through `Object.assign`. It should be noted that `sassOptions` is merged through deepMerge in a deep way. ```js pluginSass({ sassLoaderOptions: { sourceMap: true, }, }); ``` If `sassLoaderOptions` is a function, the default config is passed as the first parameter, which can be directly modified or returned as the final result. ```js pluginSass({ sassLoaderOptions(config) { config.additionalData = async (content, loaderContext) => { // ... }; }, }); ``` ### include * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `/\.s(?:a|c)ss$/` * **Version:** `>= 1.1.0` Include some `.scss` or `.sass` files, they will be transformed by `sass-loader`. The value is the same as the `rule.test` option in Rspack. For example: ```ts pluginSass({ include: /\.custom\.scss$/, }); ``` ### exclude * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `undefined` Exclude some `.sass` or `.scss` files, they will not be transformed by `sass-loader`. For example: ```ts pluginSass({ exclude: /some-folder[\\/]foo\.scss/, }); ``` ### rewriteUrls * **Type:** `boolean` * **Default:** `true` * **Version:** `>= 1.2.0` Whether to use [resolve-url-loader](https://github.com/bholloway/resolve-url-loader/tree/v5/packages/resolve-url-loader) to rewrite URLs. When enabled, `resolve-url-loader` allows you to write relative URLs in your Sass files that are correctly resolved from the current Sass file's location, rather than being relative to the Sass entry file (e.g. `main.scss`). If you set this option to `false`, the build performance will be improved, but Rsbuild will use the native URL resolution of Sass, which means all URLs must be relative to the Sass entry file. ```ts pluginSass({ rewriteUrls: false, }); ``` ## Practices ### Modify Sass implementation Sass provides several implementations, including [sass](https://npmjs.com/package/sass), [sass-embedded](https://npmjs.com/package/sass-embedded), and [node-sass](https://npmjs.com/package/node-sass). Rsbuild uses the latest `sass-embedded` implementation by default. `sass-embedded` is a JavaScript wrapper around the native Dart Sass executable, providing a consistent API and optimal performance. To use a different Sass implementation instead of the built-in `sass-embedded` included in Rsbuild, install the preferred Sass implementation in your project and specify it using the `sass-loader`'s [implementation](https://github.com/webpack-contrib/sass-loader?tab=readme-ov-file#implementation) option. ```ts pluginSass({ sassLoaderOptions: { implementation: require.resolve('sass'), }, }); ``` :::tip Switching from `sass-embedded` to another Sass implementation can significantly decrease build performance. ::: ### Select Sass API Rsbuild uses the latest `modern-compiler` API by default. If you rely on the `legacy` API of Sass, you can set the `api` option of the sass-loader to `legacy` to maintain compatibility with some deprecated Sass syntax. ```ts pluginSass({ sassLoaderOptions: { api: 'legacy', }, }); ``` :::tip Sass's `legacy` API has been deprecated and will be removed in Sass 2.0. It is recommended to migrate to the `modern-compiler` API. For more details, see [Sass - Legacy JS API](https://sass-lang.com/documentation/breaking-changes/legacy-js-api/). ::: ### Ignore Sass deprecation warnings Sass uses warning logs to notify you of deprecated usages that will be removed in future major releases of Sass. It is recommended to make changes as suggested by the logs. If you do not want to see these logs, you can ignore these warnings by using the [silenceDeprecations](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/#silenceDeprecations) option in Sass. For example, `@import` has been deprecated in Sass. If you use this syntax, Sass will output the following prompt: ``` Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. More info and automated migrator: https://sass-lang.com/d/import 0 | @import './b.scss'; ``` `@rsbuild/plugin-sass` adds the following configuration by default to silence the `@import` warning, if you need to silence other deprecated warnings, you can use the same method. ```ts pluginSass({ sassLoaderOptions: { sassOptions: { silenceDeprecations: ['import'], }, }, }); ``` > For more information, see [Sass Deprecations](https://sass-lang.com/documentation/js-api/interfaces/deprecations/). ### Configure multiple Sass plugins By using the `include` and `exclude` options, you can register multiple Sass plugins and specify different options for each plugin. For example: ```ts export default { plugins: [ pluginSass({ exclude: /\.another\.scss$/, }), pluginSass({ include: /\.another\.scss$/, sassLoaderOptions: { // some custom options }, }), ], }; ``` --- url: /plugins/list/plugin-less.md --- # Less plugin Use [Less](https://lesscss.org/) as the CSS preprocessor, implemented based on [less-loader](https://github.com/webpack-contrib/less-loader). ## Quick start ### Install plugin You can install the plugin using the following command: :::tip * The Less plugin only supports @rsbuild/core versions >= 0.7.0. * If the @rsbuild/core version is lower than 0.7.0, it has builtin support for the Less plugin, you do not need to install it. ::: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginLess } from '@rsbuild/plugin-less'; export default { plugins: [pluginLess()], }; ``` After registering the plugin, you can import `*.less` or `*.module.less` files into the code without adding other configs. ## Options To customize the compilation behavior of Less, use the following options. ### lessLoaderOptions You can modify the config of [less-loader](https://github.com/webpack-contrib/less-loader) via `lessLoaderOptions`. * **Type:** `Object | Function` * **Default:** ```js const defaultOptions = { lessOptions: { javascriptEnabled: true, paths: [path.join(rootPath, 'node_modules')], }, implementation: require.resolve('less'), sourceMap: rsbuildConfig.output.sourceMap.css, }; ``` * **Example:** If `lessLoaderOptions` is an object, it is merged with the default config through `Object.assign` in a shallow way. It should be noted that `lessOptions` is merged through deepMerge in a deep way. ```js pluginLess({ lessLoaderOptions: { lessOptions: { javascriptEnabled: false, }, }, }); ``` If `lessLoaderOptions` is a function, the default config is passed as the first parameter, which can be directly modified or returned as the final result. ```js pluginLess({ lessLoaderOptions(config) { config.lessOptions = { javascriptEnabled: false, }; }, }); ``` :::tip The `lessLoaderOptions.lessOptions` config is passed to Less. See the [Less documentation](https://lesscss.org/usage/#command-line-usage-options) for all available options. ::: ### include * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `/\.less$/` * **Version:** `>= 1.1.0` Include some `.less` files, they will be transformed by `less-loader`. The value is the same as the `rule.test` option in Rspack. For example: ```ts pluginLess({ include: /\.custom\.less$/, }); ``` ### exclude * **Type:** [RuleSetCondition](https://rspack.dev/config/module#condition) * **Default:** `undefined` Exclude some `.less` files, they will not be transformed by `less-loader`. For example: ```ts pluginLess({ exclude: /some-folder[\\/]foo\.less/, }); ``` ## Modifying Less version In some scenarios, if you need to use a specific version of Less instead of the built-in Less v4 in Rsbuild, you can install the desired Less version in your project and set it up using the `implementation` option of the `less-loader`. ```js pluginLess({ lessLoaderOptions: { implementation: require('less'), }, }); ``` ## Practices ### Configure multiple Less plugins By using the `include` and `exclude` options, you can register multiple Less plugins and specify different options for each plugin. For example: ```ts export default { plugins: [ pluginLess({ exclude: /\.another\.less$/, }), pluginLess({ include: /\.another\.less$/, lessLoaderOptions: { // some custom options }, }), ], }; ``` ## FAQ ### Division in Less file doesn't work? The built-in Less version for `@rsbuild/plugin-less` is v4. Compared to v3, there are some differences in the division syntax in Less v4: ```less // Less v3 .math { width: 2px / 2; // 1px width: 2px ./ 2; // 1px width: (2px / 2); // 1px } // Less v4 .math { width: 2px / 2; // 2px / 2 width: 2px ./ 2; // 1px width: (2px / 2); // 1px } ``` The division syntax in Less can be modified through configuration. For more details, see [Less - Math](https://lesscss.org/usage/#less-options-math). --- url: /plugins/list/plugin-stylus.md --- # Stylus plugin [Stylus](https://stylus-lang.com/) is an Expressive, dynamic and robust CSS preprocessor. With Stylus plugins, you can use Stylus as the CSS preprocessor. ## Quick start ### Install plugin You can install the plugin using the following command: ### Register plugin You can register the plugin in the `rsbuild.config.ts` file: ```ts title="rsbuild.config.ts" import { pluginStylus } from '@rsbuild/plugin-stylus'; export default { plugins: [pluginStylus()], }; ``` ## Example After registering the plugin, you can import `*.styl`, `*.stylus`, `*.module.styl` or `*.module.stylus` files into the code without adding other configs. * `normalize.styl`: ```styl the body color#000 font 14px Arial, sans-serif ``` * `title.module.styl`: ```styl .title font-size: 14px; ``` * `index.js`: ```js import './normalize.styl'; import style from './title.module.styl'; console.log(style.title); ``` ## Options To customize the compilation behavior of Stylus, use the following options. ### stylusOptions -Type: ```ts type StylusOptions = { use?: string[]; define?: [string, any, boolean?][]; include?: string[]; includeCSS?: boolean; import?: string[]; resolveURL?: boolean; lineNumbers?: boolean; hoistAtrules?: boolean; }; ``` * **Default:** `undefined` Options passed to Stylus, please refer to the [Stylus documentation](https://stylus-lang.com/docs/js) for specific usage. ```ts pluginStylus({ stylusOptions: { lineNumbers: false, }, }); ``` ### sourceMap * **Type:** `boolean` * **Default:** the same as [output.sourceMap.css](/config/output/source-map.md) Whether to generate source map. ```ts pluginStylus({ sourceMap: false, }); ``` --- url: /plugins/dev/core.md --- # Plugin core This section describes the core plugin types and APIs. ## RsbuildPlugin The type of the plugin object. The plugin object contains the following properties: * `name`: The name of the plugin, a unique identifier. * `setup`: The setup function of the plugin, which can be an async function. This function is called once when the plugin is initialized. The plugin API provides the context info, utility functions and lifecycle hooks. For a complete introduction to lifecycle hooks, please read the [Plugin Hooks](/plugins/dev/hooks.md) chapter. * `pre`: Declare the names of pre-plugins, which will be executed before the current plugin. * `post`: Declare the names of post-plugins, which will be executed after the current plugin. * `remove`: Declare the plugins that need to be removed, you can pass an array of plugin names. The type of the plugin object, which contains the following properties: ```ts type RsbuildPlugin = { name: string; pre?: string[]; post?: string[]; remove?: string[]; setup: (api: RsbuildPluginAPI) => Promise | void; }; ``` You can import this type from `@rsbuild/core`: ```ts import type { RsbuildPlugin } from '@rsbuild/core'; export default (): RsbuildPlugin => ({ name: 'plugin-foo', pre: ['plugin-bar'], setup(api) { api.onAfterBuild(() => { console.log('after build!'); }); }, }); ``` ### Pre-Plugins By default, plugins are executed in the order they are added. You can declare pre-execution plugins using the `pre` field. For example, consider the following two plugins: ```ts const pluginFoo = { name: 'plugin-foo', }; const pluginBar = { name: 'plugin-bar', pre: ['plugin-foo'], }; ``` The Bar plugin is configured with the Foo plugin in its `pre` field, so the Foo plugin will always be executed before the Bar plugin. ### Post-Plugins Similarly, you can declare post-execution plugins using the `post` field. ```ts const pluginFoo = { name: 'plugin-foo', }; const pluginBar = { name: 'plugin-bar', post: ['plugin-foo'], }; ``` The Bar plugin is configured with the Foo plugin in its `post` field, so the Foo plugin will always be executed after the Bar plugin. ### Removing plugins You can remove other plugins within a plugin using the `remove` field. ```ts const pluginFoo = { name: 'plugin-foo', }; const pluginBar = { name: 'plugin-bar', remove: ['plugin-foo'], }; ``` For example, if you register both the Foo and Bar plugins mentioned above, the Foo plugin will not take effect because the Bar plugin declares the removal of the Foo plugin. It should be noted that if the current plugin is registered as a [specific environment plugin](https://rsbuild.dev/guide/advanced/environments#add-plugins-for-specified-environment), only the removal of plugins in the same environment is supported, and global plugins cannot be removed. ## api.context `api.context` is a read-only object that provides some context information. The content of `api.context` is exactly the same as `rsbuild.context`, please refer to [rsbuild.context](/api/javascript-api/instance.md#rsbuildcontext). * **Example:** ```ts const pluginFoo = () => ({ setup(api) { console.log(api.context.distPath); }, }); ``` ## api.getRsbuildConfig * **Example:** ```ts const pluginFoo = () => ({ setup(api) { const config = api.getRsbuildConfig(); console.log(config.html?.title); }, }); ``` ## api.getNormalizedConfig * **Example:** ```ts const pluginFoo = () => ({ setup(api) { api.onBeforeBuild(({ bundlerConfigs }) => { const config = api.getNormalizedConfig(); console.log(config.html.title); }); }, }); ``` ## api.isPluginExists * **Example:** ```ts export default () => ({ setup(api) { console.log(api.isPluginExists('plugin-foo')); }, }); ``` ## api.transform Used to transform the code of modules. * **Type:** ```ts function Transform( descriptor: TransformDescriptor, handler: TransformHandler, ): void; ``` `api.transform` accepts two params: * `descriptor`: an object describing the module's matching conditions. * `handler`: a transformation function that takes the current module code and returns the transformed code. ### Example For example, match modules with the `.pug` extension and transform them to JavaScript code: ```js import pug from 'pug'; const pluginPug = () => ({ name: 'my-pug-plugin', setup(api) { api.transform({ test: /\.pug$/ }, ({ code }) => { const templateCode = pug.compileClient(code, {}); return `${templateCode}; module.exports = template;`; }); }, }); ``` ### Descriptor param The descriptor param is an object describing the module's matching conditions. * **Type:** ```ts type TransformDescriptor = { test?: RuleSetCondition; targets?: RsbuildTarget[]; environments?: string[]; resourceQuery?: RuleSetCondition; raw?: boolean; layer?: string; }; ``` The `descriptor` param supports the following matching conditions: * `test`: matches module's path (without query), the same as Rspack's [Rule.test](https://rspack.dev/config/module#ruletest). ```js api.transform({ test: /\.pug$/ }, ({ code }) => { // ... }); ``` * `targets`: matches the Rsbuild [output.target](/config/output/target.md), and applies the current transform function only to the matched targets. ```js api.transform({ test: /\.pug$/, targets: ['web'] }, ({ code }) => { // ... }); ``` * `environments`: matches the Rsbuild [environment](/guide/advanced/environments.md) name, and applies the current transform function only to the matched environments. ```js api.transform({ test: /\.pug$/, environments: ['web'] }, ({ code }) => { // ... }); ``` * `resourceQuery`: matches module's query, the same as Rspack's [Rule.resourceQuery](https://rspack.dev/config/module#ruleresourcequery). ```js api.transform({ resourceQuery: /raw/ }, ({ code }) => { // ... }); ``` * `raw`: if raw is `true`, the transform handler will receive the Buffer type code instead of the string type. ```js api.transform({ test: /\.node$/, raw: true }, ({ code }) => { // ... }); ``` * `layer`: the same as Rspack's [Rule.layer](https://rspack.dev/config/module#rulelayer). * `issuerLayer`: the same as Rspack's [Rule.issuerLayer](https://rspack.dev/config/module#ruleissuerlayer). * `issuer`: the same as Rspack's [Rule.issuer](https://rspack.dev/config/module#ruleissuer). * `with`: the same as Rspack's [Rule.with](https://rspack.dev/config/module#rulewith). ### Handler param The handler param is a transformation function that takes the current module code and returns the transformed code. * **Type:** ```ts type TransformContext = { code: string; context: string | null; resource: string; resourcePath: string; resourceQuery: string; environment: EnvironmentContext; addDependency: (file: string) => void; addMissingDependency: (file: string) => void; addContextDependency: (context: string) => void; emitFile: Rspack.LoaderContext['emitFile']; importModule: Rspack.LoaderContext['importModule']; resolve: Rspack.LoaderContext['resolve']; }; type TransformResult = | string | { code: string; map?: string | Rspack.sources.RawSourceMap | null; }; type TransformHandler = ( context: TransformContext, ) => MaybePromise; ``` The `handler` function provides the following params: * `code`: The code of the module. * `context`: The directory path of the currently processed module. The same as Rspack loader's [this.context](https://rspack.dev/api/loader-api/context#thiscontext). * `resolve`: Resolve a module specifier. The same as Rspack loader's [this.resolve](https://rspack.dev/api/loader-api/context#thisresolve). * `resource`: The absolute path of the module, including the query. * `resourcePath`: The absolute path of the module, without the query. * `resourceQuery`: The query of the module. * `environment`: The [environment context](/api/javascript-api/environment-api.md#environment-context) for current build. * `addDependency`: Add an additional file as the dependency. The file will be watched and changes to the file will trigger rebuild. The same as Rspack loader's [this.addDependency](https://rspack.dev/api/loader-api/context#thisadddependency). * `addMissingDependency`: Add an non-existing file as the dependency. The file will be watched and changes to the file will trigger rebuild. The same as Rspack loader's [this.addMissingDependency](https://rspack.dev/api/loader-api/context#thisaddmissingdependency). * `addContextDependency`: Add an additional directory as the dependency. The directory will be watched and changes to the directory will trigger rebuild. The same as Rspack loader's [this.addContextDependency](https://rspack.dev/api/loader-api/context#thisaddcontextdependency). * `emitFile`: Emits a file to the build output. The same as Rspack loader's [this.emitFile](https://rspack.dev/api/loader-api/context#thisemitfile). * `importModule`: Compile and execute a module at the build time. The same as Rspack loader's [this.importModule](https://rspack.dev/api/loader-api/context#thisimportmodule). For example: ```js api.transform( { test: /\.pug$/ }, ({ code, resource, resourcePath, resourceQuery }) => { console.log(code); // -> some code console.log(resource); // -> '/home/user/project/src/template.pug?foo=123' console.log(resourcePath); // -> '/home/user/project/src/template.pug' console.log(resourceQuery); // -> '?foo=123' }, ); ``` ### Difference with loader `api.transform` can be thought of as a lightweight implementation of Rspack loader. It provides a simple and easy to use API and automatically calls Rspack loader at the backend to transform the code. In Rsbuild plugins, you can quickly implement code transformation functions using `api.transform`, which can handle the majority of common scenarios without having to learn how to write an Rspack loader. Note that for some complex code transformation scenarios, `api.transform` may not be sufficient. In such situations, you can implement it using the Rspack loader. ## api.resolve Intercept and modify module request information before module resolution begins. The same as Rspack's [normalModuleFactory.hooks.resolve](https://rspack.dev/api/plugin-api/normal-module-factory-hooks#resolve) hook. * **Version:** `>= 1.0.17` * **Type:** ```ts function ResolveFn(handler: ResolveHandler): void; ``` ### Example * Modify the request of `a.js` file: ```js api.resolve(({ resolveData }) => { if (resolveData.request === './a.js') { resolveData.request = './b.js'; } }); ``` ### Handler param The `handler` parameter is a callback function that receives a module require information and allows you to modify it. * **Type:** ```ts type ResolveHandler = (context: { resolveData: Rspack.ResolveData; compiler: Rspack.Compiler; compilation: Rspack.Compilation; environment: EnvironmentContext; }) => Promise | void; ``` The `handler` function provides the following parameters: * `resolveData`: Module request information. For details, please refer to [Rspack - resolve hook](https://rspack.dev/api/plugin-api/normal-module-factory-hooks#resolve). * `compiler`: The Compiler object of Rspack. * `compilation`: The Compilation object of Rspack. * `environment`: The environment context of the current build. ## api.processAssets Modify assets before emitting, the same as Rspack's [compilation.hooks.processAssets](https://rspack.dev/api/plugin-api/compilation-hooks#processassets) hook. * **Version:** `>= 1.0.0` * **Type:** ```ts function processAssets( descriptor: ProcessAssetsDescriptor, handler: ProcessAssetsHandler, ): void; ``` `api.processAssets` accepts two params: * `descriptor`: an object to describes the stage and matching conditions that trigger `processAssets`. * `handler`: A callback function that receives the assets object and allows you to modify it. ### Example * Emit a new asset in the `additional` stage: ```js api.processAssets( { stage: 'additional' }, ({ assets, sources, compilation }) => { const source = new sources.RawSource('This is a new asset!'); compilation.emitAsset('new-asset.txt', source); }, ); ``` * Updating an existing asset: ```js api.processAssets( { stage: 'additions' }, ({ assets, sources, compilation }) => { const asset = assets['foo.js']; if (!asset) { return; } const oldContent = asset.source(); const newContent = oldContent + '\nconsole.log("hello world!")'; const source = new sources.RawSource(newContent); compilation.updateAsset(assetName, source); }, ); ``` * Removing an asset: ```js api.processAssets({ stage: 'optimize' }, ({ assets, compilation }) => { const assetName = 'unwanted-script.js'; if (assets[assetName]) { compilation.deleteAsset(assetName); } }); ``` ### Descriptor param The descriptor parameter is an object to describes the stage and matching conditions that trigger `processAssets`. * **Type:** ```ts type ProcessAssetsDescriptor = { stage: ProcessAssetsStage; targets?: RsbuildTarget[]; environments?: string[]; }; ``` The `descriptor` param supports the following properties: * `stage`: Rspack internally divides `processAssets` into multiple stages (refer to [process assets stages](#process-assets-stages)). You can choose the appropriate stage based on the operations you need to perform. ```js api.processAssets({ stage: 'additional' }, ({ assets }) => { // ... }); ``` * `targets`: Matches the Rsbuild [output.target](/config/output/target.md), and applies the current processAssets function only to the matched targets. ```js api.processAssets({ stage: 'additional', targets: ['web'] }, ({ assets }) => { // ... }); ``` * `environments`: matches the Rsbuild [environment](/guide/advanced/environments.md) name, and applies the current processAssets function only to the matched environments. ```js api.processAssets( { stage: 'additional', environments: ['web'] }, ({ assets }) => { // ... }, ); ``` ### Handler param The `handler` parameter is a callback function that receives an assets object and allows you to modify it. * **Type:** ```ts type ProcessAssetsHandler = (context: { assets: Record; compiler: Rspack.Compiler; compilation: Rspack.Compilation; environment: EnvironmentContext; sources: RspackSources; }) => Promise | void; ``` The `handler` function provides the following parameters: * `assets`: An object where key is the asset's pathname, and the value is data of the asset represented by the [Source](https://github.com/webpack/webpack-sources#source). * `compiler`: The Compiler object of Rspack. * `compilation`: The Compilation object of Rspack. * `environment`: The [environment context](/api/javascript-api/environment-api.md#environment-context) of the current build. * `sources`: The [Rspack Sources](https://github.com/webpack/webpack-sources#source) object, which contains multiple classes which represent a Source. ### Process assets stages Here's the list of supported stages. Rspack will execute these stages sequentially from top to bottom. Please select the appropriate stage based on the operation you need to perform. * `additional` — add additional assets to the compilation. * `pre-process` — basic preprocessing of the assets. * `derived` — derive new assets from the existing assets. * `additions` — add additional sections to the existing assets e.g. banner or initialization code. * `optimize` — optimize existing assets in a general way. * `optimize-count` — optimize the count of existing assets, e.g. by merging them. * `optimize-compatibility` — optimize the compatibility of existing assets, e.g. add polyfills or vendor prefixes. * `optimize-size` — optimize the size of existing assets, e.g. by minimizing or omitting whitespace. * `dev-tooling` — add development tooling to the assets, e.g. by extracting a source map. * `optimize-inline` — optimize the numbers of existing assets by inlining assets into other assets. * `summarize` — summarize the list of existing assets. * `optimize-hash` — optimize the hashes of the assets, e.g. by generating real hashes of the asset content. * `optimize-transfer` — optimize the transfer of existing assets, e.g. by preparing a compressed (gzip) file as separate asset. * `analyse` — analyze the existing assets. * `report` — creating assets for the reporting purposes. ## api.expose Used for plugin communication. `api.expose` can explicitly expose some properties or methods of the current plugin, and other plugins can get these APIs through `api.useExposed`. * **Type:** ```ts /** * @param id Unique identifier, using Symbol can avoid naming conflicts * @param api Properties or methods to be exposed, it is recommended to use object format */ function expose(id: string | symbol, api: T): void; ``` * **Example:** ```ts const pluginParent = () => ({ name: 'plugin-parent', setup(api) { api.expose('plugin-parent', { value: 1, double: (val: number) => val * 2, }); }, }); ``` ## api.useExposed Used for plugin communication. `api.useExposed` can get the properties or methods exposed by other plugins. * **Type:** ```ts /** * @param id Unique identifier * @returns The properties or methods obtained */ function useExposed(id: string | symbol): T | undefined; ``` * **Example:** ```ts const pluginChild = () => ({ name: 'plugin-child', pre: ['plugin-parent'], setup(api) { const parentApi = api.useExposed('plugin-parent'); if (parentApi) { console.log(parentApi.value); // -> 1 console.log(parentApi.double(1)); // -> 2 } }, }); ``` ### Identifiers You can use Symbol as a unique identifier to avoid potential naming conflicts: ```ts // pluginParent.ts export const PARENT_API_ID = Symbol('plugin-parent'); const pluginParent = () => ({ name: 'plugin-parent', setup(api) { api.expose(PARENT_API_ID, { // some api }); }, }); // pluginChild.ts import { PARENT_API_ID } from './pluginParent'; const pluginChild = () => ({ name: 'plugin-child', setup(api) { const parentApi = api.useExposed(PARENT_API_ID); if (parentApi) { console.log(parentApi); } }, }); ``` ### Type declaration You can declare types through the generics of the function: ```ts // pluginParent.ts export type ParentAPI = { // ... }; // pluginChild.ts import type { ParentAPI } from './pluginParent'; const pluginChild = () => ({ name: 'plugin-child', setup(api) { const parentApi = api.useExposed(PARENT_API_ID); if (parentApi) { console.log(parentApi); } }, }); ``` ### Execution order When communicating between plugins, you need to be aware of the order in which the plugins are executed. For example, in the above example, if `pluginParent` is not registered, or registers after `pluginChild`, then `api.useExposed('plugin-parent')` will return an `undefined`. You can use the `pre`, `post` options of the plugin object, and the `order` option of the plugin hook to ensure the order is correct. --- url: /plugins/dev/hooks.md --- # Plugin hooks This chapter introduces the plugin hooks available for Rsbuild plugins. ## Overview ### Common hooks * [modifyRsbuildConfig](#modifyrsbuildconfig): Modify the configuration passed to Rsbuild. * [modifyEnvironmentConfig](#modifyenvironmentconfig): Modify the Rsbuild configuration of a specific environment. * [modifyRspackConfig](#modifyrspackconfig): Modify the configuration passed to Rspack. * [modifyBundlerChain](#modifybundlerchain): Modify the configuration of Rspack through the chain API. * [modifyHTMLTags](#modifyhtmltags): Modify the tags that are injected into the HTML. * [onBeforeCreateCompiler](#onbeforecreatecompiler): Called before creating a compiler instance. * [onAfterCreateCompiler](#onaftercreatecompiler): Called after creating a compiler instance and before building. * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile): Called before the compilation of a single environment. * [onAfterEnvironmentCompile](#onafterenvironmentcompile): Called after the compilation of a single environment. You can get the build result information. * [onExit](#onexit): Called when the process is about to exit. ### Dev hooks Called only when running the `rsbuild dev` command or the `rsbuild.startDevServer()` method. * [onBeforeStartDevServer](#onbeforestartdevserver): Called before starting the dev server. * [onAfterStartDevServer](#onafterstartdevserver): Called after starting the dev server. * [onDevCompileDone](#ondevcompiledone): Called after each build in development mode. Called only when Rsbuild is restarted or when the [close()](/api/javascript-api/instance.md#close-server) method of `rsbuild.startDevServer()` is executed. * [onCloseDevServer](#onclosedevserver): Called when the dev server is closed. ### Build hooks Called only when running the `rsbuild build` command or the `rsbuild.build()` method. * [onBeforeBuild](#onbeforebuild): Called before running the production build. * [onAfterBuild](#onafterbuild): Called after running the production build. You can get the build result information. Called only when Rsbuild is restarted or when the [close()](/api/javascript-api/instance.md#close-build) method of `rsbuild.build()` is executed. * [onCloseBuild](#onclosebuild): Called when the build is closed. ### Preview hooks Called only when running the `rsbuild preview` command or the `rsbuild.preview()` method. * [onBeforeStartProdServer](#onbeforestartprodserver): Called before starting the production server. * [onAfterStartProdServer](#onafterstartprodserver): Called after starting the production server. ## Hooks order ### Dev hooks When the `rsbuild dev` command or `rsbuild.startDevServer()` method is executed, Rsbuild will execute the following hooks in order: * [modifyRsbuildConfig](#modifyrsbuildconfig) * [modifyEnvironmentConfig](#modifyenvironmentconfig) * [onBeforeStartDevServer](#onbeforestartdevserver) * [modifyBundlerChain](#modifybundlerchain) * [modifyRspackConfig](#modifyrspackconfig) * [onBeforeCreateCompiler](#onbeforecreatecompiler) * [onAfterCreateCompiler](#onaftercreatecompiler) * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile) * [onAfterStartDevServer](#onafterstartdevserver) * [modifyHTMLTags](#modifyhtmltags) * [onAfterEnvironmentCompile](#onafterenvironmentcompile) * [onDevCompileDone](#ondevcompiledone) * [onCloseDevServer](#onclosedevserver) * [onExit](#onexit) When rebuilding, the following hooks will be triggered again: * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile) * [modifyHTMLTags](#modifyhtmltags) * [onAfterEnvironmentCompile](#onafterenvironmentcompile) * [onDevCompileDone](#ondevcompiledone) ### Build hooks When the `rsbuild build` command or `rsbuild.build()` method is executed, Rsbuild will execute the following hooks in order: * [modifyRsbuildConfig](#modifyrsbuildconfig) * [modifyEnvironmentConfig](#modifyenvironmentconfig) * [modifyBundlerChain](#modifybundlerchain) * [modifyRspackConfig](#modifyrspackconfig) * [onBeforeCreateCompiler](#onbeforecreatecompiler) * [onAfterCreateCompiler](#onaftercreatecompiler) * [onBeforeBuild](#onbeforebuild) * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile) * [modifyHTMLTags](#modifyhtmltags) * [onAfterEnvironmentCompile](#onafterenvironmentcompile) * [onAfterBuild](#onafterbuild) * [onCloseBuild](#onclosebuild) * [onExit](#onexit) When rebuilding, the following hooks will be triggered again: * [onBeforeBuild](#onbeforebuild) * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile) * [modifyHTMLTags](#modifyhtmltags) * [onAfterEnvironmentCompile](#onafterenvironmentcompile) * [onAfterBuild](#onafterbuild) ### Preview hooks When executing the `rsbuild preview` command or `rsbuild.preview()` method, Rsbuild will execute the following hooks in order: * [modifyRsbuildConfig](#modifyrsbuildconfig) * [modifyEnvironmentConfig](#modifyenvironmentconfig) * [onBeforeStartProdServer](#onbeforestartprodserver) * [onAfterStartProdServer](#onafterstartprodserver) * [onExit](#onexit) ## Global hooks vs environment hooks In Rsbuild, some of the plugin hooks are global hooks. The execution of these hooks is often related to Rsbuild's own startup process or global logic and is shared under all environments. Such as: * `modifyRsbuildConfig` is used to modify the basic configuration of Rsbuild. The basic configuration will eventually be merged with the environment configuration; * `onBeforeStartDevServer` and `onAfterStartDevServer` are related to the Rsbuild dev server startup process, all environments share Rsbuild's dev server, middlewares, and WebSocket. Correspondingly, there are some plugin hooks that are related to the current environment. These hooks are executed with a specific environment context and are triggered multiple times depending on the environment. ### Global hooks * [modifyRsbuildConfig](#modifyrsbuildconfig) * [onBeforeStartDevServer](#onbeforestartdevserver) * [onBeforeCreateCompiler](#onbeforecreatecompiler) * [onAfterCreateCompiler](#onaftercreatecompiler) * [onAfterStartDevServer](#onafterstartdevserver) * [onDevCompileDone](#ondevcompiledone) * [onCloseDevServer](#onclosedevserver) * [onBeforeBuild](#onbeforebuild) * [onAfterBuild](#onafterbuild) * [onCloseBuild](#onclosebuild) * [onBeforeStartProdServer](#onbeforestartprodserver) * [onAfterStartProdServer](#onafterstartprodserver) * [onExit](#onexit) ### Environment hooks * [modifyEnvironmentConfig](#modifyenvironmentconfig) * [modifyBundlerChain](#modifybundlerchain) * [modifyRspackConfig](#modifyrspackconfig) * [modifyHTMLTags](#modifyhtmltags) * [onBeforeEnvironmentCompile](#onbeforeenvironmentcompile) * [onAfterEnvironmentCompile](#onafterenvironmentcompile) ## Callback order ### Default behavior If multiple plugins register the same hook, the callback functions of the hook will execute in the order in which they were registered. In the following example, the console will output `'1'` and `'2'` in sequence: ```ts const plugin1 = () => ({ setup(api) { api.modifyRsbuildConfig(() => console.log('1')); }, }); const plugin2 = () => ({ setup(api) { api.modifyRsbuildConfig(() => console.log('2')); }, }); rsbuild.addPlugins([plugin1, plugin2]); ``` ### `order` Field When registering a hook, you can declare the order of hook through the `order` field. ```ts type HookDescriptor any> = { handler: T; order: 'pre' | 'post' | 'default'; }; ``` In the following example, the console will sequentially output `'2'` and `'1'`, because `order` was set to `pre` when plugin2 called `modifyRsbuildConfig`. ```ts const plugin1 = () => ({ setup(api) { api.modifyRsbuildConfig(() => console.log('1')); }, }); const plugin2 = () => ({ setup(api) { api.modifyRsbuildConfig({ handler: () => console.log('2'), order: 'pre', }); }, }); rsbuild.addPlugins([plugin1, plugin2]); ``` ## Common hooks ### modifyRsbuildConfig Modify the config passed to the Rsbuild, you can directly modify the config object, or return a new object to replace the previous object. :::warning `modifyRsbuildConfig` is a global hook. To add support for your plugin as an [environment-specific plugin](/guide/advanced/environments.md#add-plugins-for-specified-environment), you should use [modifyEnvironmentConfig](/plugins/dev/hooks.md#modifyenvironmentconfig) instead of `modifyRsbuildConfig`. ::: * **Type:** ```ts type ModifyRsbuildConfigUtils = { mergeRsbuildConfig: typeof mergeRsbuildConfig; }; function ModifyRsbuildConfig( callback: ( config: RsbuildConfig, utils: ModifyRsbuildConfigUtils, ) => MaybePromise, ): void; ``` * **Example:** Setting a default value for a specific config option: ```ts const myPlugin = () => ({ setup(api) { api.modifyRsbuildConfig((config) => { config.html ||= {}; config.html.title = 'My Default Title'; }); }, }); ``` * **Example:** Using `mergeRsbuildConfig` to merge config objects, and return the merged object. ```ts import type { RsbuildConfig } from '@rsbuild/core'; const myPlugin = () => ({ setup(api) { api.modifyRsbuildConfig((userConfig, { mergeRsbuildConfig }) => { const extraConfig: RsbuildConfig = { source: { // ... }, output: { // ... }, }; // extraConfig will override fields in userConfig, // If you do not want to override the fields in userConfig, // you can adjust to `mergeRsbuildConfig(extraConfig, userConfig)` return mergeRsbuildConfig(userConfig, extraConfig); }); }, }); ``` :::tip `modifyRsbuildConfig` cannot be used to register additional Rsbuild plugins. This is because at the time `modifyRsbuildConfig` is executed, Rsbuild has already initialized all plugins and started executing the callbacks of the hooks. For details, please refer to [Plugin registration phase](/config/plugins.md#plugin-registration-phase). ::: ### modifyEnvironmentConfig Modify the Rsbuild configuration of a specific environment. In the callback function, the config object in the parameters has already been merged with the common Rsbuild configuration. You can directly modify this config object, or you can return a new object to replace it. * **Type:** ```ts type ArrayAtLeastOne = [A, ...Array] | [...Array, A]; type ModifyEnvironmentConfigUtils = { /** Current environment name */ name: string; mergeEnvironmentConfig: ( ...configs: ArrayAtLeastOne ) => EnvironmentConfig; }; function ModifyEnvironmentConfig( callback: ( config: EnvironmentConfig, utils: ModifyEnvironmentConfigUtils, ) => MaybePromise, ): void; ``` * **Example:** Set a default value for the Rsbuild config of a specified environment: ```ts const myPlugin = () => ({ setup(api) { api.modifyEnvironmentConfig((config, { name }) => { if (name !== 'web') { return config; } config.html.title = 'My Default Title'; }); }, }); ``` * **Example:** Using `mergeEnvironmentConfig` to merge config objects, and return the merged object. ```ts import type { EnvironmentConfig } from '@rsbuild/core'; const myPlugin = () => ({ setup(api) { api.modifyEnvironmentConfig((userConfig, { mergeEnvironmentConfig }) => { const extraConfig: EnvironmentConfig = { source: { // ... }, output: { // ... }, }; // extraConfig will override fields in userConfig, // If you do not want to override the fields in userConfig, // you can adjust to `mergeEnvironmentConfig(extraConfig, userConfig)` return mergeEnvironmentConfig(userConfig, extraConfig); }); }, }); ``` ### modifyRspackConfig To modify the Rspack config, you can directly modify the config object, or return a new object to replace the previous object. :::tip `modifyRspackConfig` is executed earlier than [tools.rspack](/config/tools/rspack.md). Therefore, the modifications made by `tools.rspack` cannot be obtained in `modifyRspackConfig`. ::: * **Type:** ```ts type ModifyRspackConfigUtils = { environment: EnvironmentContext; env: string; isDev: boolean; isProd: boolean; target: RsbuildTarget; isServer: boolean; isWebWorker: boolean; rspack: Rspack; HtmlPlugin: typeof import('html-rspack-plugin'); // more... }; function ModifyRspackConfig( callback: ( config: Rspack.Configuration, utils: ModifyRspackConfigUtils, ) => Promise | Rspack.Configuration | void, ): void; ``` * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.modifyRspackConfig((config, utils) => { if (utils.env === 'development') { config.devtool = 'eval-cheap-source-map'; } }); }, }); ``` The second parameter `utils` of the callback function is an object, which contains some utility functions and properties, see [tools.rspack - Utils](/config/tools/rspack.md#utils) for more details. ### modifyBundlerChain `modifyBundlerChain` allows you to modify the Rspack configuration using the `rspack-chain` API, providing the same functionality as [tools.bundlerChain](/config/tools/bundler-chain.md). * **Type:** ```ts type ModifyBundlerChainUtils = { environment: EnvironmentContext; env: string; isDev: boolean; isProd: boolean; target: RsbuildTarget; isServer: boolean; isWebWorker: boolean; CHAIN_ID: ChainIdentifier; HtmlPlugin: typeof import('html-rspack-plugin'); bundler: { // some Rspack built-in plugins }; }; function ModifyBundlerChain( callback: ( chain: RspackChain, utils: ModifyBundlerChainUtils, ) => Promise | void, ): void; ``` * **Example:** ```ts import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; const myPlugin = () => ({ setup(api) { api.modifyBundlerChain((chain, utils) => { if (utils.env === 'development') { chain.devtool('eval'); } chain.plugin('bundle-analyze').use(BundleAnalyzerPlugin); }); }, }); ``` The second parameter `utils` of the callback function is an object, which contains some utility functions and properties, see [tools.bundlerChain - Utils](/config/tools/bundler-chain.md#utils) for more details. ### modifyHTMLTags Modify the tags that are injected into the HTML. * **Type:** ```ts type HtmlBasicTag = { // Tag name tag: string; // Attributes of the tag attrs?: Record; // innerHTML of the tag children?: string; }; type HTMLTags = { // Tags group inserted into headTags: HtmlBasicTag[]; // Tags group inserted into bodyTags: HtmlBasicTag[]; }; type Context = { /** * The Compiler object of Rspack. */ compiler: Rspack.Compiler; /** * The Compilation object of Rspack. */ compilation: Rspack.Compilation; /** * URL prefix of assets. * @example 'https://example.com/' */ assetPrefix: string; /** * The name of the HTML file, relative to the dist directory. * @example 'index.html' */ filename: string; /** * The environment context for current build. */ environment: EnvironmentContext; }; function ModifyHTMLTags( callback: (tags: HTMLTags, context: Context) => MaybePromise, ): void; ``` * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.modifyHTMLTags(({ headTags, bodyTags }) => { headTags.push({ tag: 'script', attrs: { src: 'https://example.com/foo.js' }, }); bodyTags.push({ tag: 'script', children: 'console.log("hello world!");', }); return { headTags, bodyTags }; }); }, }); ``` ### onBeforeCreateCompiler * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onBeforeCreateCompiler(({ bundlerConfigs }) => { console.log('the bundler config is ', bundlerConfigs); }); }, }); ``` ### onAfterCreateCompiler * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterCreateCompiler(({ compiler }) => { console.log('the compiler is ', compiler); }); }, }); ``` ### onBeforeEnvironmentCompile * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onBeforeEnvironmentCompile(({ bundlerConfig, environment }) => { console.log( `the bundler config for the ${environment.name} is `, bundlerConfig, ); }); }, }); ``` ### onAfterEnvironmentCompile * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterEnvironmentCompile(({ isFirstCompile, stats }) => { console.log(stats?.toJson(), isFirstCompile); }); }, }); ``` ## Build hooks ### onBeforeBuild * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onBeforeBuild(({ bundlerConfigs }) => { console.log('the bundler config is ', bundlerConfigs); }); }, }); ``` ### onAfterBuild * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterBuild(({ isFirstCompile, stats }) => { console.log(stats?.toJson(), isFirstCompile); }); }, }); ``` ### onCloseBuild * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onCloseBuild(() => { console.log('close build!'); }); }, }); ``` ## Dev hooks ### onBeforeStartDevServer * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onBeforeStartDevServer(({ server, environments }) => { console.log('before starting dev server.'); console.log('the server is ', server); console.log('the environments contexts are: ', environments); }); }, }); ``` #### Register middlewares A common usage scenario is to register custom middlewares in `onBeforeStartDevServer`: ```ts const myPlugin = () => ({ setup(api) { api.onBeforeStartDevServer(({ server }) => { server.middlewares.use((req, res, next) => { next(); }); }); }, }); ``` When `onBeforeStartDevServer` is called, the default middlewares of Rsbuild are not registered yet, so the middlewares you add will run before the default middlewares. `onBeforeStartDevServer` allows you to return a callback function, which will be called when the default middlewares of Rsbuild are registered. The middlewares you register in the callback function will run after the default middlewares. ```ts const myPlugin = () => ({ setup(api) { api.onBeforeStartDevServer(({ server }) => { // the returned callback will be called when the default // middlewares are registered return () => { server.middlewares.use((req, res, next) => { next(); }); }; }); }, }); ``` #### Store server instance If you need to access `server` in other hooks, you can store the `server` instance through `api.onBeforeStartDevServer`, and then access it in the hooks executed later. Note that you cannot access `server` in hooks that are executed earlier than `onBeforeStartDevServer`. ```ts import type { RsbuildDevServer } from '@rsbuild/core'; const myPlugin = () => ({ setup(api) { let devServer: RsbuildDevServer | null = null; api.onBeforeStartDevServer(({ server, environments }) => { devServer = server; }); api.transform({ test: /\.foo$/ }, ({ code }) => { if (devServer) { // access server API } return code; }); api.onCloseDevServer(() => { devServer = null; }); }, }); ``` ### onAfterStartDevServer * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterStartDevServer(({ port, routes }) => { console.log('this port is: ', port); console.log('this routes is: ', routes); }); }, }); ``` ### onAfterEnvironmentCompile * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterEnvironmentCompile(({ isFirstCompile }) => { if (isFirstCompile) { console.log('first compile!'); } else { console.log('re-compile!'); } }); }, }); ``` ### onDevCompileDone * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onDevCompileDone(({ isFirstCompile }) => { if (isFirstCompile) { console.log('first compile!'); } else { console.log('re-compile!'); } }); }, }); ``` ### onCloseDevServer * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onCloseDevServer(async () => { console.log('close dev server!'); }); }, }); ``` ## Preview hooks ### onBeforeStartProdServer * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onBeforeStartProdServer(() => { console.log('before start!'); }); }, }); ``` ### onAfterStartProdServer * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onAfterStartProdServer(({ port, routes }) => { console.log('this port is: ', port); console.log('this routes is: ', routes); }); }, }); ``` ## Other hooks ### onExit * **Example:** ```ts const myPlugin = () => ({ setup(api) { api.onExit(({ exitCode }) => { console.log('exit: ', exitCode); }); }, }); ``` --- url: /api/start/index.md --- # JavaScript API Rsbuild provides a complete set of JavaScript APIs for developers to build higher level tools or frameworks on top of Rsbuild. Rsbuild's JavaScript API can be used in Node.js, Deno, or Bun. ## Access example Here is a basic example of how to access the Rsbuild JavaScript API. ### 1. Install Rsbuild You need to install the `@rsbuild/core` package: ### 2. Create an Rsbuild instance You can call the [createRsbuild](/api/javascript-api/core.md#creatersbuild) method to create an Rsbuild instance: ```ts import { createRsbuild } from '@rsbuild/core'; const rsbuild = await createRsbuild(); ``` The `createRsbuild` method provides some options, which you can learn more about in the [API - createRsbuild](/api/javascript-api/core.md#creatersbuild). ### 3. Call Rsbuild instance method The Rsbuild instance provides some methods, which you can use it according to the usage scenarios. To start local development, it is recommended to use the [rsbuild.startDevServer](/api/javascript-api/instance.md#rsbuildstartdevserver) method, which will start a local dev server. ```ts await rsbuild.startDevServer(); ``` After successfully starting dev server, you can see the following logs: ``` ➜ Local: http://localhost:3000 ➜ Network: http://192.168.0.1:3000 ``` To deploy the App to production environment, it is recommended to use the [rsbuild.build](/api/javascript-api/instance.md#rsbuildbuild) method, which will build the production outputs. ```ts await rsbuild.build(); ``` > For more introduction of Rsbuild instance methods, please read the [Rsbuild Instance](/api/javascript-api/instance.md) chapter. After completing the above three steps, you have learned the basic usage of Rsbuild. Next, you can customize the build process through the Rsbuild plugin and Rsbuild configs. ## Exports format Rsbuild provides exports in both ES Modules and CommonJS formats: ```js title="index.mjs" import { createRsbuild } from '@rsbuild/core'; ``` ```js title="index.cjs" const { createRsbuild } = require('@rsbuild/core'); ``` > It is recommended to use ES modules format, which is more in line with the community standards. --- url: /api/javascript-api/core.md --- # Rsbuild core This section describes some of the core methods provided by Rsbuild. ## createRsbuild Create an [Rsbuild instance](/api/javascript-api/instance.md). * **Type:** ```ts function createRsbuild( options?: CreateRsbuildOptions, ): Promise; ``` * **Example:** ```ts import { createRsbuild } from '@rsbuild/core'; const rsbuild = await createRsbuild({ rsbuildConfig: { // Rsbuild configuration }, }); ``` ### Options The first parameter of `createRsbuild` is an `options` object, you can pass in the following options: ```ts type CreateRsbuildOptions = { cwd?: string; environment?: string[]; rsbuildConfig?: RsbuildConfig | (() => Promise); loadEnv?: boolean | LoadEnvOptions; }; ``` * `cwd`: The root path of the current build, defaults to `process.cwd()`. * `environment`: Only build specified [environments](/guide/advanced/environments.md). If not specified or passing an empty array, all environments will be built. * `rsbuildConfig`: Rsbuild configuration object. Refer to [Configuration Overview](/config/index.md) for all available configuration options. * `loadEnv`:Whether to call the [loadEnv](/api/javascript-api/core.md#loadenv) method to load env variables and define them as global variables via [source.define](/config/source/define.md). ### Load configuration async `rsbuildConfig` can also be an async function, which allows you to dynamically load Rsbuild configuration and perform some custom operations. ```ts import { createRsbuild, loadConfig } from '@rsbuild/core'; const rsbuild = await createRsbuild({ rsbuildConfig: async () => { const { content } = await loadConfig(); someFunctionToUpdateConfig(content); return content; }, }); ``` ### Load env variables The `loadEnv` option in `createRsbuild` helps you call the [loadEnv](/api/javascript-api/core.md#loadenv) method to load env variables: ```ts const rsbuild = await createRsbuild({ loadEnv: true, }); ``` Passing `loadEnv: true` will automatically complete the following steps: 1. Call the `loadEnv` method to load env variables. 2. Add [source.define](/config/source/define.md) configuration, define the `publicVars` returned by `loadEnv` as global variables. 3. Watch the `.env` file for changes, and restart the dev server when the file changes, and invalidate the build cache. 4. Automatically call the `cleanup` method returned by `loadEnv` when closing the build or dev server. You can also pass in the options of the [loadEnv](/api/javascript-api/core.md#loadenv) method, for example: ```ts const rsbuild = await createRsbuild({ loadEnv: { prefixes: ['PUBLIC_', 'REACT_APP_'], }, }); ``` ## loadConfig Load Rsbuild configuration file. * **Type:** ```ts function loadConfig(params?: { // Default is process.cwd() cwd?: string; // Specify the configuration file, can be a relative or absolute path path?: string; meta?: Record; envMode?: string; loader?: 'jiti' | 'native'; }): Promise<{ content: RsbuildConfig; filePath: string | null; }>; ``` * **Example:** ```ts import { loadConfig } from '@rsbuild/core'; // Load `rsbuild.config.*` file by default const { content } = await loadConfig(); console.log(content); // -> Rsbuild config object const rsbuild = await createRsbuild({ rsbuildConfig: content, }); ``` If the Rsbuild config file does not exist in the cwd directory, the return value of the loadConfig method is `{ content: {}, filePath: null }`. ### Specify the configuration file Use the `path` option to load the `my-config.ts` configuration file: ```ts import { join } from 'node:path'; import { loadConfig } from '@rsbuild/core'; const { content } = await loadConfig({ path: join(__dirname, 'my-config.ts'), }); ``` ### Passing meta object Load the configuration file and pass in a custom meta object: ```ts import { join } from 'node:path'; import { loadConfig } from '@rsbuild/core'; const { content } = await loadConfig({ meta: { foo: 'bar', }, }); ``` In the `defineConfig` configuration function, you can access the `foo` variable through the `meta` object: ```ts title="rsbuild.config.ts" export default defineConfig(({ meta }) => { console.log(meta.foo); // bar return config; }); ``` ## loadEnv Load the [.env](/guide/advanced/env-vars.md#env-file) file and return all environment variables starting with the specified prefixes. * **Type:** ````ts type LoadEnvOptions = { /** * The root path to load the env file * @default process.cwd() */ cwd?: string; /** * Used to specify the name of the .env.[mode] file * Equivalent to Rsbuild CLI's `--env-mode` option * @default process.env.NODE_ENV */ mode?: string; /** * The prefix of public variables * @default ['PUBLIC_'] */ prefixes?: string[]; /** * Specify a target object to store environment variables. * If not provided, variables will be written to `process.env`. * @default process.env */ processEnv?: Record; }; type LoadEnvResult = { /** All env variables in the .env file */ parsed: Record; /** The absolute paths to all env files */ filePaths: string[]; /** * Env variables that start with prefixes. * * @example * ```ts * { * PUBLIC_FOO: 'bar', * } * ``` **/ rawPublicVars: Record; /** * Formatted env variables that start with prefixes. * The keys contain the prefixes `process.env.*` and `import.meta.env.*`. * The values are processed by `JSON.stringify`. * * @example * ```ts * { * 'process.env.PUBLIC_FOO': '"bar"', * 'import.meta.env.PUBLIC_FOO': '"bar"', * } * ``` **/ publicVars: Record; /** Clear the env variables mounted on `process.env` */ cleanup: () => void; }; function loadEnv(options: LoadEnvOptions): LoadEnvResult; ```` * **Example:** ```ts import { loadEnv, mergeRsbuildConfig } from '@rsbuild/core'; const { parsed, publicVars } = loadEnv(); const mergedConfig = mergeRsbuildConfig( { source: { define: publicVars, }, }, userConfig, ); ``` This method will also load files such as `.env.local` and `.env.[mode]`, see [Environment Variables](/guide/advanced/env-vars.md) for details. :::tip * Rsbuild CLI will automatically call the `loadEnv()` method. If you are using the Rsbuild CLI, you can set the `mode` parameter through the [--env-mode](/guide/advanced/env-vars.md#env-mode) option. * The `loadEnv` option in [createRsbuild](#creatersbuild) will help you call the `loadEnv()` method and handle related operations. ::: ### Specify the target object By default, `loadEnv` uses the `process.env` object to store environment variables. You can specify a target object to store environment variables through the `processEnv` option: ```ts import { loadEnv } from '@rsbuild/core'; // Pass an empty object to avoid modifying `process.env` loadEnv({ processEnv: {} }); // Pass a copy of the `process.env` object to avoid modifying the original object loadEnv({ processEnv: { ...process.env } }); ``` ## mergeRsbuildConfig Used to merge multiple Rsbuild configuration objects. The `mergeRsbuildConfig` function takes multiple configuration objects as parameters. It deep merges each configuration object, automatically combining multiple function values into an array of sequentially executed functions, and returns a merged configuration object. * **Type:** ```ts function mergeRsbuildConfig(...configs: RsbuildConfig[]): RsbuildConfig; ``` ### Basic example ```ts import { mergeRsbuildConfig } from '@rsbuild/core'; const config1 = { dev: { https: false, }, }; const config2 = { dev: { https: true, }, }; const mergedConfig = mergeRsbuildConfig(config1, config2); console.log(mergedConfig); // { dev: { https: true } } ``` > This method will not modify the config object in the input parameter. ### Merge rules In addition to deep merging, the `mergeRsbuildConfig` function also handles some options in a special way. For example, [tools.rspack](/config/tools/rspack.md) can be set as a function. When multiple configuration objects contain `tools.rspack`, `mergeRsbuildConfig` will not simply retain the last function. On the contrary, it will merge all `tools.rspack` functions or objects into an array. ```ts import { mergeRsbuildConfig } from '@rsbuild/core'; const config1 = { tools: { rspack: { someOption: true, }, }, }; const config2 = { tools: { rspack: (config) => { console.log('function 1'); return config; }, }, }; const config3 = { tools: { rspack: (config) => { console.log('function 2'); return config; }, }, }; const mergedConfig = mergeRsbuildConfig(config1, config2, config3); ``` In the above example, the merged configuration is in the following format. The array first contains an object `{ someOption: true }`, followed by two functions in the order they were merged. Each item in the array will be executed in sequence, and the output of the previous function will serve as the input to the next one, ultimately generating an Rspack configuration. ```ts const mergedConfig = { tools: { rspack: [ { someOption: true, }, (config) => { console.log('function 1'); return config; }, (config) => { console.log('function 2'); return config; }, ], }, }; ``` By this way, we can ensure that when merging multiple configuration objects, the same multiple `tools.rspack` fields can all be effective. In Rsbuild, most options that support function values use this rule, such as `tools.postcss`, `tools.less`, `tools.bundlerChain`, etc. ## logger Used to output log information in a unified format, based on [rslog](https://github.com/rspack-contrib/rslog). * **Example:** ```ts import { logger } from '@rsbuild/core'; // A gradient welcome log logger.greet(`\n➜ Rsbuild v1.0.0\n`); // Info logger.info('This is a info message'); // Start logger.start('This is a start message'); // Warn logger.warn('This is a warn message'); // Ready logger.ready('This is a ready message'); // Success logger.success('This is a success message'); // Error logger.error('This is a error message'); logger.error(new Error('This is a error message with stack')); // Debug logger.debug('This is a debug message'); // Same as console.log logger.log('This is a log message'); ``` ### Custom logger You can use the `logger.override` method to override partial or all methods of the default logger: ```ts import { logger } from '@rsbuild/core'; logger.override({ log: (message) => { console.log(`[log] ${message}`); }, info: (message) => { console.log(`[info] ${message}`); }, warn: (message) => { console.warn(`[warn] ${message}`); }, start: (message) => { console.log(`[start] ${message}`); }, ready: (message) => { console.log(`[ready] ${message}`); }, error: (message) => { console.error(`[error] ${message}`); }, success: (message) => { console.error(`[success] ${message}`); }, debug: (message) => { if (process.env.DEBUG) { console.log(`[debug] ${message}`); } }, }); logger.info('hello'); // [info] hello ``` ## rspack If you need to access the API or plugins exported by [@rspack/core](https://npmjs.com/package/@rspack/core), you can directly import the `rspack` object from `@rsbuild/core` without installing the `@rspack/core` package separately. * **Type:** `Rspack` * **Example:** ```ts // the same as `import { rspack } from '@rspack/core'` import { rspack } from '@rsbuild/core'; console.log(rspack.rspackVersion); // a.b.c console.log(rspack.util.createHash); console.log(rspack.BannerPlugin); ``` :::tip * Refer to [Rspack plugins](https://rspack.dev/plugins/) and [Rspack JavaScript API](https://rspack.dev/api/javascript-api/) to learn more about the available Rspack APIs. * It's not recommended to manually install the `@rspack/core` package, as it may conflict with the version that Rsbuild depends on. ::: ## version The version of `@rsbuild/core` currently in use. * **Type:** `string` * **Example:** ```ts import { version } from '@rsbuild/core'; console.log(version); // 1.0.0 ``` ## ensureAssetPrefix The `ensureAssetPrefix` function is used to prepend a given `assetPrefix` to a string that might be a URL. If the input string is already a complete URL, it returns the string directly. * **Type:** ```ts function ensureAssetPrefix( // URL string to be processed, can be a relative path or an absolute URL url: string, // URL prefix to be appended assetPrefix: string ) => string; ``` * **Example:** ```ts import { ensureAssetPrefix } from '@rsbuild/core'; ensureAssetPrefix('foo/bar.js', '/static/'); // -> '/static/foo/bar.js' ensureAssetPrefix('foo/bar.js', 'https://example.com/static/'); // -> 'https://example.com/static/foo/bar.js' ensureAssetPrefix( 'https://example.com/index.html', 'https://example.com/static/', ); // -> 'https://example.com/index.html' ``` --- url: /api/javascript-api/instance.md --- # Rsbuild instance This section describes all the properties and methods on the Rsbuild instance object. ## rsbuild.context `rsbuild.context` is a read-only object that provides some context information. ### context.version The version of `@rsbuild/core` currently in use. * **Type:** ```ts type Version = string; ``` ### context.rootPath The root path of current build, corresponding to the `cwd` option of [createRsbuild](/api/javascript-api/core.md#creatersbuild) method. * **Type:** ```ts type RootPath = string; ``` ### context.distPath The absolute path of the output directory, corresponding to the [output.distPath.root](/config/output/dist-path.md) config in `RsbuildConfig`. When there are multiple environments, Rsbuild will try to get the parent distPath of all environments as `context.distPath`. If you want to get the absolute path to the output directory of a specified environment, it is recommended to use [environment.distPath](/api/javascript-api/environment-api.md#distpath). * **Type:** ```ts type DistPath = string; ``` ### context.cachePath The absolute path of the build cache files. * **Type:** ```ts type CachePath = string; ``` ### context.devServer Dev server information, including the current dev server hostname and port number. * **Type:** ```ts type DevServer = { hostname: string; port: number; }; ``` ### context.action The current action type. * **Type:** ```ts type Action = 'dev' | 'build' | 'preview' | undefined; ``` `context.action` is set when running CLI commands or calling Rsbuild instance methods: * `dev`: will be set when running [rsbuild dev](/guide/basic/cli.md#rsbuild-dev) or [rsbuild.startDevServer()](/api/javascript-api/instance.md#rsbuildstartdevserver) * `build`: will be set when running [rsbuild build](/guide/basic/cli.md#rsbuild-build) or [rsbuild.build()](/api/javascript-api/instance.md#rsbuildbuild) * `preview`: will be set when running [rsbuild preview](/guide/basic/cli.md#rsbuild-preview) or [rsbuild.preview()](/api/javascript-api/instance.md#rsbuildpreview) For example: ```ts if (rsbuild.context.action === 'dev') { // do something } ``` ### context.bundlerType The bundler type of current build. * **Type:** ```ts type bundlerType = 'rspack' | 'webpack'; ``` > Rsbuild internally supports switching to webpack for comparative testing, so this field is provided for differentiation. Usually, you do not need to use this field. ## rsbuild.build Perform a production mode build. This method will generate optimized production bundles and emit them to the output directory. * **Type:** ```ts type BuildOptions = { /** * Whether to watch for file changes and rebuild. * @default false */ watch?: boolean; /** * Using a custom Rspack Compiler object. */ compiler?: Compiler | MultiCompiler; }; function Build(options?: BuildOptions): Promise<{ /** * Rspack's [stats](https://rspack.dev/api/javascript-api/stats) object. */ stats?: Rspack.Stats | Rspack.MultiStats; /** * Close the build and call the `onCloseBuild` hook. * In watch mode, this method will stop watching. */ close: () => Promise; }>; ``` * **Example:** ```ts import { logger } from '@rsbuild/core'; // Example 1: run build await rsbuild.build(); // Example 2: build and handle the error try { await rsbuild.build(); } catch (err) { logger.error('Failed to build.'); logger.error(err); process.exit(1); } // Example 3: build and get all assets const { stats } = await rsbuild.build(); if (stats) { const { assets } = stats.toJson({ // exclude unused fields to improve performance all: false, assets: true, }); console.log(assets); } ``` ### Monitor file changes To watch file changes and re-build, set the `watch` option to `true`. ```ts await rsbuild.build({ watch: true, }); ``` ### Close build `rsbuild.build()` returns a `close()` method, which can be used to stop the build. In watch mode, calling the `close()` method will stop watching: ```ts const buildResult = await rsbuild.build({ watch: true, }); await buildResult.close(); ``` In non-watch mode, you should also call the `close()` method to end the build, which will trigger the [onCloseBuild](/plugins/dev/hooks.md#onclosebuild) hook to perform cleanup operations. ```ts const buildResult = await rsbuild.build(); await buildResult.close(); ``` ### Stats object In non-watch mode, the `rsbuild.build()` returns an Rspack [stats](https://rspack.dev/api/javascript-api/stats) object. For example, use the `stats.toJson()` method to get all assets information: ```ts const result = await rsbuild.build(); const { stats } = result; if (stats) { const { assets } = stats.toJson({ // exclude unused fields to improve performance all: false, assets: true, }); console.log(assets); } ``` ### Custom compiler In some cases, you may want to use a custom compiler: ```ts import { rspack } from '@rsbuild/core'; const compiler = rspack({ // ... }); await rsbuild.build({ compiler, }); ``` ## rsbuild.startDevServer Start the local dev server. This method will: 1. Start a development server that serves your application. 2. Watch for file changes and trigger recompilation. * **Type:** ```ts type StartDevServerOptions = { /** * Using a custom Rspack Compiler object. */ compiler?: Compiler | MultiCompiler; /** * Whether to get port silently and not print any logs. * @default false */ getPortSilently?: boolean; }; type StartServerResult = { /** * The URLs that server is listening on. */ urls: string[]; /** * The actual port used by the server. */ port: number; server: { /** * Close the server. * In development mode, this will call the `onCloseDevServer` hook. */ close: () => Promise; }; }; function StartDevServer( options?: StartDevServerOptions, ): Promise; ``` * **Example:** Start dev server: ```ts import { logger } from '@rsbuild/core'; // Start dev server await rsbuild.startDevServer(); // Start dev server and handle the error try { await rsbuild.startDevServer(); } catch (err) { logger.error('Failed to start dev server.'); logger.error(err); process.exit(1); } ``` After successfully starting dev server, you can see the following logs: ``` ➜ Local: http://localhost:3000 ➜ Network: http://192.168.0.1:3000 ``` `startDevServer` returns the following parameters: * `urls`: URLs to access dev server. * `port`: The actual listening port number. * `server`: Server instance object. ```ts const { urls, port } = await rsbuild.startDevServer(); console.log(urls); // ['http://localhost:3000', 'http://192.168.0.1:3000'] console.log(port); // 3000 ``` ### Close server Calling the `close()` method will close the dev server and trigger the [onCloseDevServer](/plugins/dev/hooks.md#onclosedevserver) hook to perform cleanup operations. ```ts const { server } = await rsbuild.startDevServer(); await server.close(); ``` ### Get port silently In some cases, the default startup port number is already occupied. In this situation, Rsbuild will automatically increment the port number until it finds an available one. This process will output a prompt log. If you do not want this log, you can set `getPortSilently` to `true`. ```ts await rsbuild.startDevServer({ getPortSilently: true, }); ``` ### Custom compiler In some cases, you may want to use a custom compiler: ```ts import { rspack } from '@rsbuild/core'; const compiler = rspack({ // ... }); await rsbuild.startDevServer({ compiler, }); ``` ## rsbuild.createDevServer Rsbuild includes a built-in dev server designed to improve the development experience. When you run the `rsbuild dev` command, the server starts automatically and provides features such as page preview, routing, and hot module reloading. * To integrate the Rsbuild dev server into a custom server, you can use the `createDevServer` method to create a dev server instance. Please refer to [Dev server API](/api/javascript-api/dev-server-api.md) for all available APIs. * To use Rsbuild dev server to start the project directly, you can use the [rsbuild.startDevServer](#rsbuildstartdevserver) method directly. `rsbuild.startDevServer` is actually syntactic sugar for the following code: ```ts const server = await rsbuild.createDevServer(); await server.listen(); ``` ## rsbuild.preview Start a server to preview the production build locally. This method should be executed after [rsbuild.build](#rsbuildbuild). * **Type:** ```ts type PreviewOptions = { /** * Whether to get port silently * @default false */ getPortSilently?: boolean; /** * Whether to check if the dist directory exists and is not empty. * @default true */ checkDistDir?: boolean; }; type StartServerResult = { /** * The URLs that server is listening on. */ urls: string[]; /** * The actual port used by the server. */ port: number; server: { /** * Close the server. */ close: () => Promise; }; }; function preview(options?: PreviewOptions): Promise; ``` * **Example:** Start the server: ```ts import { logger } from '@rsbuild/core'; // Start preview server await rsbuild.preview(); // Start preview server and handle the error try { await rsbuild.preview(); } catch (err) { logger.error('Failed to start preview server.'); logger.error(err); process.exit(1); } ``` `preview` returns the following parameters: * `urls`: URLs to access server. * `port`: The actual listening port number. * `server`: Server instance object. ```ts const { urls, port } = await rsbuild.preview(); console.log(urls); // ['http://localhost:3000', 'http://192.168.0.1:3000'] console.log(port); // 3000 ``` ### Close server Calling the `close()` method will close the preview server. ```ts const { server } = await rsbuild.preview(); await server.close(); ``` ## rsbuild.createCompiler Create an Rspack [Compiler](https://rspack.dev/api/javascript-api/compiler) instance. If there are multiple [environments](/config/environments.md) for this build, the return value is [MultiCompiler](https://rspack.dev/api/javascript-api/compiler#multicompiler). * **Type:** ```ts function CreateCompiler(): Promise; ``` * **Example:** ```ts const compiler = await rsbuild.createCompiler(); ``` > You do not need to use this API unless you need to custom the dev server or other advanced scenarios. ## rsbuild.addPlugins Register one or more Rsbuild plugins, which can be called multiple times. This method needs to be called before compiling. If it is called after compiling, it will not affect the compilation result. * **Type:** ```ts type AddPluginsOptions = { before?: string; environment?: string }; function AddPlugins( plugins: Array, options?: AddPluginsOptions, ): void; ``` * **Example:** ```ts rsbuild.addPlugins([pluginFoo(), pluginBar()]); // Insert before the bar plugin rsbuild.addPlugins([pluginFoo()], { before: 'bar' }); // Add plugin for node environment rsbuild.addPlugins([pluginFoo()], { environment: 'node' }); ``` ## rsbuild.getPlugins Get all the Rsbuild plugins registered in the current Rsbuild instance. * **Type:** ```ts function GetPlugins(options?: { /** * Get the plugins in the specified environment. * If environment is not specified, get the global plugins. */ environment: string; }): RsbuildPlugin[]; ``` * **Example:** ```ts // get all plugins console.log(rsbuild.getPlugins()); // get plugins in `web` environment console.log(rsbuild.getPlugins({ environment: 'web' })); ``` ## rsbuild.removePlugins Removes one or more Rsbuild plugins, which can be called multiple times. This method needs to be called before compiling. If it is called after compiling, it will not affect the compilation result. * **Type:** ```ts function RemovePlugins(pluginNames: string[]): void; ``` * **Example:** ```ts // add plugin const pluginFoo = pluginFoo(); rsbuild.addPlugins(pluginFoo); // remove plugin rsbuild.removePlugins([pluginFoo.name]); ``` ## rsbuild.isPluginExists * **Example:** ```ts rsbuild.addPlugins([pluginFoo()]); rsbuild.isPluginExists(pluginFoo().name); // true ``` ## rsbuild.initConfigs Initialize and return the internal Rspack configurations used by Rsbuild. This method processes all plugins and configurations to generate the final Rspack configs. > Note: You typically don't need to call this method directly since it's automatically invoked by methods like [rsbuild.build](#rsbuildbuild) and [rsbuild.startDevServer](#rsbuildstartdevserver). * **Type:** ```ts function InitConfigs(): Promise<{ rspackConfigs: Rspack.Configuration[]; }>; ``` * **Example:** ```ts const rspackConfigs = await rsbuild.initConfigs(); console.log(rspackConfigs); ``` ## rsbuild.inspectConfig Inspect and debug Rsbuild's internal configurations. It provides access to: * The resolved Rsbuild configuration * The environment-specific Rsbuild configurations * The generated Rspack configurations The method serializes these configurations to strings and optionally writes them to disk for inspection. * **Type:** ```ts type InspectConfigOptions = { /** * Inspect the config in the specified mode. * Available options: 'development' or 'production'. * @default 'development' */ mode?: RsbuildMode; /** * Enables verbose mode to display the complete function * content in the configuration. * @default false */ verbose?: boolean; /** * Specify the output path for inspection results. * @default 'output.distPath.root' */ outputPath?: string; /** * Whether to write the inspection results to disk. * @default false */ writeToDisk?: boolean; }; async function InspectConfig(options?: InspectConfigOptions): Promise<{ rsbuildConfig: string; bundlerConfigs: string[]; environmentConfigs: string[]; origin: { rsbuildConfig: RsbuildConfig; environmentConfigs: Record; bundlerConfigs: BundlerConfigs[]; }; }>; ``` :::tip To view the Rsbuild and Rspack configurations during the build process, use [debug mode](/guide/debug/debug-mode.md), or obtain them through hooks such as [onBeforeBuild](#rsbuildonbeforebuild), [onBeforeCreateCompile](#rsbuildonbeforecreatecompiler). ::: ### Example Get the content of configs in string format: ```ts const { rsbuildConfig, bundlerConfigs } = await rsbuild.inspectConfig(); console.log(rsbuildConfig, bundlerConfigs); ``` Write the config content to disk: ```ts await rsbuild.inspectConfig({ writeToDisk: true, }); ``` ### Output path You can set the output path using `outputPath`. The default value is [output.distPath.root](/config/output/dist-path.md). If `outputPath` is a relative path, it will be concatenated relative to the value of `output.distPath.root`. You can also set `outputPath` to an absolute path, in which case the files will be written directly to that path. For example: ```ts import path from 'node:path'; await rsbuild.inspectConfig({ writeToDisk: true, outputPath: path.join(__dirname, 'custom-dir'), }); ``` ## rsbuild.onBeforeCreateCompiler * **Example:** ```ts rsbuild.onBeforeCreateCompiler(({ bundlerConfigs }) => { console.log('the Rspack config is ', bundlerConfigs); }); ``` ## rsbuild.onAfterCreateCompiler * **Example:** ```ts rsbuild.onAfterCreateCompiler(({ compiler }) => { console.log('the compiler is ', compiler); }); ``` ## rsbuild.onBeforeBuild * **Example:** ```ts rsbuild.onBeforeBuild(({ bundlerConfigs }) => { console.log('the Rspack config is ', bundlerConfigs); }); ``` ## rsbuild.onAfterBuild * **Example:** ```ts rsbuild.onAfterBuild(({ stats }) => { console.log(stats?.toJson()); }); ``` ## rsbuild.onCloseBuild * **Example:** ```ts rsbuild.onCloseBuild(async () => { console.log('close build!'); }); ``` ## rsbuild.onBeforeStartDevServer * **Example:** ```ts rsbuild.onBeforeStartDevServer(({ server, environments }) => { console.log('before starting dev server.'); console.log('the server is ', server); console.log('the environments contexts are: ', environments); }); ``` > See [Plugin hooks - onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver) for more details. ## rsbuild.onAfterStartDevServer * **Example:** ```ts rsbuild.onAfterStartDevServer(({ port, routes }) => { console.log('this port is: ', port); console.log('this routes is: ', routes); }); ``` ## rsbuild.onCloseDevServer * **Example:** ```ts rsbuild.onCloseDevServer(async () => { console.log('close dev server!'); }); ``` ## rsbuild.onBeforeStartProdServer * **Example:** ```ts rsbuild.onBeforeStartProdServer(() => { console.log('before start!'); }); ``` ## rsbuild.onAfterStartProdServer * **Example:** ```ts rsbuild.onAfterStartProdServer(({ port, routes }) => { console.log('this port is: ', port); console.log('this routes is: ', routes); }); ``` ## rsbuild.onDevCompileDone * **Example:** ```ts rsbuild.onDevCompileDone(({ isFirstCompile }) => { if (isFirstCompile) { console.log('first compile!'); } else { console.log('re-compile!'); } }); ``` ## rsbuild.onExit * **Example:** ```ts rsbuild.onExit(({ exitCode }) => { console.log('exit: ', exitCode); }); ``` ## rsbuild.getRsbuildConfig * **Example:** ```ts rsbuild.onBeforeBuild(() => { const config = rsbuild.getRsbuildConfig(); console.log(config.html?.title); }); ``` ## rsbuild.getNormalizedConfig * **Example:** ```ts rsbuild.onBeforeBuild(() => { const config = api.getNormalizedConfig(); console.log(config.html.title); }); ``` --- url: /api/javascript-api/types.md --- # Rsbuild types This section describes some of the type definitions provided by the Rsbuild. ## RsbuildInstance The type of Rsbuild instance, corresponding to the return value of the [createRsbuild](/api/javascript-api/core.md#creatersbuild) method. ```ts import type { RsbuildInstance } from '@rsbuild/core'; let rsbuild: RsbuildInstance; ``` ## RsbuildConfig The type of Rsbuild configuration. ```ts import type { RsbuildConfig } from '@rsbuild/core'; const config: RsbuildConfig = { // ... }; ``` You can also import the type definitions of each field in the Rsbuild config: ```ts import type { DevConfig, HtmlConfig, ToolsConfig, SourceConfig, ServerConfig, OutputConfig, SecurityConfig, PerformanceConfig, ModuleFederationConfig, } from '@rsbuild/core'; ``` ## NormalizedConfig The type of Rsbuild configuration after normalization, corresponding to the return value of the [getNormalizedConfig](/plugins/dev/core.md#apigetnormalizedconfig) method. ```ts import type { NormalizedConfig } from '@rsbuild/core'; const config: NormalizedConfig = api.getNormalizedConfig(); ``` You can also import the type definitions of each field in the normalized config: ```ts import type { NormalizedDevConfig, NormalizedHtmlConfig, NormalizedToolsConfig, NormalizedSourceConfig, NormalizedServerConfig, NormalizedOutputConfig, NormalizedSecurityConfig, NormalizedPerformanceConfig, NormalizedModuleFederationConfig, } from '@rsbuild/core'; ``` ## NormalizedEnvironmentConfig The type of Rsbuild environment configuration after normalization, corresponding to the return value of the [`getNormalizedConfig({ environment })`](/plugins/dev/core.md#apigetnormalizedconfig) method. ```ts import type { NormalizedEnvironmentConfig } from '@rsbuild/core'; const config: NormalizedEnvironmentConfig = api.getNormalizedConfig({ environment, }); ``` ## RsbuildContext The type of the [context property](/api/javascript-api/instance.md#rsbuildcontext) in the Rsbuild instance. ```ts import type { RsbuildContext } from '@rsbuild/core'; const context: RsbuildContext = rsbuild.context; ``` ## RsbuildPlugin The type of Rsbuild plugin. ```ts import type { RsbuildPlugin } from '@rsbuild/core'; const myPlugin: RsbuildPlugin = { name: 'my-plugin', setup() {}, }; ``` ## RsbuildPluginAPI The type of the `api` object passed into the `setup` function in the Rsbuild plugin. ```ts import type { RsbuildPluginAPI } from '@rsbuild/core'; const myPlugin = { name: 'my-plugin', setup(api: RsbuildPluginAPI) {}, }; ``` ## RsbuildTarget The type of build target. ```ts import type { RsbuildTarget } from '@rsbuild/core'; ``` ## CreateRsbuildOptions The param type of [createRsbuild](/api/javascript-api/core.md#creatersbuild) method. ```ts import type { CreateRsbuildOptions } from '@rsbuild/core'; ``` ## InspectConfigOptions The param type of [rsbuild.inspectConfig](/api/javascript-api/instance.md#rsbuildinspectconfig) method. ```ts import type { InspectConfigOptions } from '@rsbuild/core'; ``` ## Rspack Includes all types exported by `@rspack/core`, such as `Rspack.Configuration`. ```ts import type { Rspack } from '@rsbuild/core'; const rspackConfig: Rspack.Configuration = {}; ``` ## Others * OnExitFn * OnAfterBuildFn * OnAfterCreateCompilerFn * OnAfterStartDevServerFn * OnAfterStartProdServerFn * OnBeforeBuildFn * OnBeforeStartDevServerFn * OnBeforeStartProdServerFn * OnBeforeCreateCompilerFn * OnCloseDevServerFn * OnDevCompileDoneFn * ModifyRsbuildConfigFn * ModifyBundlerChainFn * ModifyRspackConfigFn * TransformFn, * TransformHandler * more... --- url: /api/javascript-api/dev-server-api.md --- # 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 * If you are a plugin author, you can access the dev server instance through the [onBeforeStartDevServer](/plugins/dev/hooks.md#onbeforestartdevserver) hook. ```ts 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](/api/javascript-api/instance.md#rsbuildcreatedevserver) method. ```ts const server = await rsbuild.createDevServer(); console.log('the server is ', server); ``` ## API interface ```ts type EnvironmentAPI = { [name: string]: { /** * Get stats info about current environment. */ getStats: () => Promise; /** * Load and execute stats bundle in server. * * @param entryName - relate to Rsbuild's `source.entry` * @returns the return value of entry module. */ loadBundle: (entryName: string) => Promise; /** * Get the compiled HTML template. */ getTransformedHtml: (entryName: string) => Promise; }; }; type RsbuildDevServer = { /** * The `connect` app instance. * Can be used to attach custom middlewares 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; }; }>; /** * 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; /** * Notify that the Rsbuild server has been started. * Rsbuild will trigger `onAfterStartDevServer` hook in this stage. */ afterListen: () => Promise; /** * Activate socket connection. * This ensures that HMR works properly. */ connectWebSocket: (options: { server: HTTPServer }) => void; /** * Close the Rsbuild server. */ close: () => Promise; /** * Print the server URLs. */ printUrls: () => void; /** * Open URL in the browser after starting the server. */ open: () => Promise; }; 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; ``` ## Example ### Integrate with custom server Here is an example of integrating [express](https://expressjs.com/) with Rsbuild dev server: ```ts 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 middlewares app.use(rsbuildServer.middlewares); const server = app.listen(rsbuildServer.port, async () => { // Notify Rsbuild that the custom server has started await rsbuildServer.afterListen(); }); rsbuildServer.connectWebSocket({ server }); } ``` For detailed usage, please refer to: * [Example code](https://github.com/rspack-contrib/rstack-examples/blob/main/rsbuild/express/server.mjs). * [rsbuild.createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver) * [server.middlewareMode](/config/server/middleware-mode.md) ### connectWebSocket Rsbuild has a builtin WebSocket handler to support HMR: 1. When a user accesses a page through browser, a WebSocket connection request is automatically initiated to the server. 2. After the Rsbuild dev server detects the connection request, it instructs the builtin WebSocket handler to process it. 3. After the browser successfully establishes a connection with the Rsbuild WebSocket handler, real-time communication is possible. 4. 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. ```ts const rsbuildServer = await rsbuild.createDevServer(); const httpServer = app.listen(rsbuildServer.port); rsbuildServer.connectWebSocket({ server: httpServer }); ``` --- url: /api/javascript-api/environment-api.md --- # Environment API Here you can find all the environment related APIs. > See [Multi-environment builds](/guide/advanced/environments.md) for more details. ## Environment context Environment context is a read-only object that provides some context information about the current environment. In Rsbuild's [Plugin hooks](/plugins/dev/hooks.md#plugin-hooks), you can get the environment context object through the `environment` or `environments` parameter. ```ts type EnvironmentContext = { name: string; browserslist: string[]; config: NormalizedEnvironmentConfig; distPath: string; entry: RsbuildEntry; htmlPaths: Record; tsconfigPath?: string; }; ``` ### name The unique name of the current environment is used to distinguish and locate the environment, corresponds to the key in the [environments](/config/environments.md) configuration. * **Type:** `string` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { if (environment.name === 'node') { // modify config for node environment } return config; }); ``` ### browserslist The browserslist configuration of the current environment. See [Browserslist](/guide/advanced/browserslist.md) for more details. * **Type:** `string[]` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { console.log(environment.browserslist); return config; }); ``` ### config The normalized Rsbuild config for the current environment. * **Type:** ```ts type NormalizedEnvironmentConfig = DeepReadonly<{ dev: NormalizedDevConfig; html: NormalizedHtmlConfig; tools: NormalizedToolsConfig; source: NormalizedSourceConfig; server: NormalizedServerConfig; output: NormalizedOutputConfig; plugins?: RsbuildPlugins; security: NormalizedSecurityConfig; performance: NormalizedPerformanceConfig; moduleFederation?: ModuleFederationConfig; }>; ``` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { // Rspack config console.log(config); // Rsbuild config for current environment console.log(environment.config); return config; }); ``` ### distPath The absolute path of the output directory, corresponding to the [output.distPath.root](/config/output/dist-path.md) config of Rsbuild. * **Type:** `string` ```js api.modifyRspackConfig((config, { environment }) => { console.log(environment.distPath); return config; }); ``` ### entry The entry object from the [source.entry](/config/source/entry.md) option. * **Type:** ```ts type RsbuildEntry = Record; ``` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { console.log(environment.entry); return config; }); ``` ### htmlPaths The path information for all HTML assets. This value is an object, the key is the entry name and the value is the relative path of the HTML file in the dist directory. * **Type:** ```ts type htmlPaths = Record; ``` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { console.log(environment.htmlPaths); return config; }); ``` ### tsconfigPath The absolute path of the tsconfig.json file, or `undefined` if the tsconfig.json file does not exist in current project. * **Type:** ```ts type TsconfigPath = string | undefined; ``` * **Example:** ```js api.modifyRspackConfig((config, { environment }) => { console.log(environment.tsconfigPath); return config; }); ``` ## Environment API Environment API provides some APIs related to the multi-environment build. You can use environment API via [rsbuild.createDevServer()](/api/javascript-api/instance.md#rsbuildcreatedevserver) or [dev.setupMiddlewares](/config/dev/setup-middlewares.md), which allows you to get the build outputs information for a specific environment in the server side. ```ts type EnvironmentAPI = { [name: string]: { getStats: () => Promise; loadBundle: (entryName: string) => Promise; getTransformedHtml: (entryName: string) => Promise; }; }; ``` ### getStats Get the build stats of current environment. * **Type:** ```ts type GetStats = () => Promise; ``` * **Example:** ```ts const webStats = await environments.web.getStats(); console.log(webStats.toJson({ all: false })); ``` ### loadBundle Load and execute the bundles on the server side. This method returns the exports of the entry module. * **Type:** ```ts /** * @param entryName - Entry name, corresponding to a key in Rsbuild `source.entry` * @returns The return value of the entry module */ type LoadBundle = (entryName: string) => Promise; ``` * **Example:** ```ts // Load the bundle of `main` entry const result = await environments.node.loadBundle('main'); ``` ### getTransformedHtml Get the HTML template content after compilation and transformation. * **Type:** ```ts type GetTransformedHtml = (entryName: string) => Promise; ``` * **Example:** ```ts // Get the HTML content of main entry const html = await environments.web.getTransformedHtml('main'); ``` This method returns the complete HTML string, including all resources and content injected through HTML plugins. --- url: /community/index.md --- # Community ## Version Rsbuild follows the Semantic Versioning specification. For more details, see [Releases](/community/releases/index.md). ## Team The development of Rsbuild is driven by ByteDance's Rspack team and community contributors. For information about the team members, please refer to [Rspack - Core team](https://rspack.dev/misc/team/core-team). ## Communication You can communicate with the developers of Rsbuild through the following channels: * [GitHub Discussions](https://github.com/web-infra-dev/rsbuild/discussions) * [Discord](https://discord.com/invite/XsaKEEk4mW) * [Twitter](https://twitter.com/rspack_dev) * [Bluesky](https://bsky.app/profile/rspack.dev) ## Resources Please check out [awesome-rspack](https://github.com/web-infra-dev/awesome-rspack) to discover more community resources related to Rspack and Rsbuild. ## Contribution Contributions to Rsbuild are welcomed! Please refer to the [Rsbuild Contribution Guide](https://github.com/web-infra-dev/rsbuild/blob/main/CONTRIBUTING.md). ## Blogs Please visit [Rspack - Blog](https://rspack.dev/blog/index) to read our latest articles and announcements. ## Examples Please visit [rspack-contrib/rstack-examples](https://github.com/rspack-contrib/rstack-examples) to view or contribute to the example projects of Rsbuild. --- url: /community/releases/index.md --- # Overview ## Changelog Please visit [GitHub - release](https://github.com/web-infra-dev/rsbuild/releases) to view the changes for each version of Rsbuild. ## Semantic version Rsbuild follows the [Semantic Versioning](https://semver.org/) specification. * Major version: contains incompatible API changes. * Minor version: contains backward compatible features and fixes. * Patch version: contains backwards compatible bug fixes. ## Release cycle * Rsbuild will release several patch versions every week. --- url: /community/releases/v1-0.md --- *September 10, 2024* # Announcing Rsbuild 1.0 ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-1-0-banner.png) We are pleased to announce the release of Rsbuild 1.0! ## Why Rsbuild For a long time, developers using webpack have been bothered by two major issues: **slow build times and configuration complexity**. We have used Rust to rewrite webpack into [Rspack](https://github.com/web-infra-dev/rspack), which addresses the slow build issue. However, to maintain compatibility with the webpack ecosystem, Rspack retains webpack's configuration and API, which means it still has some complexity and a learning curve. ### Evolution of the ecosystem In the early days, there were some excellent tools within the webpack ecosystem, such as Create React App (CRA) and Vue CLI. These tools provided best practices for building React or Vue applications, while hiding the complex webpack configuration. As a result, many React and Vue users used these tools to build applications without having to configure webpack from scratch. As the ecosystem evolved, full-stack web frameworks such as Next.js, Nuxt, and Remix became popular; Vite was introduced as a lightweight build tool and also gained popularity. However, CRA and Vue CLI gradually stopped being maintained. When we look at the npm download numbers for webpack, CRA, and Vue CLI, we find that a large number of projects are still using these tools. For example, webpack has about 25 million weekly downloads, and CRA has nearly 3 million weekly downloads. Many of these projects are CSR applications that do not require the SSR features of full-stack frameworks. Vite seems like a good choice, but after using Vite in our ByteDance projects, we found that migrating from webpack to Vite comes with high costs and introduces new problems, such as dev and build inconsistency, and slow page refreshes in large applications during development. For the webpack ecosystem, we discovered a sad fact: **the webpack ecosystem lacks a build tool that is easy to use and well maintained**. The tool should be as user-friendly as CRA and Vue CLI, fully meet the needs of CSR application development, and have features such as fast startup and plugin support similar to Vite. ### The birth of Rsbuild During the development of Rspack, we became aware of the above problems and decided to create a modern build tool based on Rspack called **Rsbuild**. ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-1-0-build-tools.png) Rsbuild is built on top of Rspack. We designed Rsbuild with an easy-to-use, TypeScript-friendly API and a set of carefully designed configurations to fully leverage the Rspack's build performance while reducing configuration complexity and high up-front costs. When developing Rsbuild, we learned best practices from the best tools in the community and focused on two usage scenarios: * As a lightweight build tool: Helps developers quickly setup web applications with out-of-the-box support for CSR applications. * As a shared infrastructure: Provides [JavaScript API](https://rsbuild.dev/api/start/) and [Plugin API](https://rsbuild.dev/plugins/dev/) for higher-level tools and frameworks, allowing developers to easily build their tools or frameworks on top of Rsbuild. ## Performance **Rsbuild is currently the fastest build tool in the webpack and Rspack ecosystem**. Here is a comparison between Rsbuild, Create React App, Vite, and Rspack CLI: | Metric | Create React App | Vite (with SWC) | Rspack CLI | Rsbuild | Rsbuild vs CRA | | ------------------------------- | ---------------- | --------------- | ---------- | ------- | ----------------- | | dev startup time (1000 modules) | 5.47s | 1.29s | 0.66s | 0.39s | **14x faster** | | build time (1000 modules) | 5.69s | 1.39s | 0.51s | 0.27s | **20x faster** | | npm dependencies count | 1241 | 15 | 283 | 14 | **99% reduction** | | npm install size | 146.6MB | 56.3MB | 75.1MB | 59.1MB | **60% reduction** | Compared to the [Rspack CLI](https://npmjs.com/package/@rspack/cli), Rsbuild provides a richer set of features while demonstrating superior performance. This is because Rspack CLI needs to maintain compatibility with the [webpack-cli](https://npmjs.com/package/webpack-cli). It relies on the `webpack-dev-server` and provides the same default behavior as webpack, which has some performance limitations. Rsbuild, on the other hand, is designed for modern web development. We have reimplemented a lighter CLI, dev server, and build process for Rsbuild, resulting in faster startup speeds and fewer npm dependencies. > See the [Rsbuild Introduction](https://rsbuild.dev/guide/start/index) for more comparisons between Rsbuild, webpack, Vue CLI, and Vite. ## Who is using In the [Rspack 1.0 Announcement](https://rspack.dev/blog/announcing-1-0), we introduced that Rspack is growing rapidly, with almost half of Rspack users using Rsbuild and giving us lots of positive feedback. At ByteDance, we use Rsbuild as the cornerstone of our internal web frameworks to support thousands of web projects. These projects cover diverse use cases, including desktop web applications, mobile web applications, cross-platform web applications, documentation sites, and more. For the community, we have open-sourced a high-performance toolchain based on Rsbuild, including the static site generator [Rspress](https://github.com/web-infra-dev/rspress), the library development tool [Rslib](https://github.com/web-infra-dev/rslib), the full-stack React framework [Modern.js](https://github.com/web-infra-dev/modern.js), and the [Storybook Rsbuild](https://github.com/rspack-contrib/storybook-rsbuild). The extensibility of Rsbuild allows these tools to flexibly integrate with Rsbuild and share its plugin ecosystem. After releasing Rsbuild 1.0, we also plan to collaborate with some excellent teams like [Remix](https://github.com/remix-run/remix), to bring Rsbuild to more web frameworks. ## Plugin ecosystem The Rsbuild plugin ecosystem is constantly evolving. There are currently over 50 [Rsbuild plugins](https://github.com/web-infra-dev/awesome-rspack?tab=readme-ov-file#rsbuild-plugins) available in the community. We provide several advanced features through plugins to support the development of production-grade applications, such as [type checking](https://github.com/rspack-contrib/rsbuild-plugin-type-check), [compatibility checking](https://github.com/rspack-contrib/rsbuild-plugin-check-syntax), and [static assets retry](https://github.com/rspack-contrib/rsbuild-plugin-assets-retry). Thanks to Rspack's compatibility with webpack, Rsbuild also supports most webpack plugins. Compared to webpack or Rspack, the Rsbuild plugin API is more straightforward and beginner-friendly, allowing developers to easily create plugins to meet their specific needs. For example, let's implement a plugin that outputs a file to the dist directory. The implementation comparison between Rspack and Rsbuild is as follows: ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-1-0-plugin-compare.png) As shown, the API style of the Rsbuild plugin is similar to esbuild, it can be defined by a function. The plugin hooks have been simplified to avoid verbose APIs, making plugin development more intuitive. ## How to use 1.0 * If you haven't used Rsbuild before, you can experience it through the [CodeSandbox example](https://codesandbox.io/p/github/rspack-contrib/rsbuild-codesandbox-example) or refer to the [Quick start](https://rsbuild.dev/guide/start/quick-start) to use Rsbuild. * If you are using Rsbuild 0.7 or earlier, please note that 1.0 includes some breaking changes. You can refer to the [Migrating from 0.x](https://rsbuild.dev/guide/migration/rsbuild-0-x) document to upgrade. * Rsbuild also provides migration guides for projects that use webpack, CRA, Vue CLI, etc. See [Migrate from Existing Projects](https://rsbuild.dev/guide/start/quick-start#migrate-from-existing-projects). > Give a star 🌟 to the [Rsbuild GitHub repository](https://github.com/web-infra-dev/rsbuild). ## What's next Rsbuild 1.0 provides several advanced features for the development of enterprise applications and higher-level tools, such as the [multi-environment build API](https://rsbuild.dev/guide/advanced/environments), [SSR API](https://rsbuild.dev/guide/advanced/ssr), [plugin API](https://rsbuild.dev/plugins/dev/), [Module Federation support](https://rsbuild.dev/guide/advanced/module-federation), and [library build (Rslib)](https://github.com/web-infra-dev/rslib). We plan to continue to enhance these features to better support the development of the Rsbuild ecosystem. In the next 12 to 18 months, Rsbuild will evolve together with Rspack, adopting Rspack's new features as soon as they become available. These features include persistent caching, faster HMR, and TypeScript-based optimizations. For more details, see [Rspack - What's next](https://rspack.dev/blog/announcing-1-0#whats-next). Finally, a big thank you to all the developers who have contributed to Rsbuild ❤️: ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-1-0-contributors.png) --- url: /community/releases/v0-7.md --- *May 28, 2024* # Announcing Rsbuild 0.7 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-7.png) Rsbuild 0.7 has been released with Rspack 0.7! This is the last minor release before the Rsbuild 1.0. After this, the Rspack team will focus on the development of 1.0 and aim to launch the Rspack / Rsbuild 1.0 alpha version soon. Notable changes in Rsbuild 0.7: * [Support for Storybook](#support-for-storybook) * [Faster Sass Compilation](#faster-sass-compilation) * [Better CSS supports](#better-css-supports) * [Typed CSS Modules](#typed-css-modules) * [ESM/CJS Exports](#esmcjs-exports) * [Breaking Changes](#breaking-changes) ## Support for Storybook Rsbuild now supports Storybook! [storybook-builder-rsbuild](https://github.com/rspack-contrib/storybook-rsbuild) is a Storybook builder based on Storybook v8 and Rsbuild that allows you to quickly build your components and stories. ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-with-storybook.png) * For projects using Rsbuild, you can now quickly integrate Storybook and reuse your existing Rsbuild config. * For projects using the Storybook webpack builder, you can now upgrade to Rsbuild and **get ~5x faster build performance**. We also provide `storybook-react-rsbuild` and `storybook-vue3-rsbuild` to support React and Vue 3. For example, to integrate React: ```js title=".storybook/main.js" import { StorybookConfig } from 'storybook-react-rsbuild'; const config: StorybookConfig = { framework: 'storybook-react-rsbuild', }; export default config; ``` ![](https://assets.rspack.dev/rsbuild/assets/storybook-rsbuild-preview.png) > For more usage, please refer to [storybook-rsbuild repository](https://github.com/rspack-contrib/storybook-rsbuild). ## Faster Sass compilation In Rsbuild 0.7, **Sass compilation is 3~10 times faster**. The performance improvements are particularly noticeable on large projects. Comparison of build times for Rsbuild 0.6 and 0.7 when compiling Bootstrap's Sass code: ![](https://assets.rspack.dev/rsbuild/assets/sass-embedded-compare.jpeg) This improvement is due to Rsbuild's default use of [sass-embedded](https://npmjs.com/package/sass-embedded), a JavaScript wrapper around the native Dart Sass executable that provides a consistent API and superior performance. Rsbuild has also enabled the latest sass-loader's [modern-compiler](https://github.com/webpack-contrib/sass-loader/releases/tag/v14.2.0) API. This can enable Sass's shared resources feature, which allows the same compiler process to be reused when compiling multiple files, improving build performance. ## Better CSS supports Rsbuild now uses [CssExtractRspackPlugin](https://rspack.dev/plugins/rspack/css-extract-rspack-plugin) to extract CSS into separate files, rather than using the [experimental.css](https://rspack.dev/config/experiments#experimentscss) config to do so. This allows Rsbuild to support more CSS features, including: * Support for using ` ``` * Support for complex CSS Modules `:global()` syntax ```css title="style.module.css" :local(.parent):global(.child) > ul { color: red; } ``` * Support for more CSS Modules options, such as [cssModules.exportGlobals](/config/output/css-modules.md#cssmodulesexportglobals) * Now you can use [tools.cssExtract](/config/tools/css-extract.md) to configure CssExtractRspackPlugin. ## Typed CSS Modules Rsbuild 0.7 added a new [Typed CSS Modules plugin](https://github.com/rspack-contrib/rsbuild-plugin-typed-css-modules), which is used to generate type declaration files for CSS Modules in the project. When you use CSS Modules in a TypeScript project, the default type definition is as follows. It can only provide basic type support, and cannot accurately prompt which class names are exported by CSS Modules. ```ts title="src/env.d.ts" declare module '*.module.css' { const classes: { readonly [key: string]: string }; export default classes; } ``` After using the Typed CSS Modules plugin, Rsbuild will generate type declaration files for all CSS Modules in the project, providing accurate type hints. For example, create two files named `src/index.ts` and `src/index.module.css`: ```tsx title="src/index.ts" import styles from './index.module.css'; console.log(styles.pageHeader); ``` ```css title="index.module.css" .page-header { color: black; } ``` After building, Rsbuild will generate a `src/index.module.css.d.ts` type declaration file: ```ts title="src/index.module.css.d.ts" interface CssExports { 'page-header': string; pageHeader: string; } declare const cssExports: CssExports; export default cssExports; ``` Now when you open the `src/index.ts` file, you can see that the `styles` object already has an accurate type. ## ESM/CJS Exports Now, all packages of Rsbuild provide exports in both ES modules and CommonJS formats, and ["type"="module"](https://nodejs.org/api/packages.html#type) has been declared in the package.json. ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-dual-package-example.png) This allows you to use `import` or `require` to use the JavaScript API of Rsbuild: ```js // ES module import { createRsbuild } from '@rsbuild/core'; // CommonJS const { createRsbuild } = require('@rsbuild/core'); ``` ESM/CJS interop is a tricky issue, so we will provide both formats for a long time to make it easier for more users to use. ## Breaking changes ### Upgrade Rspack to 0.7 Rsbuild has upgraded the dependent Rspack to version 0.7 and adapted to the breaking changes included in it. Typically, these breaking changes will not affect you. In the new version, Rspack supports lazy compilation, which can significantly improve the dev startup time for large projects. Please refer to [Announcing Rspack 0.7](https://rspack.dev/blog/announcing-0-7) to learn more. In Rsbuild, you can use [dev.lazyCompilation](/config/dev/lazy-compilation.md) to enable lazy compilation. ### Sass and Less plugins Rsbuild's Sass and Less plugins are now two separate npm packages instead of being built into `@rsbuild/core` as before. This change allows users to enable Sass and Less compilation as needed. For example, projects using CSS solutions such as Tailwind CSS, CSS-in-JS, etc., no longer need to install the dependencies required for Sass and Less, **saving about 7MB of disk space**. * If your project requires compiling `.scss` or `.sass` files, please install and register the [@rsbuild/plugin-sass](/plugins/list/plugin-sass.md) plugin: ```ts title="rsbuild.config.ts" import { pluginSass } from '@rsbuild/plugin-sass'; export default { plugins: [pluginSass()], }; ``` * If your project requires compiling `.less` files, please install and register the [@rsbuild/plugin-less](/plugins/list/plugin-less.md) plugin: ```ts title="rsbuild.config.ts" import { pluginLess } from '@rsbuild/plugin-less'; export default { plugins: [pluginLess()], }; ``` ### dataUriLimit defaults The default value for [output.dataUriLimit](/config/output/data-uri-limit.md) has been changed from `10000 (10kB)` to `4096 (4KiB)`. This is because more applications are currently using HTTP 2.0, so splitting assets into separate files would perform better. Meanwhile, inlining assets over 4KiB can make the JS bundle to be too large and not cache friendly. If you prefer the previous defaults, add the following config: ```ts title="rsbuild.config.ts" export default { output: { dataUriLimit: 10000, }, }; ``` --- url: /community/releases/v0-6.md --- *April 10, 2024* # Announcing Rsbuild 0.6 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-6.png) Rsbuild 0.6 has been released along with Rspack 0.6! Notable changes: * Upgrade to Rspack 0.6 * Error overlay enabled by default * Support for Vue JSX HMR * New transform plugin API * Default port changed to 3000 ## Upgrade to Rspack 0.6 Rsbuild has upgraded the dependent Rspack to version 0.6, and adapted the breaking changes of CSS Modules contained in Rspack 0.6. In the new version, Rspack has enabled the new tree shaking algorithm by default, resulting in a significant improvement in bundle size and artifact stability. Please refer to the [Rspack 0.6 release announcement](https://rspack.dev/blog/announcing-0-6) to learn more. ## Error overlay enabled by default Starting from Rsbuild 0.6, the default value of [dev.client.overlay](/config/dev/client.md) has been adjusted to `true`. This means that when a compilation error occurs, Rsbuild will pop up the error overlay by default to display the error information: ![](https://assets.rspack.dev/rsbuild/assets/rsbuild-error-overlay.png) If you do not need this feature, you can set `dev.client.overlay` to `false` to disable it. ```ts title="rsbuild.config.ts" export default defineConfig({ dev: { client: { overlay: false, }, }, }); ``` ## Support for Vue JSX HMR `@rsbuild/plugin-vue-jsx` now supports JSX HMR. When you modify JSX code in a Vue 3 application, it will automatically trigger hot module replacement and preserve the current page state. This feature is implemented by community contributor [@liyincode](https://github.com/liyincode) ❤️, and released as a standalone package [babel-plugin-vue-jsx-hmr](https://github.com/liyincode/babel-plugin-vue-jsx-hmr), for use in projects outside of Rsbuild. ## New transform API Rsbuild plugin now supports the [transform API](/plugins/dev/core.md#apitransform), which can be thought of as a lightweight implementation of Rspack loader. It provides a simple and easy to use API and automatically calls Rspack loader at the backend to transform the code. In Rsbuild plugins, you can quickly implement code transformation functions using `api.transform`, which can handle the majority of common scenarios without having to learn how to write an Rspack loader. For example, match modules with the `.pug` extension and transform them to JavaScript code: ```ts import pug from 'pug'; const pluginPug = () => ({ name: 'my-pug-plugin', setup(api) { api.transform({ test: /\.pug$/ }, ({ code }) => { const templateCode = pug.compileClient(code, {}); return `${templateCode}; module.exports = template;`; }); }, }); ``` For some complex code transformation scenarios, `api.transform` may not be sufficient. In such situations, you can implement it using the Rspack loader. ## Default port changed to 3000 Rsbuild has changed the default value of [server.port](/config/server/port.md) from `8080` to `3000`. Port 3000 is commonly used for web development, and is also the default port used by tools such as create-react-app. Changing the default port to 3000 can prevent possible port conflicts when using 8080. To use port 8080, set it manually as follows: ```ts title="rsbuild.config.ts" export default defineConfig({ server: { port: 8080, }, }); ``` --- url: /community/releases/v0-5.md --- *March 19, 2024* # Announcing Rsbuild 0.5 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-5.png) Rsbuild 0.5 is an important milestone. As of this release, most of the Rsbuild API has reached a stable state and we expect to release Rsbuild 1.0 in Q3 2024. Main changes: * ⚡️ Support for [Lightning CSS](https://lightningcss.dev/) to speed up CSS compilation. * 🌟 Support for custom server based on the new JavaScript API. * 🍭 Refactor the SVGR plugin to support more usages. * 📍 Support for custom minify options. ## ⚡️ Supports Lightning CSS Lightning CSS is a high performance CSS parser, transformer and minifier written in Rust. It supports parsing and transforming many modern CSS features into syntax supported by target browsers, and also provides a better compression ratio. Rsbuild provides the Lightning CSS plugin to use Lightning CSS on an opt-in basis, replacing the built-in PostCSS, autoprefixer, and SWC CSS minimizer in Rsbuild. All you need to do is register the Lightning CSS plugin in the Rsbuild configuration to complete the switch: ```ts title="rsbuild.config.ts" import { pluginLightningcss } from '@rsbuild/plugin-lightningcss'; export default { plugins: [pluginLightningcss()], }; ``` In a real large-scale web application, we have integrated the Rsbuild Lightning CSS plugin and used [Rsdoctor](https://rsdoctor.dev/) to analyze the changes in build time: * CSS compilation time was reduced from 8.4s to 0.12s, a 70x improvement. * The overall build time was reduced from 33.1s to 25.4s, a 30% increase. ## 🌟 Support for custom server Rsbuild now supports replacing the dev server with a custom server that reuses Rsbuild's page preview, routing, and module hot update features. This makes it easier to integrate Rsbuild with other Node.js frameworks. For example, you can implement a custom server based on express: ```ts import express from 'express'; import { createRsbuild } from '@rsbuild/core'; async function startCustomServer() { const app = express(); const rsbuild = await createRsbuild({ rsbuildConfig: { server: { middlewareMode: true, }, }, }); const { port, middlewares } = await rsbuild.createDevServer(); app.use(middlewares); app.listen(port); } ``` For more details, please refer to [Rsbuild - createDevServer](/api/javascript-api/instance.md#rsbuildcreatedevserver). ## 🍭 Refactoring SVGR plugin In versions prior to 0.5.0, the default usage of the SVGR plugin was the same as create-react-app, allowing SVGs to be used via mixed import: ```js import logoUrl, { ReactComponent as Logo } from './logo.svg'; console.log(logoUrl); // -> string console.log(Logo); // -> React component ``` However, there are two problems with this approach: 1. **Increased bundle size**: Mixed import causes a single SVG module to be compiled into two types of code (even if some exports are not used), which will increase the bundle size. 2. **Slow down compiling**: Mixed import will cause extra compilation overhead. Even if the ReactComponent export is not used in the code, the SVG file will still be compiled by SVGR. And SVGR is based on Babel, which has a high performance overhead. So we have refactored the `@rsbuild/plugin-svgr` plugin to support converting SVGs to React components via the `?react` query. This approach can solve the problems mentioned above, and is more in line with community best practices. ```jsx import logoUrl from './logo.svg'; import Logo from './logo.svg?react'; console.log(logoUrl); // -> string console.log(Logo); // -> React component ``` The SVGR plugin now supports switching between different SVGR usages. If a project needs to use the previous mixed import usage, you can manually enable the [mixedImport](/plugins/list/plugin-svgr.md#mixedimport) option: ```js pluginSvgr({ mixedImport: true, }); ``` ## 📍 Custom minify options The `output.disableMinimize` option has been renamed to [output.minify](/config/output/minify.md), and it allows customizing JS and HTML minification options. ```ts title="rsbuild.config.ts" export default { output: { minify: { jsOptions: { minimizerOptions: { mangle: false, }, }, }, }, }; ``` Projects using `output.disableMinimize` can refer to the example below: ```ts export default { output: { disableMinimize: true, // [!code --] minify: false, // [!code ++] }, }; ``` > See ["allow customize minify options"](https://github.com/web-infra-dev/rsbuild/issues/1681). *** For more information, please refer to: * [Rsbuild 0.5.0 Changelog](https://github.com/web-infra-dev/rsbuild/releases/tag/v0.5.0) * [Rsbuild 0.5.0 Breaking Changes](https://github.com/web-infra-dev/rsbuild/discussions/1732) --- url: /community/releases/v0-4.md --- *February 06, 2024* # Announcing Rsbuild 0.4 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-4.png) Rsbuild 0.4 provides built-in support for module federation. It also contains some incompatible API updates. Please refer to the current document for upgrading. ### Module Federation config Rsbuild now provides a builtin [moduleFederation](/config/module-federation/options.md) option, which will make configuring Module Federation in Rsbuild much easier. * **Example:** ```ts title="rsbuild.config.ts" export default defineConfig({ moduleFederation: { options: { // ModuleFederationPluginOptions }, }, }); ``` When you use this option, Rsbuild will automatically set the default `publicPath` and `splitChunks` config, making module federation ready to use out of the box. > See [RFC - Provide first-class support for Module Federation](https://github.com/web-infra-dev/rsbuild/discussions/1461) for details. ### Plugin hook order In Rsbuild plugin, you can now declare the order of hooks using the `order` field: ```ts const myPlugin = () => ({ setup(api) { api.modifyRsbuildConfig({ handler: () => console.log('hello'), order: 'pre', }); }, }); ``` > For more details, see [Plugin Hooks](/plugins/dev/hooks.md). ### Rename disableFilenameHash The `output.disableFilenameHash` config has been renamed to [output.filenameHash](/config/output/filename-hash.md). * Before: ```ts export default { output: { disableFilenameHash: true, }, }; ``` * After: ```ts export default { output: { filenameHash: false, }, }; ``` ## Remove postcss-flexbugs-fixes Rsbuild 0.4 removed the builtin [postcss-flexbugs-fixes](https://github.com/luisrudge/postcss-flexbugs-fixes) plugin. This plugin is used to fix some flex bugs for IE 10 / 11. Considering that modern browsers no longer have these flex issues, we removed this plugin to improve build performance. If your project needs to be compatible with IE 10 / 11 and encounters these flex issues, you can manually add this plugin in Rsbuild: * Install plugin: ```bash npm add postcss-flexbugs-fixes -D ``` * Register plugin in `postcss.config.cjs`: ```js module.exports = { 'postcss-flexbugs-fixes': {}, }; ``` ## Pure React plugin The React plugin has removed default [source.transformImport](/config/source/transform-import.md) config for [antd](https://npmjs.com/package/antd) v4 and [@arco-design/web-react](https://npmjs.com/package/@arco-design/web-react). Configurations related to the UI library should be provided in the UI library-specific plugins, such as `rsbuild-plugin-antd` or `rsbuild-plugin-arco`, and the React plugin will concentrate on providing fundamental abilities for React. * If your project is using `antd` v3 or v4, you can manually add the following config: ```ts title="rsbuild.config.ts" export default { source: { transformImport: [ { libraryName: 'antd', libraryDirectory: 'es', style: 'css', }, ], }, }; ``` * If your project is using `@arco-design/web-react`, you can manually add the following config: ```ts title="rsbuild.config.ts" export default { source: { transformImport: [ { libraryName: '@arco-design/web-react', libraryDirectory: 'es', camelToDashComponentName: false, style: 'css', }, { libraryName: '@arco-design/web-react/icon', libraryDirectory: 'react-icon', camelToDashComponentName: false, }, ], }, }; ``` ## JavaScript API The `loadConfig` method now returns both the contents of the config and the path to the config file: ```js import { loadConfig } from '@rsbuild/core'; // 0.3 const config = await loadConfig(); // 0.4 const { content, filePath } = await loadConfig(); ``` --- url: /community/releases/v0-3.md --- *January 10, 2024* # Announcing Rsbuild 0.3 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-3.png) Rsbuild 0.3 version has upgraded Rspack to 0.5 and now supports Module Federation. In addition, it includes some incompatible API changes. Please refer to the current documentation for upgrading. ## Rspack 0.5 Bump Rspack to v0.5.0, see: [Rspack 0.5 Release Announcement](https://rspack.dev/blog/announcing-0-5) Notable changes: * [Module Federation added to Rspack](https://rspack.dev/blog/module-federation-added-to-rspack) * [Remove deprecated builtins options](https://rspack.dev/blog/announcing-0-5#make-swchelpers-and-react-refresh-as-peerdependencies) ## TOML / YAML plugin The need to import TOML and YAML in JS is not common, so Rsbuild core will no longer support import TOML and YAML by default in v0.3.0. The TOML and YAML plugin will become a independent plugin: * TOML: ```ts // rsbuild.config.ts import { pluginToml } from '@rsbuild/plugin-toml'; export default { plugins: [pluginToml()], }; ``` * YAML: ```ts // rsbuild.config.ts import { pluginYaml } from '@rsbuild/plugin-yaml'; export default { plugins: [pluginYaml()], }; ``` ## JavaScript API Some JavaScript APIs have changed: * The `printURLs` option of `rsbuild.startDevServer` is deprecated, use [server.printUrls](/config/server/print-urls.md) instead. * The `logger` option of `rsbuild.startDevServer` is deprecated, use [logger.override()](/api/javascript-api/core.md#logger) instead. ## Node target * Adjust default browserslist for node target, from `node >= 14` to `node >= 16`. * The default value of `output.distPath.server` is changed from `'bundles'` to `'server'` --- url: /community/releases/v0-2.md --- *December 11, 2023* # Announcing Rsbuild 0.2 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-2.png) The Rsbuild 0.2 contains some incompatible API changes. Please refer to the current documentation for upgrading. ## Targets We will move the `target` option of `createRsbuild` to rsbuild config, this change allows user to configure `targets` in the rsbuild config file. * before: ```js const rsbuild = await createRsbuild({ target: ['web', 'node'], }); ``` * after: ```js // rsbuild.config.ts export default { output: { targets: ['web', 'node'], }, }; ``` > Only affect JavaScript API. Users using the Rsbuild CLI do not need to change. ## Entry Remove the deprecated `source.entries` config. `source.entries` has been renamed to `source.entry` since Rsbuild 0.1.0, and we will remove the legacy `source.entries` config in Rsbuild v0.2.0. * before: ```js // rsbuild.config.ts export default { source: { entries: {}, }, }; ``` * after: ```js // rsbuild.config.ts export default { source: { entry: {}, }, }; ``` ## Write to disk `dev.writeToDisk` defaults to `false`. Motivation: * Reduce fs overhead and improve dev server performance. * Avoid trigger watcher of UnoCSS and other tools. See [#654](https://github.com/web-infra-dev/rsbuild/issues/654). * Align the default behavior with webpack-dev-middleware and other community dev servers. User can enable writeToDisk manually: ```js export default { dev: { writeToDisk: true, }, }; ``` ## Babel plugin `@rsbuild/plugin-babel` will move all babel-loader options to `babelLoaderOptions`: * before: ```ts pluginBabel({ plugins: [], presets: [], }); ``` * after: ```ts pluginBabel([ babelLoaderOptions: { plugins: [], presets: [], } ]); ``` This change allows us to add more options for `pluginBabel`, such as `include` and `exclude`. ## Source map `output.disableSourceMap` has been renamed to `output.sourceMap`. * before: ```js export default { output: { disableSourceMap: { js: true, css: true, }, }, }; ``` * after: ```js export default { output: { sourceMap: { js: false, css: false, }, }, }; ``` The default value of source map has also been updated to improve build performance. * before: generate JS / CSS source map in development, generate JS source map in production. * after: generate JS source map in development, no source map are generated in production. ## Inject styles Rename `output.disableCssExtract` to `output.injectStyles` to be clearer: * before: ```js export default { output: { disableCssExtract: true, }, }; ``` * after: ```js export default { output: { injectStyles: true, }, }; ``` --- url: /community/releases/v0-1.md --- *November 22, 2023* # Announcing Rsbuild 0.1 ![](https://assets.rspack.dev/rsbuild/rsbuild-banner-v0-1.png) We are pleased to announce **the release of** **[Rsbuild](https://github.com/web-infra-dev/rsbuild)** **0.1!** Rsbuild is an Rspack-based build tool, designed to be **an enhanced Rspack** **CLI** that is both more user friendly and out-of-the-box. Rsbuild is the ideal solution for those looking to migrate from webpack to Rspack. It significantly reduces configuration by 90% while offering a 10x build speed. ### 🚀 Performance The build performance of Rsbuild is on par with native Rspack. Considering that Rsbuild includes more out-of-the-box features, its performance will be slightly lower than Rspack. This is the time it takes to build 1000 React components: > The data is based on the benchmark built by the Farm team, more info in [build-tools-performance](https://github.com/rspack-contrib/build-tools-performance). ### 🔥 Features Rsbuild has the following features: * **Easy to Configure**: One of the goals of Rsbuild is to provide out-of-the-box build capabilities for Rspack users, allowing developers to start a web project with zero configuration. In addition, Rsbuild provides semantic build configuration to reduce the learning curve for Rspack configuration. * **Performance Oriented**: Rsbuild integrates high-performance Rust-based tools from the community, including [Rspack](https://github.com/web-infra-dev/rspack), [SWC](https://swc.rs/) and [Lightning CSS](https://lightningcss.dev/), to deliver top-notch build speed and development experience. Compared to webpack-based tools like Create React App and Vue CLI, Rsbuild provides 5 to 10 times faster build performance and lighter dependencies. * **Plugin Ecosystem**: Rsbuild has a lightweight plugin system and includes a range of high-quality official plugins. Furthermore, Rsbuild is compatible with most webpack plugins and all Rspack plugins, allowing users to leverage existing community or in-house plugins in Rsbuild without the need for rewriting code. * **Stable Artifacts**: Rsbuild is designed with a strong focus on the stability of build artifacts. It ensures high consistency between artifacts in the development and production builds, and automatically completes syntax downgrading and polyfill injection. Rsbuild also provides plugins for type checking and artifact syntax validation to prevent quality and compatibility issues in production code. * **Framework Agnostic**: Rsbuild is not coupled with any front-end UI framework. It supports frameworks like React, Vue, Svelte, Solid and Preact through plugins, and plans to support more UI frameworks from the community in the future. ### 💡 Next step Currently, Rsbuild is still evolving rapidly and plans to introduce many more powerful new features. For example, we are developing **Rsdoctor**, a robust build analysis tool that can be used with all Rspack and webpack projects. It will provide a visual user interface to help developers analyze build times, duplicate dependencies, code transformation processes, and more, making it easier to locate and resolve build issues. ![Rsdoctor preview](https://assets.rspack.dev/rsbuild/assets/rsdoctor-preview.jpg) We will be releasing the first working version of Rsdoctor soon. Thereafter, Rsbuild will iterate in sync with Rspack, with plans to release version 1.0 in the first half of 2024. --- url: /index.md ---