Repository navigation
Add weft_shop, a streamed storefront example, and fix the Weft bugs it found - #14
Merged
Merged
Conversation
- weft: a pending Suspense boundary whose content arrived after hydration started, and suspended as it hydrated (an entrypoint's chunk still loading), rendered its content again after the server's, which stayed unhydrated. It now stays dehydrated until what it waits on settles. - weft_signals: the hooks gave useSyncExternalStore no server snapshot, so an entrypoint reading a signal failed to render on the server (error 15) and the page fell back to client rendering. - weft_dom: hydration compared style values as written, while browsers read them back normalised (hsl as rgb, -0% as 0%), warning about styles that were the same. autoFocus now focuses an element rendered after the page loaded. New aria and form props. - weft_server: Navigation.navigate, load and refresh resolved when their transition started, not once the new page was on screen as documented. Bootstrap.start takes a ~signal that stops the page. - weft_vite_plugin: the harness keeps cookies as a browser does, and opening a page closes the one before (its root unmounted), so a page left open by one test can't act in the next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A larger example than weft_notes, built to exercise how Weft's features work together with the latency of real services in between: - Home and category pages are server-driven: a tree of CMS blocks kept as data, personalised per shopper and changed at runtime. Each block streams under its own boundary, inside a BlockFrame entrypoint (an error boundary with Retry, refetched from its own route, polled when live), and keeps its state when a refresh moves it. - Every slow call waits on Latency: seeded random delays and failures in dev and `vp run start`, gates the tests open in `manual` mode. - Catalog filters as navigations, "Load more" through an RPC returning server-rendered cards, search suggestions cancelling older requests, variant offers refetched by themselves, a cart in a signals store handed down by context, portals, cookie sessions through servy middleware, a three-step checkout and a self-refreshing order page. Tests: 45 scenario tests through the plugin's harness, and 16 Playwright tests against the build (one project with gated latency, one with seeded random latency and failures), now in CI's browser job. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A route answering a navigation's payload request with a redirect showed
the redirected page under the URL that was asked for. Now:
- weft_server: Decoder.fetch resolves with `fetched` ({stream, url?}),
webFetch reporting where the browser's fetch was redirected to, and
Decoder.Latest.fetchElement with the element and its URL. Navigation
records that URL, navigate passes it to onNavigate, and a redirected
load or refresh calls the new ~onRedirect (Bootstrap replaces the
history entry).
- weft_vite_plugin: the harness's fetch follows same-origin redirects
as a browser does (bounded, 303 as GET, manual/error respected),
setting url/redirected on its responses; a redirected first page is
at the URL it led to (WeftTesting.url).
- weft_shop: /account (signed out) redirects to /signin?next=/account
again, and an empty cart's /checkout to /cart, with harness and e2e
tests of the URL after following a link.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
A larger Weft example than
weft_notes, built to exercise how Weft's features work together, with the latency of real services in between, and to find bugs the smaller examples don't. It found six; each is fixed here with a regression test (checked to fail without the fix) and a changeset.examples/weft_shop("Loom & Co.")Suspenseboundary inside aBlockFrameentrypoint (error boundary with Retry, refetched from its own route, polled when live), and keeps its state when a refresh moves it.Latency.res): seeded random delays and failures invp dev/vp run start; gates the tests open, in the order they choose.Rpc.callwith a signal), variant offers refetched by themselves, a cart in asignalsstore handed down by context, portals (drawer, sign-in dialog), cookie sessions through servy middleware, a three-step checkout, a self-refreshing order page.Framework fixes
weft: a pending boundary whose content arrived after hydration started, and suspended while hydrating (an entrypoint's chunk still loading), rendered its content a second time after the server's, which stayed unhydrated.weft_signals: the hooks gaveuseSyncExternalStoreno server snapshot, so an entrypoint reading a signal couldn't render on the server (error 15).weft_dom: hydration comparedstyleas written, not as the browser reads it back (hsl→rgb,-0%→0%), warning about identical styles;autoFocusdidn't focus elements rendered after page load. Also new aria and form props.weft_server:Navigation.navigate/load/refreshresolved when their transition started, not once the new page was on screen as documented.weft_server: a navigation the server redirected recorded and pushed the URL it asked for, not the redirect's final URL.weft_vite_plugin): no cookies, no redirects, and pages from earlier tests stayed mounted and acted in later ones. It now keeps cookies, follows redirects, and closes a page when the next opens (Bootstrap.start ~signal).Known follow-ups, not in this PR
useRefetchable'srefetchresolves when its render starts (documented);BlockFrame's Retry waits onisPendingbefore resetting its error boundary.document.titleisn't updated on navigation (already in the server components plan's follow-ups).Checklist
pnpm run check,pnpm run buildandpnpm run testpasspnpm changeset) if a published package changed🤖 Generated with Claude Code