Bundlers

webpack and Rspack

For a webpack or Rspack build that is not behind a framework, the motif extractor is one entry in the plugins array. The same @usemotif/compiler-swc package exposes a webpack instance and an Rspack instance from one source.

Updated 3 days agoEdit on GitHubWeb & native

Install

example.tsx
yarn add -D @usemotif/compiler-swc

Add the plugin

The default export is a universal unplugin instance. Call .webpack() and add the result to plugins.

webpack.config.js
const motif = require('@usemotif/compiler-swc').default;
 
module.exports = {
plugins: [
  motif.webpack(),
],
};

For an Rspack build the call is .rspack() instead — same options, same behaviour. The plugin enforces a pre stage, so motif extraction runs before whatever compiles your JSX, whether that is swc-loader, babel-loader, or ts-loader.

Ship the extracted CSS

The plugin aggregates extracted rules into a virtual module. Import it once from your entry, and let your CSS pipeline — mini-css-extract-plugin, css-loader, or the built-in CSS handling — turn it into a stylesheet asset.

src/index.tsx
import 'virtual:motif-extract.css';
 
import { createRoot } from 'react-dom/client';
import { App } from './App';
 
createRoot(document.getElementById('root')!).render(<App />);

If the import is missing, the virtual module is never pulled into the graph and the extracted CSS is dropped — every styled element then falls back to the runtime path. The bare alias 'motif-extract.css' resolves to the same module.

Scope the transform

MotifBundlerOptions carries include and exclude. The defaults transform .js, .jsx, .ts, .tsx, .mjs, and .cjs, and skip node_modules.

webpack.config.js
motif.webpack({
exclude: [/node_modules/, /\.test\.tsx?$/],
})

Verify it ran

Build, then check the emitted CSS for a motif rule — extracted class names carry the m- prefix.

example.tsx
webpack --mode production && grep -rl 'm-' dist/*.css

An empty result means the virtual import is missing or exclude is catching your source files.