Lazy Loading
As an application grows, downloading all route code on the initial load can increase startup time, including code for routes a user does not visit.
Lazy loading splits code into separate files and downloads a file when the user navigates to its route.
Basic Lazy Loading
Use lazy() to lazy-load a route component. Pass it a function that returns a dynamic import() for the component file.
import { defineRoutes, lazy } from 'retend/router'; // This component is included in the main initial download const Home = () => <div>Home</div>; // This component is separated into its own file and downloaded only when needed const SettingsLazy = lazy(() => import('./views/Settings')); const routes = defineRoutes([ { path: '/', component: Home }, { path: '/settings', component: SettingsLazy }, ]);
Exporting your Component
The component passed to lazy() must be the file’s default export.
// views/Settings.tsx // You can still use local helper components function SettingsForm() { return <form>...</form>; } // But the component you want to lazy-load MUST be the `default` export export default function SettingsView() { return ( <div class="settings"> <h1>Account Settings</h1> <SettingsForm /> </div> ); }
Lazy Loading Nested Routes
Lazy loading also applies to nested routes. The parent layout, child pages, or both can be lazy-loaded.
import { defineRoutes, lazy, Outlet } from 'retend/router'; const DashboardLayout = () => ( <div> <h1>Dashboard</h1> <Outlet /> </div> ); // The child page is lazy-loaded const UserProfileLazy = lazy(() => import('./views/dashboard/UserProfile')); const routes = defineRoutes([ { path: '/dashboard', component: DashboardLayout, children: [{ path: 'profile', component: UserProfileLazy }], }, ]);
Lazy Subtrees (Advanced)
For applications with many routes, the route configuration itself can become large.
Lazy subtrees split the routing configuration so a section’s routes are downloaded when the user enters that section.
Step 1: Create the Subtree File
Create a separate file that exports one route configuration as its default export:
// finance.routes.ts import { defineRoute, lazy } from 'retend/router'; import FinanceDashboard from './views/FinanceDashboard'; // The path MUST match where it will be mounted in the parent router export default defineRoute({ path: '/finance/:accountId', component: FinanceDashboard, children: [ { path: 'reports', component: lazy(() => import('./views/Reports')), }, { path: 'invoices', component: lazy(() => import('./views/Invoices')), }, ], });
Step 2: Connect it to the Main Router
In the main route file, set subtree instead of component or children, and wrap the import in lazy():
// index.routes.ts import { defineRoutes, lazy } from 'retend/router'; const routes = defineRoutes([ { path: '/', component: Home }, { path: '/finance/:accountId', // The entire finance section (routes and components) loads on demand subtree: lazy(() => import('./finance.routes.ts')), }, ]);
Lazy loading can reduce the initial JavaScript required as the number of routes grows.