website/docs/en/plugins/css-extract-rspack-plugin.mdx
import { ApiMeta } from '@components/ApiMeta.tsx';
<ApiMeta specific={['Rspack']} />
CssExtractRspackPlugin works with css-loader to extract CSS imported by JavaScript modules into separate files. In Rspack, use it as an alternative to mini-css-extract-plugin, or whenever your project needs css-loader features.
By default, CSS in entry chunks is emitted as [name].css. CSS loaded through dynamic import() is handled by runtime code injected by the plugin.
If your project does not need css-loader, prefer Rspack's built-in CSS support to avoid the extra loader and plugin processing.
:::warning
CssExtractRspackPlugin.loader cannot be used with Rspack's built-in CSS module types: css, css/auto, css/global, or css/module. The default module type is javascript/auto, so type can normally be omitted. If a module uses one of the built-in CSS types, the loader skips it and emits a warning; the plugin does not extract its CSS.
:::
Register the plugin and place CssExtractRspackPlugin.loader before css-loader in the CSS rule:
import { rspack } from '@rspack/core';
export default {
entry: './src/index.js',
plugins: [new rspack.CssExtractRspackPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
},
],
},
};
If the main entry imports CSS, the default output includes:
dist/
├── main.js
└── main.css
CssExtractRspackPlugin emits CSS imported by an entry, but does not add a link for it to HTML. Register HtmlRspackPlugin alongside it to generate index.html and inject the corresponding stylesheet <link> tags:
import { rspack } from '@rspack/core';
export default {
entry: './src/index.js',
plugins: [new rspack.HtmlRspackPlugin(), new rspack.CssExtractRspackPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
},
],
},
};
The configuration above generates dist/index.html with a link to main.css:
<link href="main.css" rel="stylesheet" />
CssExtractRspackPlugin represents extracted styles as modules of type css/mini-extract. Use splitChunks.cacheGroups.{cacheGroup}.type to select only CSS extracted by this plugin, without selecting JavaScript modules or modules handled by Rspack's built-in CSS support.
import { rspack } from '@rspack/core';
export default {
plugins: [new rspack.CssExtractRspackPlugin()],
module: {
rules: [
{
test: /\.css$/i,
use: [rspack.CssExtractRspackPlugin.loader, 'css-loader'],
},
],
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
extractedCss: {
type: 'css/mini-extract',
name: 'styles',
chunks: 'all',
enforce: true,
},
},
},
},
};
Here, extractedCss selects only modules whose type is css/mini-extract. For details about enforce, see splitChunks.cacheGroups.{cacheGroup}.enforce.
Pass these options to new rspack.CssExtractRspackPlugin().
Type:
type CssFilenameFunction = (
pathData: PathData,
assetInfo?: AssetInfo,
) => string;
type CssFilename = string | CssFilenameFunction;
Default: '[name].css'
Sets the filename of extracted CSS assets for chunks loaded with an entry. The value supports the placeholders documented for output.filename. When omitted or set to an empty string, Rspack uses [name].css. CSS assets for on-demand chunks use chunkFilename.
String: Uses a non-empty value as the filename template for every CSS chunk loaded with an entry.
new rspack.CssExtractRspackPlugin({
filename: 'css/[name].[contenthash].css',
});
Function: For each CSS chunk loaded with an entry, Rspack calls the function with its PathData and optional AssetInfo, then uses the returned string as the filename.
new rspack.CssExtractRspackPlugin({
filename: ({ chunk }) => `css/${chunk?.name ?? 'styles'}.css`,
});
When filename is a function and chunkFilename is omitted, on-demand CSS chunks use [id].css; Rspack does not reuse the function for them.
Type:
type CssChunkFilenameFunction = (
pathData: PathData,
assetInfo?: AssetInfo,
) => string;
type CssChunkFilename = string | CssChunkFilenameFunction;
Default: Derived from filename
Sets the filename of extracted CSS assets for on-demand chunks, including chunks created by dynamic import(). An explicitly configured non-empty string or function overrides the value derived from filename. The value supports the placeholders documented for output.chunkFilename.
When omitted, Rspack derives the value as follows:
If a string filename contains [name], [id], [chunkhash], or [contenthash], Rspack reuses it.
If a string filename contains none of those placeholders, Rspack adds [id]. before its basename. For example, css/styles.css produces css/[id].styles.css for async chunks.
If filename is a function, Rspack uses [id].css.
String: Uses a non-empty value as the filename template for every on-demand CSS chunk.
new rspack.CssExtractRspackPlugin({
chunkFilename: 'css/[id].[contenthash].chunk.css',
});
Function: Rspack calls the function for each on-demand CSS chunk with its PathData and optional AssetInfo, then uses the returned string as the filename.
new rspack.CssExtractRspackPlugin({
chunkFilename: ({ chunk }) =>
`css/${chunk?.name ?? chunk?.id ?? 'chunk'}.chunk.css`,
});
booleanfalseControls whether Rspack reports CSS order conflicts. By default, Rspack warns when different chunk groups require incompatible CSS orders, then emits the CSS using a fallback order.
Set ignoreOrder to true to suppress these warnings. This does not change the order Rspack chooses and does not resolve order-dependent styling conflicts.
new rspack.CssExtractRspackPlugin({
ignoreOrder: true,
});
Type:
type InsertFunction = (linkTag: HTMLLinkElement) => void;
type Insert = string | InsertFunction;
Default: undefined
Sets the insertion position of stylesheet <link> elements created by the plugin runtime for async CSS chunks and HMR updates. It does not affect stylesheet links already present in HTML.
When omitted, the runtime appends a new async stylesheet to document.head. During a hot update, it inserts the replacement after the previous stylesheet.
String: Treats the value as a selector passed to document.querySelector() and inserts the stylesheet immediately after the first matching element. The selector must match an element at runtime.
new rspack.CssExtractRspackPlugin({
insert: '#css-anchor',
});
Function: Serializes the function into the generated runtime and calls it in the browser with the new <link> element. The function must insert the element itself and cannot use variables from the Rspack configuration's scope.
new rspack.CssExtractRspackPlugin({
insert: (linkTag) => {
document.head.appendChild(linkTag);
},
});
The insert option has no effect when runtime is false.
Record<string, string>undefinedAdds custom attributes to stylesheet <link> elements created by the plugin runtime. These elements are used when loading async CSS chunks and applying HMR updates; stylesheet links already present in HTML are not affected. When omitted, the runtime adds no custom attributes.
new rspack.CssExtractRspackPlugin({
attributes: {
'data-source': 'rspack',
},
});
Use linkType to control the type attribute. When both options set type, a string linkType takes precedence. The attributes option has no effect when runtime is false.
string | false'text/css'Sets the type attribute on stylesheet <link> elements created by the plugin runtime. These elements are used when loading async CSS chunks and applying HMR updates; stylesheet links already present in HTML are not affected.
When omitted, the runtime sets the attribute to text/css.
String: Sets the type attribute to the provided value.
new rspack.CssExtractRspackPlugin({
linkType: 'text/css',
});
false: Disables the plugin's default type assignment. The attribute is omitted unless attributes supplies a custom type value.
new rspack.CssExtractRspackPlugin({
linkType: false,
});
The linkType option has no effect when runtime is false.
booleantrueControls whether the plugin injects code that loads CSS for async chunks at runtime. Setting it to false still emits extracted CSS assets, but your application must load CSS for on-demand chunks itself.
When omitted, the plugin includes the CSS-loading runtime.
When disabled, insert, attributes, and linkType cannot affect async CSS loading because the plugin does not create those <link> elements.
new rspack.CssExtractRspackPlugin({
runtime: false,
});
booleantrue when output.pathinfo is enabled, otherwise falseControls whether the plugin adds a comment containing the readable module path before each extracted module. These comments make CSS assets easier to inspect, but increase their size and can expose source paths.
An explicit pathinfo value takes precedence over output.pathinfo. When omitted, the option inherits the value of output.pathinfo.
new rspack.CssExtractRspackPlugin({
pathinfo: true,
});
booleanfalseWhen the effective loader publicPath is 'auto', Rspack calculates asset URLs relative to the emitted CSS file. If the calculated prefix is empty, this option controls whether the URL starts with ./. The default produces url(assets/icon.svg); setting it to true produces url(./assets/icon.svg).
An explicitly configured loader publicPath other than 'auto' takes precedence, so enforceRelative has no effect in that case.
new rspack.CssExtractRspackPlugin({
enforceRelative: true,
});
Set these options on CssExtractRspackPlugin.loader in module.rules.
Type:
type PublicPathFunction = (resourcePath: string, context: string) => string;
type PublicPath = string | PublicPathFunction;
Default: output.publicPath
Sets the public path used for assets referenced in CSS, such as images and fonts. It does not affect the URL of the emitted CSS file itself.
An explicit loader publicPath takes precedence over output.publicPath for the CSS resource being processed.
When omitted, the loader uses output.publicPath.
String: Uses the same public path for every matching CSS resource.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
publicPath: '/assets/',
},
},
'css-loader',
],
};
Function: Calls the function at build time with the absolute CSS resourcePath and the compiler root context. The returned string becomes the public path for that resource.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
publicPath: (resourcePath, context) =>
resourcePath.startsWith(context) ? '/assets/' : '/external-assets/',
},
},
'css-loader',
],
};
booleantrueControls whether CSS from the processed resource is included in extracted CSS assets. Setting it to false still processes the resource and preserves any CSS Modules exports in JavaScript, but omits its CSS from emitted files.
When omitted, the resource's CSS is included in an emitted CSS asset.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
emit: false,
},
},
'css-loader',
],
};
booleantrueControls whether the JavaScript module generated by CssExtractRspackPlugin.loader uses ES module or CommonJS syntax. Setting it to false uses CommonJS. For consistent output, set css-loader's esModule option to the same value.
When omitted, CssExtractRspackPlugin.loader uses ES module syntax.
When css-loader generates named CSS Modules exports, those exports remain ES modules. In that case, use defaultExport to control whether the loader also generates a default export.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
esModule: false,
},
},
{
loader: 'css-loader',
options: {
esModule: false,
},
},
],
};
stringundefinedAssigns the processed CSS resource to the specified Rspack module layer. This is a module-graph layer, not a CSS cascade @layer. Use it with options such as splitChunks.cacheGroups.{cacheGroup}.layer to select extracted CSS by layer.
When omitted, this loader does not assign an explicit module layer.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
layer: 'theme',
},
},
'css-loader',
],
};
booleanfalseWhen css-loader generates named CSS Modules exports, this option controls whether CssExtractRspackPlugin.loader also generates a default object containing all local class names. The named exports are always preserved.
This option has no effect when css-loader does not generate named exports. When omitted, only the named exports are generated in that mode.
const cssRule = {
test: /\.css$/i,
use: [
{
loader: rspack.CssExtractRspackPlugin.loader,
options: {
defaultExport: true,
},
},
{
loader: 'css-loader',
options: {
modules: {
namedExport: true,
},
},
},
],
};