---
title: "Loaders"
slug: "loaders"
abstract: "Learn how loaders implement server-side data fetching in Angular apps using the Content SDK."
---
# Loaders

Loaders are the central engine of the Content SDK Angular implementation and the primary enabler of server-side data fetching from SitecoreAI. They function as server-side data resolvers, conceptually similar to Next.js's [`getServerSideProps`](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props) or server functions in [React Server Components](https://react.dev/reference/rsc/server-components).

The loader flow is built on [Angular route data resolvers](https://angular.dev/guide/routing/data-resolvers), but instead of defining separate functions for each resolver, loaders execute through the Content SDK wrapper `loaderResolver`. Out of the box, loaders populate the page and dictionary properties for a route. You can expand this logic to populate additional route properties when a request is processed by Angular SSR.

## Basic usage

You can define loaders on Angular routes by name:

```ts
{
  path: '**',
  component: PageComponent,
  resolve: {
    page: loaderResolver('page'),
    dictionary: loaderResolver('dictionary'),
  },
}
```

`loaderResolver` is the main entry point for loader logic and enforces the core design goal of strict server-side data fetching.

## Flow of execution

On the server, the execution flow is as follows:

1. `loaderResolver` retrieves the loader from the injectable loader registry by name.
2. It executes the loader or retrieves cached data from `loaderCache` depending on route, language, loader name, and other parameters.
3. It writes the loader result to Angular's `TRANSFER_STATE`, making the value available during client-side navigation without re-executing the loader.

In the browser, the execution flow is as follows:

1. `loaderResolver` attempts to read the loader result from `TRANSFER_STATE`.
2. If absent, it invokes a request to the loader-data-service Express.js middleware via `loader-data.service`.
3. The Express middleware retrieves the loader from the registry, executes it (or reads data from the `loaderCache`), and responds with the result.

Depending on the loader execution result type (`data`, `error`, or `notFound`), either the specified route property is populated, or `loaderResolver` invokes a redirect to the appropriate error or not-found page.

## Loader registry

Loaders are retrieved from a loader registry injected in `src/app.config.ts`:

```ts
import { LOADERS } from '../content-sdk/loaders';

providers: [
  // ...
  provideLoaderRegistry(LOADERS),
  // ...
]
```

Loader implementations are located in the `src/content-sdk/loaders` folder.

## Loader implementation

The following example shows the default page loader implementation:

```ts
import type { LoaderFn, Page } from "@sitecore-content-sdk/angular";
import {
  NotFoundNavigationError,
  getEditingPreviewData,
  splitLocaleFromPath,
} from "@sitecore-content-sdk/angular";
import scConfig from "../../../sitecore.config";
import { getClient } from "../client/sitecore-client";

/**
 * Page loader: fetches layout data from Sitecore for the current URL.
 * Uses imported config and getClient so this runs outside Angular injection context.
 */
export const pageLoader: LoaderFn<Page> = async (context) => {
  const previewData = getEditingPreviewData(context.requestContext);

  const locale =
    (context.params["locale"] as string | undefined) ||
    scConfig.defaultLanguage;

  const { nonLocalePath } = splitLocaleFromPath(
    context.url,
    scConfig.angular.locales,
  );

  const site = scConfig.defaultSite;

  const page = previewData
    ? await getClient().getPreview(previewData)
    : await getClient().getPage(nonLocalePath, { locale, site });

  if (!page) {
    throw new NotFoundNavigationError();
  }

  return page;
};
```

> [!note]
> Loaders must implement the `LoaderFn` contract. Loaders can execute outside of the Angular injection context and must not contain any `inject()` calls.

## Caching

The loader execution layer includes a caching mechanism to preserve loader result data. For configuration details, refer to Loader cache layer and tags revalidation.

## Link prefetching

Loaders normally fetch data on demand when a route resolver runs. Sitecore link fields rendered through `scRouterLink` and `scRichText` can prefetch a destination route's loader data before the user navigates there, so the resolver consumes a staged response instead of starting a fresh request. See [Link prefetching](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/link-prefetching.html) for configuration options.

## Middleware considerations

Personalize, multisite, and SXA redirect support is implemented through Express.js middleware handlers in the Angular Content SDK.

Because the Angular Content SDK uses a loaders-centric architecture, middleware handlers are invoked on regular server requests and browser navigation requests that resolve loader data for the client side. For a full list of the available middleware plugins and their configuration options, see [Middleware plugins](https://doc.sitecore.com/sai/en/developers/content-sdk/angular/1x/middleware-plugins.md "Middleware plugins").