---
title: Loading and preloading
description: Keep catalog and payment interactions fast without losing package code splitting.
sidebar:
  order: 3
---

import CodeBlock from "blume/components/content/CodeBlock.astro";
import lazyPaymentRecipe from "../../recipes/lazy-payment.tsx?raw";

Separate entry points keep Stripe out of catalog pages.

## Route-level split

<CodeBlock code={lazyPaymentRecipe} lang="tsx" />

## Preload on intent

```tsx
import type { LockerverseCatalog } from "@lockerverse/sdk/checkout";

let paymentModule: ReturnType<typeof importPayment> | undefined;

function importPayment() {
  return import("@lockerverse/react/payment");
}

export async function preloadPayment(catalog: LockerverseCatalog) {
  paymentModule ??= importPayment();
  const { preloadLockerversePayment } = await paymentModule;
  return preloadLockerversePayment(catalog);
}
```

Call `preloadPayment(catalog)` on checkout `pointerenter`, `focus`, or when the
cart becomes valid. The browser reuses both the payment module and the Stripe
load when React renders payment. `LockerverseDonateLauncher` does this
automatically when its dialog opens.
