diff --git a/src/lib/examples.ts b/src/lib/examples.ts index 4dc6f62..d3a620c 100644 --- a/src/lib/examples.ts +++ b/src/lib/examples.ts @@ -20,6 +20,7 @@ export function exampleGroups(base: string): ExampleGroup[] { items: [ { label: 'Vite', href: `${base}examples/vite/`, key: 'vite' }, { label: 'webpack', href: `${base}examples/webpack/`, key: 'webpack' }, + { label: 'Rspack', href: `${base}examples/rspack/`, key: 'rspack' }, ], }, ]; diff --git a/src/lib/playgrounds.ts b/src/lib/playgrounds.ts index da0c9e1..d193d16 100644 --- a/src/lib/playgrounds.ts +++ b/src/lib/playgrounds.ts @@ -38,6 +38,7 @@ export const PLAYGROUND_LINKS: PlaygroundLink[] = [ { id: 'default', label: 'Default' }, { id: 'vite', label: 'Vite' }, { id: 'webpack', label: 'webpack' }, + { id: 'rspack', label: 'Rspack' }, ]; export function playgroundGroups(base: string) { @@ -54,7 +55,7 @@ export function playgroundGroups(base: string) { }, { label: 'Frameworks', - items: [link('vite', 'Vite'), link('webpack', 'webpack')], + items: [link('vite', 'Vite'), link('webpack', 'webpack'), link('rspack', 'Rspack')], }, ]; } @@ -90,6 +91,17 @@ const webpackConfig = `export default { }, };`; +const rspackConfig = `export default { + module: { + rules: [ + { + test: /\\.css$/i, + use: ['style-loader', 'css-loader', '@postcss-go/rspack-loader'], + }, + ], + }, +};`; + const demoInput = `.hero { display: flex; gap: 1rem; @@ -139,6 +151,19 @@ const webpackInput = `.hero { } `; +const rspackInput = `.hero { + display: flex; + gap: 0.5rem; + min-height: 100vh; + align-items: center; + justify-content: center; + + & h1 span { + color: #c8ff3d; + } +} +`; + export const PLAYGROUND_PRESETS: Record = { default: { id: 'default', @@ -221,4 +246,33 @@ export const PLAYGROUND_PRESETS: Record = { ], previewHtml: `

webpack + PostCSS

`, }, + rspack: { + id: 'rspack', + title: 'Rspack', + description: 'CSS as @postcss-go/rspack-loader would hand to the engine.', + exampleId: 'rspack', + plugins: { nested: true, autoprefixer: true }, + files: [ + { + id: 'postcss', + filename: 'postcss.config.js', + language: 'javascript', + content: postcssConfig, + }, + { + id: 'rspack', + filename: 'rspack.config.js', + language: 'javascript', + content: rspackConfig, + }, + { + id: 'css', + filename: 'src/styles.css', + language: 'css', + content: rspackInput, + input: true, + }, + ], + previewHtml: `

Rspack + PostCSS

`, + }, }; diff --git a/src/pages/examples/rspack.astro b/src/pages/examples/rspack.astro new file mode 100644 index 0000000..13af817 --- /dev/null +++ b/src/pages/examples/rspack.astro @@ -0,0 +1,82 @@ +--- +import ExamplesLayout from '../../layouts/ExamplesLayout.astro'; +import CodeSample from '../../components/CodeSample.astro'; +import PlaygroundCta from '../../components/PlaygroundCta.astro'; + +const install = + 'pnpm add -D @postcss-go/core @postcss-go/rspack-loader autoprefixer @rspack/core @rspack/cli css-loader style-loader'; +const config = `export default { + plugins: { + autoprefixer: {}, + }, +};`; +const rspackConfig = `export default { + module: { + rules: [ + { + test: /\\.css$/i, + use: ['style-loader', 'css-loader', '@postcss-go/rspack-loader'], + }, + ], + }, +};`; +const rspackConfigInline = `import autoprefixer from 'autoprefixer'; + +export default { + module: { + rules: [ + { + test: /\\.css$/i, + use: [ + 'style-loader', + 'css-loader', + { + loader: '@postcss-go/rspack-loader', + options: { + sourceMap: true, + postcssOptions: { + config: false, + plugins: [autoprefixer()], + }, + }, + }, + ], + }, + ], + }, +};`; +const css = `.button { + display: flex; + gap: 0.5rem; +}`; +const scripts = `{ + "scripts": { + "build": "rspack --mode production", + "build:css": "postcss-go src/**/*.css --base src --dir dist/css --no-map" + } +}`; +--- + + +

Rspack

+

+ Add @postcss-go/rspack-loader to your CSS rule. It calls the Go engine directly and does + not depend on postcss or the official postcss-loader. By default it + discovers postcss.config.js from the input file, same as the CLI. You can keep + css-loader or Rspack's builtin:css-loader after this loader. +

+ + + + +

+ Pass postcssOptions inline when you want to disable config lookup or set plugins in the + Rspack config. postcssOptions can also be a function that receives mode, + env, file, and the loader context. +

+ + +

You can still run the CLI for a bundler-free CSS pass:

+ +
diff --git a/src/pages/guide/get-started.md b/src/pages/guide/get-started.md index 820af4a..e2515a6 100644 --- a/src/pages/guide/get-started.md +++ b/src/pages/guide/get-started.md @@ -50,8 +50,9 @@ file or environment:
terminal
pnpm postcss-go src/index.css -o dist/index.css
-For the default config, see [Examples](../../examples/default/). For Vite and webpack, -see the [Vite example](../../examples/vite/) and [webpack example](../../examples/webpack/). +For the default config, see [Examples](../../examples/default/). For Vite, webpack, and Rspack, +see the [Vite example](../../examples/vite/), [webpack example](../../examples/webpack/), and +[Rspack example](../../examples/rspack/). For a gradual migration, see the [migration and compatibility guide](../migration/). For browsers, import `@postcss-go/core/wasm` and follow the [Browser and WASM](../browser-wasm/) guide. diff --git a/test/examples.test.ts b/test/examples.test.ts index 1a33c74..617c64c 100644 --- a/test/examples.test.ts +++ b/test/examples.test.ts @@ -6,7 +6,7 @@ describe('exampleGroups', () => { it('includes Vite in Frameworks', () => { const groups = exampleGroups('/'); const frameworks = groups.find((group) => group.label === 'Frameworks'); - expect(frameworks?.items.map((item) => item.key)).toEqual(['vite', 'webpack']); + expect(frameworks?.items.map((item) => item.key)).toEqual(['vite', 'webpack', 'rspack']); }); it('builds framework hrefs from the site base', () => { diff --git a/test/playgrounds.test.ts b/test/playgrounds.test.ts index 4a27c37..d144e85 100644 --- a/test/playgrounds.test.ts +++ b/test/playgrounds.test.ts @@ -10,7 +10,12 @@ import { describe('playgrounds', () => { it('lists the Vite preset', () => { - expect(PLAYGROUND_LINKS.map((item) => item.id)).toEqual(['default', 'vite', 'webpack']); + expect(PLAYGROUND_LINKS.map((item) => item.id)).toEqual([ + 'default', + 'vite', + 'webpack', + 'rspack', + ]); }); it('builds playground nav links from the site base', () => { @@ -25,6 +30,10 @@ describe('playgrounds', () => { expect(PLAYGROUND_PRESETS.vite.exampleId).toBe('vite'); }); + it('links the Rspack preset to the Rspack example', () => { + expect(PLAYGROUND_PRESETS.rspack.exampleId).toBe('rspack'); + }); + it('includes Vite config and CSS input files', () => { const preset = playgroundPreset('vite'); expect(preset.files.map((file) => file.filename)).toEqual([ @@ -35,6 +44,16 @@ describe('playgrounds', () => { expect(playgroundInputFile(preset).filename).toBe('src/styles.css'); }); + it('includes Rspack config and CSS input files', () => { + const preset = playgroundPreset('rspack'); + expect(preset.files.map((file) => file.filename)).toEqual([ + 'postcss.config.js', + 'rspack.config.js', + 'src/styles.css', + ]); + expect(playgroundInputFile(preset).filename).toBe('src/styles.css'); + }); + it('falls back to the default preset for unknown ids', () => { expect(playgroundPreset('missing').id).toBe('default'); });