Performance: Protected routes with loaders
This affects the initial page load speed and user interaction responsiveness by controlling data fetching and access before rendering.
import { json } from '@remix-run/node'; import { useLoaderData, Navigate } from '@remix-run/react'; export async function loader({ request }) { const user = await getUserFromSession(request); return json({ user }); } export default function ProtectedPage() { const { user } = useLoaderData(); if (!user) { return <Navigate to='/login' replace />; } return <div>Welcome, {user.name}</div>; }
import { redirect, json } from '@remix-run/node'; import { useLoaderData } from '@remix-run/react'; export async function loader({ request }) { const user = await getUserFromSession(request); if (!user) { throw redirect('/login'); } return json({ user }); } export default function ProtectedPage() { const { user } = useLoaderData(); return <div>Welcome, {user.name}</div>; }
| Pattern | DOM Operations | Reflows | Paint Cost | Verdict |
|---|---|---|---|---|
| Blocking loader with redirect on server | Minimal DOM nodes | 1 reflow after data load | Delays initial paint by 100-300ms | [X] Bad |
| Loader returns data immediately, client redirects if unauthenticated | Minimal DOM nodes | 1 reflow on initial render | Paint starts immediately, faster LCP | [OK] Good |
throw redirect() to redirect users.throw redirect('/login'), which is the correct Remix pattern.import { redirect } from '@remix-run/node';
export async function loader({ request }) {
const user = await getUser(request);
if (!user) {
throw redirect('/login');
}
return { user };
}user is falsy (not logged in), the loader throws redirect('/login').import { redirect } from '@remix-run/node';
export async function loader({ request }) {
const user = await getUser(request);
if (!user) {
return redirect('/login');
}
return { user };
}throw redirect(), not return it.import { redirect } from '@remix-run/node';
export async function loader({ request }) {
const user = await getUser(request);
if (!user) {
throw redirect('/login');
}
const profile = await getUserProfile(user.id);
return { user, profile };
}Pass the test and this pattern moves unknown