examples/nextjs: server components + Suspense streaming for home & header#3810
Merged
fredericoo merged 4 commits intoJun 24, 2026
Merged
Conversation
Author
|
I have signed the CLA! |
Move the Next.js example's components/ and lib/ directories from under app/ to the project root, and replace relative imports with the @/ path alias. No behavior change — imports only, plus pure file moves. Verified: tsc --noEmit and next build both pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ader Restructure the Next.js example toward better App Router patterns (and toward Cache Components): - Extract CartButton as a client island so Header can be a server component that fetches its own collections. - Split the home product grid into a static shell + a Suspense-streamed ProductList with a skeleton fallback. - Drop force-dynamic and the blocking cart/collections fetch from the root layout; data is colocated in the components that need it and the request-scoped storefront client stays React.cache()-memoized. - Cart is seeded client-side by CartProvider's built-in fetch instead of a blocking server seed, keeping the layout non-blocking. See the Providers TODO for the promise + React.use() path that needs core support. - Load standard-actions.js with afterInteractive so next/script injects it via an effect rather than rendering a <script> React 19 won't execute on the client. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4a67169 to
7cbb1cf
Compare
Add blank line between import groups to satisfy oxfmt --check. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
andguy95
approved these changes
Jun 18, 2026
fredericoo
approved these changes
Jun 24, 2026
fredericoo
left a comment
Contributor
There was a problem hiding this comment.
thank you for the contribution! it all works as expected. looks like our generated code was misusing next a little bit
Contributor
|
lol i read it backwards, thought it was to merge this one first. will fix it on my end! |
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.
WHY are these changes introduced?
The Next.js example used patterns that block streaming and aren't idiomatic App Router: a
"use client"header with prop-drilled data, aforce-dynamiclayout that blocks on cart + collections before anything paints, and a home page that awaits all products before rendering the hero.This restructures the example toward idiomatic App Router data-fetching and streaming — and toward
cacheComponents— without touching the@shopify/hydrogencore.WHAT is this pull request doing?
CartButtonsoHeaderis a server component that fetches its own collections — no"use client"on the header, no prop-drilling from the layout.ProductListShell+ a<Suspense>-streamedProductListwith a skeleton fallback, so the hero paints before products resolve.force-dynamicand the blocking cart/collections fetch from the root layout. Data is colocated in the components that need it;getStorefrontClientstaysReact.cache()-memoized so shared calls dedupe within a request.CartProviderseeds client-side via its built-in fetch instead of a blocking server seed, keeping the layout streamable. AProvidersTODO documents the promise +React.use()path that would restore an SSR'd cart count (needs a core change, deferred).HOW to test your changes?
pnpm run dev:nextpnpm run check(format, lint, typecheck, test) passes.Follow-ups (toward Cache Components)
Header's collections in<Suspense>so the nav shell doesn't block the layout (and won't taint the route undercacheComponents).cacheComponents+use cacheon catalog fetches — requires splittingheaders()out ofgetStorefrontClientso catalog queries (no per-request input) become cacheable, separate from cart / buyer-IP (dynamic).Checklist