From ce8fedee0b5fbbb97af7b021101926d8c0fc8ea9 Mon Sep 17 00:00:00 2001 From: Bendik Aagaard Lynghaug Date: Tue, 8 Sep 2026 18:57:51 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20Phase=203=20complete=20=E2=80=94=20toSt?= =?UTF-8?q?ream,=20prefetch,=20lazy=20routes,=20devtools,=20codemod?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_014NgfSjHE11oFpoSnLVKLXd --- docs/v8.md | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/docs/v8.md b/docs/v8.md index e5b8a02..56f9e32 100644 --- a/docs/v8.md +++ b/docs/v8.md @@ -31,9 +31,18 @@ everything new lives under `packages/`. - `raw.js` — mark pre-encoded strings (works with both renderers) - `packages/component` — `@choojs/component`: ← nanocomponent 6.6.0 + on-load 3.4.1 as ES classes; the future island/hydration boundary. +- `packages/devtools` — `@choojs/devtools`: window.choo with live state, + event log, timings via PerformanceObserver, copy(); no-op on the server. +- `packages/migrate` — `@choojs/migrate`: the `choo-migrate` codemod. + Regex-based on purpose: converts simple top-level CJS to ESM, remaps + specifiers (choo → @choojs/core, nanohtml → @choojs/html, …), points + retired packages at their replacements, and reports everything it + refuses to guess at. - `examples/counter` — the isomorphic proof: one app module, mounted zero-build in the browser via import map (`index.html`), string-rendered in Node (`render.js`). +- `examples/streaming` — streaming SSR demo server + (`node examples/streaming/server.js`). ## Status vs the modernization plan @@ -59,14 +68,25 @@ apps by @choojs/component caching (proxy nodes skip unchanged subtrees), and the number to beat if Phase 3 explores keyed-hole optimizations. Server string rendering is on par with nanohtml v1 (~13k ops/s, within 6%). happy-dom numbers in bench/render.js are indicative only. -- [ ] Phase 3: v8 wiring (`toStream`, devtools, codemod). Includes the - answer to choojs/choo#653 (async/lazy routes): route handlers may - resolve lazily via native import(); browser renders previous tree - or a loading view until resolution, server awaits inside toStream - (toString stays sync and fails loudly). Deliberately deferred until - toStream exists so the SSR half ships with the browser half — the - missing server story is what stalled #653. API shape (thenable - handler vs lazy() wrapper vs loader-view option) goes to the RFC. +- [x] Phase 3: v8 wiring, all shipped together: + - `toStream(location, state)` — web-standard ReadableStream of + UTF-8; `new Response(stream)` on web servers, + `Readable.fromWeb(stream).pipe(res)` on Node. Progressive: the + server tag now builds a parts list, so promises/async iterables + in child position flush the shell first and stream the rest in + document order (proven byte-level and in real Chromium). + - `state.prefetch` — stores push promises during init; toStream + awaits them before rendering; toString refuses them loudly. + - `lazy(loader, loadingView?)` — the answer to choojs/choo#653, + both halves at once: browser renders the loading view (or holds + the current tree) until the dynamic import lands, server awaits + it in toStream; toString fails with guidance. Views cache after + first load. + - `@choojs/devtools` and the `choo-migrate` codemod (validated by + migrating choo's own v7 example and running the result on v8). +- [ ] Phase 3 follow-ups for the RFC: API shape feedback on lazy() + (thenable handlers vs wrapper), serializing streamed state for + hydration of async holes (bankai v10 territory). - [ ] Phase 4: bankai v10 (Vite 8/Rolldown shell, SSR middleware, 103 Early Hints, service worker, precompression) - [ ] Phase 5: docs, examples, launch