Deploying React AppsEntry 3 of 11

Lazy Loading Route Loaders with import()

When a lazy page also exports a loader, the route's loader must load that module with import() too, then call the loader from it.

Notes

  • Importing loader statically from the page file would pull the whole page into the main bundle, undoing the lazy loading.
  • Instead, the route's loader is a function that dynamically imports the module and calls its loader.
  • Pass the loader arguments through ({ params, request }) so dynamic routes still get their params.
  • The browser caches the module, so the loader and the lazy component share one download.

What / Why / When

What

Deferred loader code.

Why

Keeps the page and its data logic out of the main bundle.

When

Any lazy-loaded page that has a loader or action.

Code compare

React
// App.tsximport { lazy } from "react";import type { LoaderFunctionArgs } from "react-router";​const BlogPage = lazy(() => import("./pages/Blog"));const PostPage = lazy(() => import("./pages/Post"));​const router = createBrowserRouter([  {    path: "/",    element: <RootLayout />,    children: [      { index: true, element: <HomePage /> },      {        path: "posts",        children: [          {            index: true,            element: <BlogPage />, // wrapped in Suspense in Entry 4            loader: () => import("./pages/Blog").then((module) => module.loader()),          },          {            path: ":id",            element: <PostPage />,            loader: (args: LoaderFunctionArgs) =>              import("./pages/Post").then((module) => module.loader(args)),          },        ],      },    ],  },]);

Resolvers live in the route config, so put them in a lazy routes file. They're then downloaded with the feature.

Angular
// app.routes.ts{ path: 'posts', loadChildren: () => import('./posts/posts.routes').then((m) => m.POSTS_ROUTES) }
Angular
// posts/posts.routes.ts (separate chunk, including resolvers)export const POSTS_ROUTES: Routes = [  { path: "", component: BlogComponent, resolve: { posts: postsResolver } },  { path: ":id", component: PostComponent, resolve: { post: postResolver } },];

Quick reference

ReactAngular
loader: () => import('./Page').then(m => m.loader())Resolver inside a loadChildren routes file
loader: (args) => import(...).then(m => m.loader(args))ResolveFn receives route automatically