Skip to content

feat: add development diagnostics with separate development and production builds - #236

Merged
dangreen merged 2 commits into
mainfrom
feat/devtools-event
Sep 7, 2026
Merged

dangreen merged 2 commits into
mainfrom
feat/devtools-event

Conversation

@dangreen

@dangreen dangreen commented Sep 7, 2026 •

Copy link
Copy Markdown
Member

What

Development-only diagnostics across the core packages, delivered through a development build that sits next to the production build.

Warnings, console.warn, development build only:

  • agera: a signal written while a computed is evaluating; an effect or an effect scope created while a computed is evaluating; a lifecycle listener attached to a signal that is not mountable.
  • store: StaticHydrator finds no dehydrated value for a key.
  • query: a cache key parameter is a function or a symbol (it serializes to null); a shard name registered twice.
  • router: a path function called without a required parameter.
  • intl: a message key missing in the loaded namespace; a params placeholder whose value is undefined.

kida's inject keeps its "outside of injection context" check in development only, production falls through to the TypeError from context.get. DependencyNotFound carries the full message in development and the token name in production.

How

  • Every check is behind import.meta.env.DEV, which Vite replaces statically in library mode. agera, kida, store, query, router and intl build twice, NODE_ENV=development and NODE_ENV=production, into dist/index.development.js and dist/index.production.js. This mirrors the setup kida had before feat(nanoviews,kida): migrate kida and nanoviews to agera #52.
  • publishConfig.exports gained the development and production conditions, default is production. Vite and webpack pick by mode, bare Node, Bun, esbuild and Rollup get production, node -C development opts in. No node condition: the old one mapped Node to the development build.
  • Development-only code is a light wrapper over the production path, so the production build stays byte-identical to main after minification. Verified through Vite, webpack, esbuild and Rollup.
  • Types come from one root vite-env.d.ts included through files in the root tsconfig.json, so dependent packages compiling these sources see import.meta.env.
  • size-limit measures dist/index.production.js. kida and store moved to .size-limit.js with modifyEsbuildConfig defining import.meta.env.DEV as false: size-limit resolves workspace dependencies to TypeScript sources, where esbuild cannot fold the flag. The other packages keep JSON, size-limit ignores their peers.
  • Benchmarks import ../agera/dist/index.production.js.
  • The Next.js examples' integration mode (NANO_KIT_DEV) compiles the package sources through transpilePackages: it now skips the type check like the other example builds and defines import.meta.env.DEV as false through DefinePlugin, webpack turned import.meta.env into undefined in the server build otherwise.

Sizes

Production limits are back at the main values in every package. kida and store lost the inject message: All publics 4.7 → 4.65 kB and 5.95 → 5.9 kB Brotli.

Tests

New cases for every warning in agera, query, store and intl, and for the router path builder. The agera case for a write inside a notified effect guards the 'compute' in activeSub discriminator: notify() clears WatchingFlag on a queued effect, so the flag cannot tell a computed from an effect.

…ction builds

Warnings, only in the development build: a signal written or an effect created while a computed is evaluating (agera), a lifecycle listener on a signal that is not mountable (agera), a missing dehydrated value (store), a cache key parameter that serializes to null and a shard registered twice (query), a path built without a required parameter (router), a missing message and a parameter without a value (intl). `inject` outside of an injection context and `DependencyNotFound` keep their full messages in development only.

The diagnostics sit behind `import.meta.env.DEV`. agera, kida, store, query, router and intl now build twice into `dist/index.development.js` and `dist/index.production.js`, and `exports` selects them through the `development` and `production` conditions, `default` is production. size-limit measures the production build, kida and store define the flag for the workspace sources they bundle.
@dangreen
dangreen force-pushed the feat/devtools-event branch from 7bd7abf to 4319790 Compare September 7, 2026 13:37
@codecov

codecov Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.17647% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.85%. Comparing base (a91f3a1) to head (8f4d89b).

Files with missing lines Patch % Lines
packages/query/src/cache.ts 85.71% 0 Missing and 2 partials ⚠️
packages/intl/src/format/params.ts 88.88% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #236      +/-   ##
==========================================
+ Coverage   82.75%   82.85%   +0.10%     
==========================================
  Files          98       98              
  Lines        2465     2497      +32     
  Branches      521      533      +12     
==========================================
+ Hits         2040     2069      +29     
  Misses        315      315              
- Partials      110      113       +3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…s example integration builds

The integration mode compiles the package sources through `transpilePackages`. Their `import.meta.env.DEV` is typed by the root declaration the examples do not see, and webpack turns `import.meta.env` into `undefined` in the server build, so prerendering failed. Skip the type check like the other example builds and define the flag as `false`, the production value.
@dangreen
dangreen merged commit 39be996 into main Sep 7, 2026
10 checks passed
@dangreen
dangreen deleted the feat/devtools-event branch September 7, 2026 14:23
@github-actions github-actions Bot mentioned this pull request Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant