Build React Apps 10x Faster with Rspack and Rsbuild: The Rust-Powered Bundler Guide

If you have ever waited minutes for your webpack build to finish, you know the pain. Rspack and Rsbuild are here to change that. Written in Rust, Rspack is a drop-in webpack replacement that delivers build speeds up to 10x faster, while Rsbuild is the higher-level build tool that provides an out-of-the-box development experience on top of it.
In this tutorial, you will build a complete React application from scratch using Rsbuild, then learn how to configure Rspack directly for advanced use cases. You will also learn how to migrate an existing webpack project step by step.
Prerequisites
Before starting, make sure you have:
- Node.js 18+ installed (Node 20 recommended)
- npm, yarn, or pnpm as your package manager
- Basic knowledge of React and TypeScript
- A code editor (VS Code recommended)
- Optional: An existing webpack project if you plan to migrate
What You Will Build
By the end of this tutorial, you will have:
- A new React + TypeScript app built with Rsbuild from scratch
- Understanding of Rspack configuration for advanced control
- Knowledge to migrate any webpack project to Rspack
Understanding the Rspack Ecosystem
Before diving into code, let us understand the two main tools:
- Rspack is the low-level bundler, a Rust-based replacement for webpack. It is compatible with most webpack plugins and loaders while being dramatically faster.
- Rsbuild is the high-level build tool built on top of Rspack. Think of it as what Create React App or Vite is for their respective bundlers, but powered by Rspack.
When to use which?
| Use Case | Tool |
|---|---|
| New React project | Rsbuild |
| Need full webpack-like control | Rspack CLI |
| Migrating from CRA | Rsbuild |
| Migrating from webpack | Rspack (then optionally Rsbuild) |
| Library bundling | Rspack |
Step 1: Create a New React Project with Rsbuild
The fastest way to get started is using Rsbuild's project generator:
npm create rsbuild@latestWhen prompted, select:
- Project name:
my-rsbuild-app - Framework:
React - Language:
TypeScript
This creates a project with sensible defaults. Navigate into it and install dependencies:
cd my-rsbuild-app
npm installStart the development server:
npm run devYour app should be running at http://localhost:3000 with blazing-fast Hot Module Replacement (HMR).
Step 2: Explore the Project Structure
The generated project has a clean structure:
my-rsbuild-app/
src/
App.tsx
App.css
index.tsx
env.d.ts
rsbuild.config.ts
tsconfig.json
package.json
The key file is rsbuild.config.ts. Open it:
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
export default defineConfig({
plugins: [pluginReact()],
});That is it. Two lines of configuration and you have a fully working React + TypeScript setup with:
- SWC-based compilation (no Babel needed)
- CSS Modules support
- Fast Refresh (HMR)
- Automatic code splitting
- Environment variable loading
Step 3: Configure Rsbuild for Production
Let us add production-ready configuration. Update rsbuild.config.ts:
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
export default defineConfig({
plugins: [
pluginReact({
swcReactOptions: {
runtime: 'automatic',
},
splitChunks: {
react: true,
router: true,
},
}),
],
source: {
entry: {
index: './src/index.tsx',
},
},
output: {
distPath: {
root: 'dist',
},
cleanDistPath: true,
sourceMap: {
js: process.env.NODE_ENV === 'production'
? 'source-map'
: 'cheap-module-source-map',
},
},
html: {
title: 'My Rsbuild App',
favicon: './src/favicon.ico',
},
server: {
port: 3000,
open: true,
},
performance: {
chunkSplit: {
strategy: 'split-by-experience',
},
},
});What each section does:
- plugins: Registers the React plugin with chunk splitting for React and React Router
- source.entry: Defines the application entry point
- output: Configures build output, source maps, and cleaning
- html: Sets the page title and favicon
- server: Dev server configuration with auto-open
- performance.chunkSplit: Splits vendor chunks intelligently based on common patterns
Step 4: Add CSS Modules and Styling
Rsbuild supports CSS Modules out of the box. Create a component with scoped styles:
/* src/components/Card.module.css */
.card {
border: 1px solid #e0e0e0;
border-radius: 12px;
padding: 24px;
transition: box-shadow 0.2s ease;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.title {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 8px;
}
.description {
color: #666;
line-height: 1.6;
}// src/components/Card.tsx
import styles from './Card.module.css';
interface CardProps {
title: string;
description: string;
}
export function Card({ title, description }: CardProps) {
return (
<div className={styles.card}>
<h3 className={styles.title}>{title}</h3>
<p className={styles.description}>{description}</p>
</div>
);
}Any file ending in .module.css is automatically treated as a CSS Module. No configuration needed.
Step 5: Environment Variables
Rsbuild loads .env files automatically. Create a .env file:
# .env
PUBLIC_API_URL=https://api.example.com
PUBLIC_APP_NAME=My Rsbuild AppAccess them in your code:
// Variables prefixed with PUBLIC_ are available in client code
console.log(process.env.PUBLIC_API_URL);
console.log(process.env.PUBLIC_APP_NAME);You can customize the prefix in your config:
export default defineConfig({
loadEnv: {
prefixes: ['PUBLIC_', 'REACT_APP_'],
},
});This is especially useful when migrating from Create React App, where variables use the REACT_APP_ prefix.
Step 6: Advanced Rspack Configuration
For projects that need webpack-level control, you can use Rspack directly. Here is a complete rspack.config.ts for a React + TypeScript project:
import { defineConfig } from '@rspack/cli';
import { rspack, type SwcLoaderOptions } from '@rspack/core';
import { ReactRefreshRspackPlugin } from '@rspack/plugin-react-refresh';
const isDev = process.env.NODE_ENV === 'development';
const targets = ['last 2 versions', '> 0.2%', 'not dead'];
export default defineConfig({
entry: {
main: './src/index.tsx',
},
output: {
path: './dist',
filename: isDev ? '[name].js' : '[name].[contenthash:8].js',
cssFilename: isDev ? '[name].css' : '[name].[contenthash:8].css',
clean: true,
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js'],
alias: {
'@': './src',
},
},
module: {
rules: [
{
test: /\.(tsx?|jsx?)$/,
exclude: /node_modules/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
transform: {
react: {
runtime: 'automatic',
development: isDev,
refresh: isDev,
},
},
},
env: { targets },
} satisfies SwcLoaderOptions,
},
},
{
test: /\.css$/,
type: 'css/auto',
},
{
test: /\.(png|jpe?g|gif|svg|webp)$/,
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // 8KB
},
},
},
],
},
plugins: [
new rspack.HtmlRspackPlugin({
template: './index.html',
}),
new rspack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
}),
isDev && new ReactRefreshRspackPlugin(),
].filter(Boolean),
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
},
});Key differences from webpack:
builtin:swc-loaderreplacesbabel-loaderentirely. It is written in Rust and compiles TypeScript and JSX natively.css/autotype handles CSS files including CSS Modules detection automatically.rspack.HtmlRspackPluginis a Rust-native replacement forhtml-webpack-plugin.ReactRefreshRspackPluginreplaces@pmmmwh/react-refresh-webpack-plugin.
Step 7: Migrate an Existing Webpack Project
If you have an existing webpack project, follow these steps:
7.1: Install Rspack
npm install @rspack/core @rspack/cli -D
npm install @rspack/plugin-react-refresh -D7.2: Rename Configuration
mv webpack.config.js rspack.config.js7.3: Update Package Scripts
{
"scripts": {
"dev": "rspack serve",
"build": "rspack build"
}
}7.4: Replace babel-loader with builtin:swc-loader
Remove Babel dependencies:
npm uninstall babel-loader @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescriptReplace the babel-loader rule in your config:
// Before (webpack)
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-typescript',
],
},
},
}
// After (rspack)
{
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
transform: {
react: {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development',
refresh: process.env.NODE_ENV === 'development',
},
},
},
},
},
}7.5: Replace Plugins
| webpack Plugin | Rspack Replacement |
|---|---|
html-webpack-plugin | rspack.HtmlRspackPlugin |
mini-css-extract-plugin | Built-in (use type: 'css/auto') |
copy-webpack-plugin | rspack.CopyRspackPlugin |
DefinePlugin | rspack.DefinePlugin |
react-refresh-webpack-plugin | @rspack/plugin-react-refresh |
7.6: Handle CSS
Replace css-loader + style-loader chain with the built-in CSS type:
// Before (webpack)
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}
// After (rspack)
{
test: /\.css$/,
type: 'css/auto',
}Step 8: Add Popular Plugins
Sass/SCSS Support
npm install @rsbuild/plugin-sass -Dimport { pluginSass } from '@rsbuild/plugin-sass';
export default defineConfig({
plugins: [
pluginReact(),
pluginSass(),
],
});SVG as React Components
npm install @rsbuild/plugin-svgr -Dimport { pluginSvgr } from '@rsbuild/plugin-svgr';
export default defineConfig({
plugins: [
pluginReact(),
pluginSvgr({
svgrOptions: {
exportType: 'named',
},
}),
],
});Use SVGs as components:
import { ReactComponent as Logo } from './logo.svg';
function App() {
return <Logo width={100} height={100} />;
}Tailwind CSS
No special plugin needed. Just install Tailwind and configure it normally:
npm install tailwindcss @tailwindcss/postcss postcss -DCreate postcss.config.js:
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};Then import Tailwind in your CSS:
@import "tailwindcss";Rsbuild picks up PostCSS configuration automatically.
Step 9: Build and Analyze
Run the production build:
npm run buildYou will notice the build completes significantly faster than webpack. For a medium-sized React project, expect:
| Metric | webpack | Rspack |
|---|---|---|
| Cold build | 30-60s | 3-6s |
| HMR update | 500-2000ms | 50-200ms |
| Dev server start | 10-20s | 1-3s |
To analyze your bundle:
RSBUILD_BUNDLE_ANALYZE=true npm run buildThis generates an interactive bundle analysis report in your browser.
Testing Your Implementation
Verify everything works correctly:
- Dev server: Run
npm run devand confirm HMR works by editing a component - CSS Modules: Check that styles are scoped (class names should be hashed)
- TypeScript: Introduce a type error and verify it shows in the terminal
- Production build: Run
npm run buildand serve thedistfolder - Environment variables: Add a
PUBLIC_variable and log it in a component
Troubleshooting
"Module not found" for webpack loaders
If you see errors about missing loaders, you are likely using a webpack-specific loader. Check if Rspack has a built-in replacement (most common ones do).
CSS not being extracted in production
Make sure you are using type: 'css/auto' in your Rspack rules. Rsbuild handles this automatically.
React Fast Refresh not working
Ensure ReactRefreshRspackPlugin is only added in development mode and that refresh: true is set in your SWC options.
Webpack plugins not compatible
While most webpack plugins work, some that rely on internal webpack APIs may not. Check the Rspack compatibility list at rspack.dev for alternatives.
Next Steps
- Explore the full Rsbuild plugin ecosystem at rsbuild.dev
- Set up Storybook with Rsbuild using
storybook-rsbuild - Try Module Federation for micro-frontends with Rspack
- Add testing with Vitest (works seamlessly alongside Rsbuild)
- Check out Rslib for building library packages with Rspack
Conclusion
Rspack and Rsbuild bring the speed of Rust to the JavaScript bundling world without sacrificing webpack compatibility. Whether you are starting a new project with Rsbuild's zero-config approach or migrating an existing webpack project to Rspack, you get dramatic build speed improvements with minimal effort.
The key takeaway: start with Rsbuild for new projects (it handles the complexity for you), and use Rspack directly when you need fine-grained webpack-level control. Either way, your builds will be faster, your development experience smoother, and your team happier.
Discuss Your Project with Us
We're here to help with your web development needs. Schedule a call to discuss your project and how we can assist you.
Let's find the best solutions for your needs.
Related Articles

Build a Real-Time Full-Stack App with Convex and Next.js 15
Learn how to build a real-time full-stack application using Convex and Next.js 15. This tutorial covers schema design, queries, mutations, real-time subscriptions, authentication, and file uploads — all with end-to-end type safety.

Build a Full-Stack App with Firebase and Next.js 15: Auth, Firestore & Real-Time
Learn how to build a full-stack app with Next.js 15 and Firebase. This guide covers authentication, Firestore, real-time updates, Server Actions, and deployment to Vercel.

Building Local-First Collaborative Apps with Yjs and React
Learn how to build real-time collaborative applications that work offline using Yjs CRDTs and React. This tutorial covers conflict-free data synchronization, offline-first architecture, and building a shared document editor from scratch.