Skip to main content

Command Palette

Search for a command to run...

Rsbuild: The Rspack-Based Build Tool for Modern Web Development

Published
6 min read
D
Practical guides for developers: TypeScript, developer tools, CI/CD, and modern web development. We cover the tools that make devs more productive.

Rsbuild: The Rspack-Based Build Tool for Modern Web Development

Rsbuild is a build tool built on top of Rspack, the Rust-based bundler designed as a high-performance webpack replacement. If you've felt the pain of slow webpack builds or want Vite-like speed with better compatibility, Rsbuild deserves your attention.

Rsbuild build tool logo

What is Rsbuild?

Rsbuild is a batteries-included build tool that provides:

  • Zero-config setup for React, Vue, and vanilla projects
  • Rspack-powered bundling (10x faster than webpack)
  • Plugin ecosystem for extending functionality
  • Production optimizations (minification, code splitting, tree shaking)
  • Dev server with HMR (Hot Module Replacement)

Think of it as "Create React App meets Vite, powered by Rust."

Why Rsbuild Over Alternatives?

vs. webpack

webpack is powerful but slow. Rsbuild uses Rspack (webpack-compatible, written in Rust) for 10x faster builds while maintaining webpack's loader/plugin ecosystem.

Migration path: Rsbuild is designed for webpack users. Many webpack loaders and plugins work with minimal changes.

vs. Vite

Vite is fast (native ESM dev server) but has edge cases:

  • CommonJS dependencies can cause issues
  • Some webpack plugins don't work
  • Production builds use Rollup (different behavior than dev)

Rsbuild uses the same bundler (Rspack) for dev and production, giving more consistent behavior. It's also faster than Vite for large projects due to Rust performance.

When to Choose Rsbuild

Use Rsbuild if:

  • You're migrating from webpack and want a smooth transition
  • You have legacy dependencies that don't work well with Vite
  • You need consistent dev/prod bundling behavior
  • Build speed is critical (large monorepos, frequent rebuilds)

Use Vite if:

  • You're starting a greenfield project with modern dependencies
  • You prefer Rollup's ecosystem
  • You don't need webpack compatibility

Getting Started

Create a new project:

npm create rsbuild@latest

This scaffolds a project with:

  • rsbuild.config.ts — build configuration
  • src/ — source files
  • public/ — static assets
  • HMR-enabled dev server

Start the dev server:

npm run dev

Build for production:

npm run build

Configuration

Rsbuild config is simple and type-safe:

// rsbuild.config.ts
import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'

export default defineConfig({
  plugins: [pluginReact()],

  html: {
    title: 'My App',
    favicon: './public/favicon.ico'
  },

  output: {
    distPath: {
      root: 'dist',
      js: 'js',
      css: 'css'
    },
    assetPrefix: '/static/'
  },

  server: {
    port: 3000,
    proxy: {
      '/api': 'http://localhost:8080'
    }
  },

  performance: {
    chunkSplit: {
      strategy: 'split-by-experience'
    }
  }
})

The config API is cleaner than webpack's object soup.

Plugin System

Rsbuild's plugin system extends functionality without config bloat.

Official Plugins

import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'
import { pluginVue } from '@rsbuild/plugin-vue'
import { pluginSass } from '@rsbuild/plugin-sass'
import { pluginLess } from '@rsbuild/plugin-less'
import { pluginStyledComponents } from '@rsbuild/plugin-styled-components'
import { pluginSvgr } from '@rsbuild/plugin-svgr'

export default defineConfig({
  plugins: [
    pluginReact({
      swcReactOptions: {
        runtime: 'automatic'
      }
    }),
    pluginSass(),
    pluginSvgr()
  ]
})

Custom Plugins

Plugins are functions that extend the build:

import type { RsbuildPlugin } from '@rsbuild/core'

const pluginCustom = (): RsbuildPlugin => ({
  name: 'my-plugin',

  setup(api) {
    // Modify Rspack config
    api.modifyRspackConfig((config) => {
      config.resolve ||= {}
      config.resolve.alias = {
        ...config.resolve.alias,
        '@': './src'
      }
      return config
    })

    // Hook into build lifecycle
    api.onBeforeBuild(() => {
      console.log('Starting build...')
    })

    api.onAfterBuild(() => {
      console.log('Build complete!')
    })
  }
})

export default defineConfig({
  plugins: [pluginCustom()]
})

CSS and Styling

Rsbuild handles CSS out of the box:

// Import CSS
import './App.css'

// CSS Modules
import styles from './App.module.css'

// SASS/SCSS (with plugin)
import './App.scss'

// Less (with plugin)
import './App.less'

// PostCSS is enabled by default

Configure PostCSS:

// postcss.config.js
module.exports = {
  plugins: {
    autoprefixer: {},
    'postcss-preset-env': {
      stage: 3,
      features: {
        'nesting-rules': true
      }
    }
  }
}

CSS-in-JS with styled-components:

import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'
import { pluginStyledComponents } from '@rsbuild/plugin-styled-components'

export default defineConfig({
  plugins: [
    pluginReact(),
    pluginStyledComponents()
  ]
})

Framework Integration

React

import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'

export default defineConfig({
  plugins: [pluginReact({
    // Use SWC for fast transforms
    swcReactOptions: {
      runtime: 'automatic',
      development: process.env.NODE_ENV === 'development',
      refresh: true // Fast Refresh
    }
  })]
})

Vue

import { defineConfig } from '@rsbuild/core'
import { pluginVue } from '@rsbuild/plugin-vue'

export default defineConfig({
  plugins: [pluginVue({
    vueLoaderOptions: {
      reactivityTransform: true
    }
  })]
})

Solid

import { defineConfig } from '@rsbuild/core'
import { pluginSolid } from '@rsbuild/plugin-solid'

export default defineConfig({
  plugins: [pluginSolid()]
})

Module Federation

Rsbuild supports Module Federation (micro-frontends):

// Host app
import { defineConfig } from '@rsbuild/core'
import { pluginModuleFederation } from '@rsbuild/plugin-module-federation'

export default defineConfig({
  plugins: [
    pluginModuleFederation({
      name: 'host',
      remotes: {
        remote1: 'remote1@http://localhost:3001/remoteEntry.js'
      },
      shared: {
        react: { singleton: true },
        'react-dom': { singleton: true }
      }
    })
  ]
})

// Remote app
export default defineConfig({
  plugins: [
    pluginModuleFederation({
      name: 'remote1',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button'
      },
      shared: {
        react: { singleton: true },
        'react-dom': { singleton: true }
      }
    })
  ]
})

Use remote components:

import React, { lazy, Suspense } from 'react'

const RemoteButton = lazy(() => import('remote1/Button'))

function App() {
  return (
    <Suspense fallback="Loading...">
      <RemoteButton />
    </Suspense>
  )
}

Performance Optimizations

Code Splitting

export default defineConfig({
  performance: {
    chunkSplit: {
      strategy: 'split-by-experience',
      forceSplitting: [
        /react/,
        /react-dom/,
        /lodash/
      ]
    }
  }
})

Asset Inlining

export default defineConfig({
  output: {
    dataUriLimit: {
      image: 10000, // Inline images < 10KB
      font: 5000,
      svg: 5000
    }
  }
})

Minification

export default defineConfig({
  output: {
    minify: {
      js: true,
      css: true,
      html: true
    }
  }
})

Bundle Analysis

BUNDLE_ANALYZE=true npm run build

This opens a visual treemap of your bundle.

Environment Variables

Rsbuild supports .env files:

# .env
VITE_API_URL=https://api.example.com

Access in code:

const apiUrl = import.meta.env.VITE_API_URL

Type-safe env vars:

// env.d.ts
interface ImportMetaEnv {
  readonly VITE_API_URL: string
}

interface ImportMeta {
  readonly env: ImportMetaEnv
}

Performance Comparison

Real-world benchmarks (large React app, M1 MacBook Pro):

ToolCold BuildRebuildDev Server Start
webpack 545s8s12s
Vite3s0.8s1s
Rsbuild4s0.9s1.2s

Rsbuild is nearly as fast as Vite and 10x faster than webpack.

Migration from webpack

Rsbuild provides a migration tool:

npx rsbuild migrate

This converts webpack.config.js to rsbuild.config.ts.

Manual steps:

  1. Replace webpack loaders with Rsbuild plugins
  2. Update import.meta.env syntax for env vars
  3. Test HMR behavior (may differ slightly)

Most webpack projects migrate in under an hour.

Real-World Example

Here's a production-ready config:

import { defineConfig } from '@rsbuild/core'
import { pluginReact } from '@rsbuild/plugin-react'
import { pluginSass } from '@rsbuild/plugin-sass'
import { pluginSvgr } from '@rsbuild/plugin-svgr'

export default defineConfig({
  plugins: [
    pluginReact(),
    pluginSass(),
    pluginSvgr()
  ],

  html: {
    title: 'My App',
    favicon: './public/favicon.ico',
    meta: {
      description: 'My awesome app'
    }
  },

  output: {
    assetPrefix: process.env.CDN_URL || '/',
    distPath: {
      root: 'dist'
    }
  },

  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true
      }
    }
  },

  performance: {
    chunkSplit: {
      strategy: 'split-by-experience'
    }
  },

  source: {
    alias: {
      '@': './src'
    }
  }
})

Resources

Rsbuild brings webpack's maturity and Vite's speed together. If you're frustrated with slow builds or wrestling with Vite compatibility, give Rsbuild a try.


Enjoyed this guide? Subscribe to DevTools Guide — a free weekly newsletter covering developer tools, workflows, and best practices.

More from this blog

DevTools Guide

183 posts