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?