Fix: Rspack Not Working — Build Failing, Loaders Not Applying, or Dev Server Not Starting
Quick Answer
How to fix Rspack issues — configuration migration from webpack, loader compatibility, CSS extraction, module federation, React Fast Refresh, and build performance tuning.
The Problem
Rspack fails to start with a config error:
npx rspack buildError: configuration.module.rules[0].use is not a valid valueOr a webpack loader you migrated doesn’t work:
Error: Can't resolve 'babel-loader'
Module not found: Error: Package path ./loader is not exported from packageOr CSS isn’t extracted into separate files:
All styles are inlined in JavaScript — no .css output fileOr React Fast Refresh doesn’t work — the page fully reloads on every change:
[HMR] Update applied. Full reload needed.Why This Happens
Rspack is a Rust-based bundler designed as a drop-in replacement for webpack. It supports most of webpack’s configuration format, but with important differences:
- Not all webpack loaders are compatible — Rspack uses its own Rust-based implementations for common transformations (TypeScript, JSX, CSS). JavaScript-based loaders like
babel-loaderandts-loaderwork but are slower. Some loaders that depend on webpack internals don’t work at all. - Built-in features replace plugins — Rspack has native CSS support, built-in SWC for TypeScript/JSX, and integrated asset handling. Using the webpack equivalents (
css-loader,style-loader,MiniCssExtractPlugin) still works but is unnecessary and slower. - Config format is almost identical but not 100% — most
webpack.config.jsoptions work unchanged. But some plugin APIs, hook signatures, and loader option formats differ. The error messages are usually clear about what’s wrong, but the fix isn’t always obvious. - React Fast Refresh needs the Rspack plugin, not the webpack one —
@pmmmwh/react-refresh-webpack-plugindoesn’t work with Rspack. Use@rspack/plugin-react-refreshinstead.
Fix 1: Basic Rspack Configuration
npm install -D @rspack/core @rspack/cli// rspack.config.js
const { defineConfig } = require('@rspack/cli');
const path = require('path');
module.exports = defineConfig({
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[contenthash].js',
clean: true,
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx'],
alias: {
'@': path.resolve(__dirname, 'src'),
},
},
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
// Use Rspack's built-in SWC loader — much faster than babel-loader
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
transform: {
react: {
runtime: 'automatic', // React 17+ JSX transform
development: process.env.NODE_ENV === 'development',
refresh: process.env.NODE_ENV === 'development',
},
},
},
},
},
{
test: /\.css$/,
// Built-in CSS support — no css-loader or style-loader needed
type: 'css',
},
{
test: /\.(png|jpg|gif|svg|woff2?)$/,
// Built-in asset handling
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 8 * 1024, // Inline if under 8kb
},
},
},
],
},
// Built-in plugins — no npm install needed
plugins: [],
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
},
});Fix 2: CSS Extraction and Processing
Rspack has native CSS support — no plugins needed for basic CSS:
// rspack.config.js
module.exports = {
module: {
rules: [
// Basic CSS — extracted to separate file automatically in production
{
test: /\.css$/,
type: 'css', // Built-in CSS handling
},
// CSS Modules
{
test: /\.module\.css$/,
type: 'css/module', // Built-in CSS Modules
},
// Sass/SCSS — still needs sass-loader
{
test: /\.scss$/,
use: [
{
loader: 'sass-loader',
options: {
// Use modern API
api: 'modern-compiler',
},
},
],
type: 'css', // Output goes through built-in CSS pipeline
},
// PostCSS + Tailwind CSS
{
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
'tailwindcss',
'autoprefixer',
],
},
},
},
],
type: 'css',
},
],
},
// For production — CSS is extracted by default
// For development — CSS is injected via style tags for HMR
experiments: {
css: true, // Enable native CSS support (default in Rspack)
},
};If you prefer the webpack-style MiniCssExtractPlugin approach:
const rspack = require('@rspack/core');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
rspack.CssExtractRspackPlugin.loader,
'css-loader',
'postcss-loader',
],
},
],
},
plugins: [
new rspack.CssExtractRspackPlugin({
filename: 'css/[name].[contenthash].css',
}),
],
};Fix 3: React Fast Refresh
HMR for React requires the Rspack-specific refresh plugin:
npm install -D @rspack/plugin-react-refresh react-refresh// rspack.config.js
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh');
const isDev = process.env.NODE_ENV === 'development';
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: { syntax: 'typescript', tsx: true },
transform: {
react: {
runtime: 'automatic',
development: isDev,
refresh: isDev, // Enable refresh transform in dev
},
},
},
},
},
],
},
plugins: [
isDev && new ReactRefreshPlugin(),
].filter(Boolean),
devServer: {
hot: true,
},
};Fast Refresh won’t work if:
- Component files export non-component values (e.g., constants alongside components)
- Components are wrapped in
React.memoat the export level in some edge cases - The file uses
module.hot.accept()manually — remove it and let the plugin handle it - Class components are used — Fast Refresh only works with function components and hooks
Fix 4: Migrate from webpack
Most webpack configs work with minimal changes:
// webpack.config.js → rspack.config.js — what to change
// BEFORE (webpack)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
module: {
rules: [
{ test: /\.tsx?$/, use: 'ts-loader' },
{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] },
],
},
plugins: [
new HtmlWebpackPlugin({ template: './public/index.html' }),
new MiniCssExtractPlugin(),
new CopyWebpackPlugin({ patterns: [{ from: 'public' }] }),
],
};
// AFTER (rspack)
const rspack = require('@rspack/core');
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
// Replace ts-loader with built-in SWC
loader: 'builtin:swc-loader',
options: {
jsc: {
parser: { syntax: 'typescript', tsx: true },
transform: { react: { runtime: 'automatic' } },
},
},
},
{
test: /\.css$/,
// Replace css-loader + MiniCssExtractPlugin with built-in
type: 'css',
},
],
},
plugins: [
// HtmlWebpackPlugin → built-in HtmlRspackPlugin
new rspack.HtmlRspackPlugin({ template: './public/index.html' }),
// CopyWebpackPlugin → built-in CopyRspackPlugin
new rspack.CopyRspackPlugin({
patterns: [{ from: 'public', globOptions: { ignore: ['**/index.html'] } }],
}),
],
};Loader compatibility quick reference:
| webpack Loader | Rspack Equivalent |
|---|---|
babel-loader | builtin:swc-loader (built-in) |
ts-loader | builtin:swc-loader (built-in) |
css-loader + style-loader | type: 'css' (built-in) |
file-loader / url-loader | type: 'asset' (built-in) |
sass-loader | sass-loader (still needed) |
postcss-loader | postcss-loader (still needed) |
svg-inline-loader | type: 'asset/source' |
Fix 5: Module Federation
Rspack supports Module Federation v1.5 natively:
// rspack.config.js — host application
const rspack = require('@rspack/core');
module.exports = {
plugins: [
new rspack.container.ModuleFederationPlugin({
name: 'host',
remotes: {
// Remote app available at runtime
remoteApp: 'remoteApp@http://localhost:3001/remoteEntry.js',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};
// rspack.config.js — remote application
module.exports = {
plugins: [
new rspack.container.ModuleFederationPlugin({
name: 'remoteApp',
filename: 'remoteEntry.js',
exposes: {
'./Button': './src/components/Button',
'./Header': './src/components/Header',
},
shared: {
react: { singleton: true, requiredVersion: '^18.0.0' },
'react-dom': { singleton: true, requiredVersion: '^18.0.0' },
},
}),
],
};// In host app — import remote component
const RemoteButton = React.lazy(() => import('remoteApp/Button'));
function App() {
return (
<Suspense fallback="Loading...">
<RemoteButton />
</Suspense>
);
}Fix 6: Build Performance Tuning
Rspack is fast by default, but you can optimize further:
module.exports = {
// Source maps — choose based on need
devtool: process.env.NODE_ENV === 'production'
? 'source-map' // Full source maps for production debugging
: 'cheap-module-source-map', // Faster for dev
// Caching — persistent cache across builds
cache: true, // Simple boolean or configure as object
// Optimization
optimization: {
// Split vendor chunks
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'all',
},
},
},
// Tree shaking — on by default in production
usedExports: true,
sideEffects: true,
// Minimize — uses SWC minifier (faster than terser)
minimize: process.env.NODE_ENV === 'production',
},
// Resolve — limit resolution scope
resolve: {
extensions: ['.ts', '.tsx', '.js'], // Don't add unnecessary extensions
modules: ['node_modules'], // Don't search upward
},
// Stats — reduce build output noise
stats: 'errors-warnings',
};Compare build times:
# Measure build performance
npx rspack build --profile
# Analyze bundle size
npx rspack build --analyze
# Opens a bundle analyzer in the browserStill Not Working?
builtin:swc-loader throws “unexpected token” on decorators — SWC needs decorator support enabled explicitly. Add jsc.parser.decorators: true and jsc.transform.legacyDecorator: true to your builtin:swc-loader options. Make sure experimentalDecorators is also set in your tsconfig.json.
Webpack plugin X doesn’t work with Rspack — not all webpack plugins are compatible. Plugins that use compiler.hooks extensively (e.g., webpack-bundle-analyzer, ForkTsCheckerWebpackPlugin) may need Rspack-specific alternatives. Check @rspack/ scoped packages first. For webpack-bundle-analyzer, use Rspack’s built-in --analyze flag instead.
Dev server starts but page is blank — check that devServer.historyApiFallback: true is set if you’re using client-side routing. Also verify the output.publicPath matches your dev server setup. The default / works for most cases, but if your app is served from a subdirectory, set it explicitly.
CSS @import in type: 'css' doesn’t resolve node_modules — by default, Rspack’s built-in CSS resolves @import relative to the file. For @import 'package-name/styles.css', prefix with ~: @import '~package-name/styles.css'. Or switch to postcss-loader with postcss-import which resolves node_modules automatically.
For related build tool issues, see Fix: esbuild Not Working and Fix: Webpack Bundle Size Too Large.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: Clack Not Working — Prompts Not Displaying, Spinners Stuck, or Cancel Not Handled
How to fix @clack/prompts issues — interactive CLI prompts, spinners, multi-select, confirm dialogs, grouped tasks, cancellation handling, and building CLI tools with beautiful output.
Fix: Sharp Not Working — Installation Failing, Image Not Processing, or Build Errors on Deploy
How to fix Sharp image processing issues — native binary installation, resize and convert operations, Next.js image optimization, Docker setup, serverless deployment, and common platform errors.
Fix: Shiki Not Working — No Syntax Highlighting, Wrong Theme, or Build Errors
How to fix Shiki syntax highlighter issues — basic setup, theme configuration, custom languages, transformer plugins, Next.js and Astro integration, and bundle size optimization.
Fix: Biome Not Working — Rules Not Applied, ESLint Config Not Migrated, or VSCode Extension Ignored
How to fix Biome linter/formatter issues — biome.json configuration, migrating from ESLint and Prettier, VSCode extension setup, CI integration, and rule override syntax.