What Framework v0.11.4
Patch release. All 14 packages move to 0.11.4 together (fixed-group release). Three production-surfaced fixes, plus the devtools/MCP prod-leak hardening carried over from Unreleased. No API changes. 0.11.3 shipped an exports-map packaging regression that broke real consumers, so this patch is warranted for that alone.
Fixed
-
core: a reactive
() => cond ? <Component/> : <element>thunk that is the direct child of an element no longer stacks copies of the component branch on repeated toggles. A component realizes to aDocumentFragmentbounded by comment markers (<!--c:start--> … <!--c:end-->). The single-node "replace" fast path inreconcileInserttreated that fragment as one node and calledreplaceChild(fragment, current)— but inserting a fragment moves its children into the DOM and leaves the fragment empty, so the value stored as the newcurrentno longer referenced the real nodes. The next switch away could not find/remove them, and each return appended another copy (a production dashboard stacked four empty-states).DocumentFragmentvalues are now excluded from the fast path and flow throughvaluesToNodes, which flattens and tracks each child for correct removal. Distinct from the 0.11.3 thunk-in-array-child fix and the 0.11.2 component-swap fix. -
packaging: every public package export resolves again under
require()/createRequire().resolve(), not onlyimport()— fixes a 0.11.3 regression. In 0.11.3,what-react's subpath exports were rewritten from plain strings (which resolve under every condition) to conditional objects listing onlytypes+import, with norequire/defaultfallback. The CJS resolver has noimportcondition, socreateRequire(...).resolve('what-react')threwERR_PACKAGE_PATH_NOT_EXPORTED, breaking a real consumer'svite.config+ Vitest. Every public package's conditional exports entry now ends with adefaultcondition → all 37 public subpaths across the 14 packages resolve underrequire()as well asimport(). -
devtools-mcp: the Vite plugin no longer crashes
vite devwhen the optionalwhat-devtoolspeer is not installed. With the peer absent, Vite's dev transform could not resolve the bootstrap's bareimport … from 'what-devtools'and the dev server died.what-devtoolsis now a formally optional peer; the plugin probes for it up front and degrades gracefully — injects nothing + logs one clearconsole.info— instead of crashing dev. -
devtools-mcp: the DevTools/MCP client can no longer leak into a production build. (PR #19) The Vite plugin now gates
resolveId/load/transformIndexHtmlon the resolved Vitecommand(not justapply: 'serve'), and the injected bootstrap wraps its side effects inif (import.meta.env.DEV)so a prod build contains zero devtools/MCP code however the plugin is wired.
Verified
- New regression tests:
reactive-thunk-branch-switch.test.js(toggle a direct-child thunk between a bare component and an element/component/null; exactly one copy after repeated cycles — fails on 0.11.3, passes now) andvite-plugin-missing-peer.test.js(no injection + one notice + no throw when the peer is unresolvable). - New hygiene guard in
check-publish-surface.mjsexercisescreateRequire().resolve()for every public exports subpath across all 14 packages, so an exports map can never silently drop its CJS entry point again. - Full suite green (1440 tests) plus the adversarial stress suite. All release gates pass:
hygiene:publish,build,check:size(within budget),test:prod,smoke:scaffold,bench:gate.createRequire().resolve('what-react')confirmed working against the published 0.11.4 package.