Plumeria 16.4
2026-07-22
Plumeria v16.4 reworks @plumeria/inspector to use export conditions for environment separation. The inspector now costs exactly 0KB in production — no runtime guard, no empty component, no client chunk at all.
What changed
Previously, @plumeria/inspector shipped a single entry point with a runtime process.env.NODE_ENV check and an optional production prop:
// Before (16.1–16.3)
import { Inspector } from '@plumeria/inspector';
<Inspector /> // dev only (runtime guard)
<Inspector production={true} /> // force in productionThis worked, but the full inspector module was still bundled and shipped to the client in production — even though it rendered null. The 'use client' directive in the entry caused Next.js to emit a client chunk regardless.
How it works now
The package now declares development and production export conditions in its package.json:
"exports": {
".": {
"development": "./dist/index.js",
"production": "./dist/index.noop.js",
"default": "./dist/index.js"
},
"./production": {
"default": "./dist/index.js"
}
}@plumeria/inspector— In development, webpack resolves thedevelopmentcondition and loads the full inspector. In production, theproductioncondition resolves toindex.noop.js, a minimal no-op module that intentionally omits the'use client'directive. Without a client entry, the bundler never generates a client chunk — the inspector is completely absent from the production build.@plumeria/inspector/production— Always resolves to the full inspector, for staging, demos, or documentation sites that need the inspector in production.
The default field falls back to the full inspector for bundlers that don't support export conditions, where the runtime NODE_ENV guard inside index.tsx still prevents rendering.
Migration
The production prop has been removed. If you were using it, switch to the /production subpath:
-import { Inspector } from '@plumeria/inspector';
+import { Inspector } from '@plumeria/inspector/production';
-<Inspector production={true} />
+<Inspector />For development-only usage, no changes are needed — import { Inspector } from '@plumeria/inspector' continues to work as before.
Results
| Environment | Inspector chunk | Badge |
|---|---|---|
| Production / top page | 0KB (eliminated) | None |
| Production / inspector docs | Loaded (/production subpath) | ✅ |
| Development / all pages | Loaded | ✅ |
Fixes
16.4.2 (Jul 24, 2026)
- Fix: fix error occurring with dynamic props
16.4.1 (Jul 24, 2026)
- Fix: dev-only cascade divergence in
@plumeria/turbopack-loaderwhere the winning style depended on module compile order
In development the Turbopack loader accumulates every module's rules into one shared stylesheet, appending only the rules it does not already contain. optimizer() runs per module, so the "@media last" ordering that production establishes in a single global pass was never re-applied across the accumulated file.
That mattered because @media { padding } and base paddingTop carry the same specificity — one :not(#\#) each — and overrideLonghand treats a nested at-rule as its own cascade scope, so neither eliminates the other. Nothing resolves that pair; it falls through to cascading order. Production is stable only because postcss-combine-media-query always hoists @media to the end. Development had no such guarantee: when an @media rule was inserted by an earlier-compiled module and a conflicting base longhand was appended later, the base rule won in development while production resolved it to the @media rule.
Because the write order is decided by which module wins the file lock, the outcome was not even stable. Across 100 independent trials it diverged in ~57% of cases, and roughly half of them flipped between two identical runs.
orderMediaLast in @plumeria/utils now reorders the accumulated rule set before it is written, so @media always lands last and development matches the order production ships. Media detection is a single-pass character scan that skips leading whitespace and block comments, so a rule preceded by a comment — such as the placeholder the Next.js plugin writes when it resets the shared file — is still classified correctly.
16.4.0 (Jul 21, 2026)
- Feat: zero-cost production inspector via export conditions
- Breaking: remove
productionprop — use@plumeria/inspector/productionsubpath instead
Thanks for building with Plumeria! If you have any feedback or questions, please let us know on GitHub Discussions or GitHub Issues.