Server-Side Rendering (SSR) Differences with PWA Kit
PWA Kit and Storefront Next implement SSR, but with fundamentally different architectures that reflect their respective technology stacks. PWA Kit’s SSR approach gives developers explicit control through Express and React Query, with optional partial hydration via Islands. Storefront Next uses React Router 7’s built-in SSR with automatic streaming, middleware chains, and loader-based data fetching. Storefront Next’s approach reduces boilerplate and provides better streaming performance, while the PWA Kit approach offers more granular control over hydration timing.
| Aspect | PWA Kit | Storefront Next |
|---|---|---|
| SSR Runtime | Express server with runtime.render | React Router 7 framework mode |
| Data Hydration | React Query cache serialization | Promise streaming with use() hook |
| Middleware | Express middleware | React Router middleware chain |
| Partial Hydration | Island component with strategies | Suspense boundaries with createPage |
| Server Context | useServerContext() hook | Context from middleware chain |
| Code Splitting | @loadable/component | React Router’s automatic splitting |
| Cache Control | Manual via res.set() | Via HTTP response from middleware |
PWA Kit:
- Express receives request.
- React tree renders.
- React Query hooks execute during render.
- Data fetched, components re-render with data.
- Query cache serialized to HTML.
- Client hydrates with cached data.
Storefront Next:
- React Router receives request.
- Middleware chain runs (auth, config, i18n).
- Loaders execute, return promises.
- React renders,
use()unwraps promises. - HTML streams as promises resolve.
- Client hydrates, clientLoader runs.
PWA Kit offers fine-grained control with Island:
Storefront Next uses Suspense boundaries:
-
useServerContext vs. Middleware: Server-side logic like setting cache headers moves from component hooks to middleware or loaders.
-
React Query vs. Loaders: Data fetching moves from hooks inside components to loader functions exported from route files.
-
Island vs. Suspense: Partial hydration with Island becomes Suspense boundaries with
createPage. -
Express routes vs. Resource routes: Custom API endpoints move from Express handlers to React Router resource routes.