Remix loader system (loader, defer, Suspense)
FrontWing leverages Remix loaders for data fetching, enabling server-side rendering (SSR) and smooth client hydration. The architecture is built around performance-first SSR with progressive data loading.
Benefits
π§ SSR-first architecture for fast TTFB
π€ Lazy loading non-critical data (e.g. associations, reviews)
π§Ό Clean separation of server and client logic
π Built-in caching (browser/server)
Example:
export async function loader({ params }: LoaderFunctionArgs) {
const product = await fetchProduct(params.slug);
return json({ product });
}
This data is then accessed on the client with:
const { product } = useLoaderData<typeof loader>();
defer()
and lazy loading with <Await>
defer()
and lazy loading with <Await>For improved performance, FrontWing uses defer()
and <Await>
to load secondary data lazily after the initial HTML is rendered.
Use case: On the Product Page, we fetch primary product data synchronously, while associations, attributes, and reviews are loaded asynchronously in the background.
export async function loader({ params }: LoaderFunctionArgs) {
return defer({
product: await fetchProduct(params.slug),
reviews: fetchProductReviews(params.slug), // no await
associations: fetchAssociations(params.slug),
});
}
On the client:
<Suspense fallback={<SkeletonReviews />}>
<Await resolve={data.reviews}>
{(reviews) => <ReviewList reviews={reviews} />}
</Await>
</Suspense>
Where to look in code
routes/product.tsx
β loader usingdefer()
and multiple fetchesProductPage.tsx
β uses<Await>
with<Suspense>
utils/api.server.ts
β functions fetching Sylius datacomponents/product/
β components that render async sections
Last updated
Was this helpful?