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?
