Vite, webpack, Rspack, Rollup, esbuild
@nibcss/unplugin is one plugin for five bundlers: the same options, the same generated files, the same dev-server behaviour.
@nibcss/unplugin is the build half of NibCSS. Whatever the framework, the plugin does the same four
things: read nibcss.config.ts, scan your sources, write the stylesheet, and compile static
attributes into class names.
1. Install#
npm i @nibcss/runtime
npm i -D @nibcss/unplugin2. Add it#
import { defineConfig } from "vite";
import nib from "@nibcss/unplugin/vite";
export default defineConfig({ plugins: [nib()] });Then import the two things the plugin publishes:
import "@nibcss/styles.css"; // the generated stylesheet
import nibConfig from "@nibcss/config"; // the resolved nibcss.config.tsWith webpack and Rspack the plugin also appends the runtime to your client entry, so a project with no
provider still works. With Vite, hand the config to your framework's bindings —
<NibProvider {...nibConfig}>, app.use(Nib, nibConfig), setupNib(nibConfig).
3. Options#
Everything about styling lives in nibcss.config.ts. These are the build-only decisions:
Option | Default | What it does |
|---|---|---|
|
| compile static attributes into classes. |
|
| webpack/Rspack: append the runtime to the client entry |
|
| mount the diagnostics overlay in dev (needs |
| auto-detected | path to the config file |
| project sources | extra globs to scan, or skip |
| — | config fields that win over the file |
|
|
|
| auto-detected | tell the plugin which compiler is the browser bundle |
nib({
include: ["src/**/*.{ts,tsx,html}", "docs/**/*.md"],
exclude: ["**/*.stories.tsx"],
override: { debug: process.env.CI !== "true" },
})What the build generates#
Path | What it is |
|---|---|
| the stylesheet, imported as |
| the resolved config, as a module and as data |
| a real package re-exporting it, so |
| webpack/Rspack: the runtime entry appended to the client bundle |
| dev only, with |
Everything lives inside node_modules, so there is nothing to add to .gitignore.
Dev-server behaviour#
- A config edit is applied to the page you have open — no reload, no restart. The build pushes the new config and the new stylesheet over the dev channel, and the page swaps the stylesheet and re-resolves its elements. Rules the change removes go away too.
- A source edit is a normal hot update.
- Diagnostics are served at
/__nib/warningsand pushed to the overlay as you type.
Every generated file opens with /* eslint-disable */ and an @generated marker, so linters and
reviewers leave them alone.
Common pitfalls#
- Expecting Turbopack support — it has no plugin API yet; run Next with
--webpack. - Setting
rewrite: falseand wondering why production ships attributes instead of classes. - A monorepo where the plugin picks the wrong config: point
configat the right file. - Scanning
node_modulesthrough a wideincludeglob — it is skipped on purpose; keep it that way.