//
Search across all documentation pages
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥
import { prefetchDNS, preconnect, preload, preinit } from "react-dom";
function App() {
// Eagerly load and execute a script
preinit("https://cdn.example.com/analytics.js", { as: "script" });
// Preload a font (download early, use later)
preload("https://fonts.example.com/inter.woff2", {
as: "font",
type: "font/woff2",
crossOrigin: "anonymous",
});
// Preload a stylesheet
preload("https://cdn.example.com/theme.css", { as: "style" });
// DNS prefetch for a domain you will request later
prefetchDNS("https://api.example.com");
// Preconnect (DNS + TCP + TLS) for a domain you will request soon
preconnect("https://images.example.com");
return <main>{/* ... */}</main>;
}When to reach for this: Use these APIs to improve initial page load and client-side navigation performance by telling the browser about resources it will need before React renders the components that use them.
// A page that preloads all critical resources for optimal performance
import { Suspense } from "react";
import { preload, preinit, preconnect } from "react-dom";
// Preload critical resources at the module level (runs once on import)
preconnect("https://api.myapp.com");
preload("/fonts/brand-bold.woff2", { as: "font", type: "font/woff2", crossOrigin: "anonymous" });
preload("/fonts/brand-regular.woff2", { as: "font", type: "font/woff2", crossOrigin: "anonymous" });
function CriticalCSS() {
return (
<>
{/* React deduplicates and manages stylesheet loading order via precedence */}
<link rel="stylesheet" href="/styles/reset.css" precedence="reset" />
<link rel="stylesheet" href="/styles/base.css" precedence="default" />
<link rel="stylesheet" href="/styles/theme.css" precedence="high" />
</>
);
}
function HeavyWidget() {
// Preinit a script needed by this widget
preinit("/scripts/chart-library.js", { as: "script" });
return (
<div className="widget">
<h2>Sales Dashboard</h2>
<div id="chart-container" />
</div>
);
}
function ImageGallery({ images }: { images: { src: string; alt: string }[] }) {
// Preload the first few images for instant display
images.slice(0, 3).forEach((img) => {
preload(img.src, { as: "image" });
});
return (
<div className="grid grid-cols-3 gap-4">
{images.map((img, i) => (
<img
key={i}
src={img.src}
alt={img.alt}
loading={i < 3 ? "eager" : "lazy"}
/>
))}
</div>
);
}
export default function DashboardPage() {
return (
<>
<CriticalCSS />
<title>Dashboard | MyApp</title>
<header>
<h1>Dashboard</h1>
</header>
<Suspense fallback={<p>Loading widget...</p>}>
<HeavyWidget />
</Suspense>
<Suspense fallback={<p>Loading gallery...</p>}>
<ImageGallery
images={[
{ src: "/images/product-1.jpg", alt: "Product 1" },
{ src: "/images/product-2.jpg", alt: "Product 2" },
{ src: "/images/product-3.jpg", alt: "Product 3" },
{ src: "/images/product-4.jpg", alt: "Product 4" },
{ src: "/images/product-5.jpg", alt: "Product 5" },
{ src: "/images/product-6.jpg", alt: "Product 6" },
]}
/>
</Suspense>
</>
);
}What this demonstrates:
preconnect establishing early connections to API domainspreload for fonts at the module level (before any component renders)<link rel="stylesheet" precedence={}> for ordered, deduplicated CSSpreinit eagerly loading a third-party script inside a componentpreload for images to speed up above-the-fold renderingpreload(href, options) -- Inserts a <link rel="preload"> tag into the document. The browser downloads the resource at high priority but does not execute or apply it. Use for fonts, images, stylesheets, and scripts you will need soon.preinit(href, options) -- Downloads and executes/applies the resource immediately. For scripts, this means the script runs. For stylesheets, this means the CSS is applied. Use when you need the resource active right away.prefetchDNS(href) -- Inserts a <link rel="dns-prefetch"> hint. The browser resolves the domain name early. Cheapest option -- use when you might request from this domain.preconnect(href) -- Inserts a <link rel="preconnect">. The browser performs DNS + TCP + TLS handshake early. Use when you will definitely request from this domain soon.href.<link> tags in the HTML <head> and as early hints (103 Early Hints) if the server supports it.<link rel="stylesheet" precedence={}> tells React to manage the stylesheet. React will suspend rendering of the component until the stylesheet loads, preventing a flash of unstyled content.Preloading on hover (predictive):
"use client";
import { preload } from "react-dom";
import Link from "next/link";
function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
function handleMouseEnter() {
// Preload the page's CSS and hero image when user hovers
preload(`/styles${href}.css`, { as: "style" });
preload(`/images${href}-hero.jpg`, { as: "image" });
}
return (
<Link href={href} onMouseEnter={handleMouseEnter}>
{children}
</Link>
);
}Conditional preloading based on viewport:
"use client";
import { useEffect } from "react";
import { preload } from "react-dom";
function AdaptiveLoader() {
useEffect(() => {
const connection = (navigator as any).connection;
if (connection?.effectiveType === "4g") {
// Only preload heavy resources on fast connections
preload("/videos/hero.mp4", { as: "video" });
preload("/fonts/display.woff2", { as: "font", crossOrigin: "anonymous" });
}
}, []);
return null;
}Module-level preloading (runs on import):
import { preconnect, preload } from "react-dom";
// These execute when the module is imported, before any component renders
preconnect("https://cdn.example.com");
preload("https://cdn.example.com/critical.css", { as: "style" });
export default function Page() {
return <div>Content that needs cdn.example.com resources</div>;
}"react-dom".preload(href: string, options: { as: string; crossOrigin?: string; type?: string; fetchPriority?: "high" | "low" | "auto" }).preinit(href: string, options: { as: "script" | "style"; crossOrigin?: string; fetchPriority?: "high" | "low" | "auto"; nonce?: string }).prefetchDNS(href: string) and preconnect(href: string, options?: { crossOrigin?: string }) have minimal options.precedence attribute on <link rel="stylesheet"> is typed as string.preinit executes scripts immediately -- If the script has side effects or depends on DOM elements that have not rendered yet, it may fail. Fix: Use preload instead and add a <script> tag when the DOM is ready, or ensure the script handles missing DOM gracefully.preload must specify crossOrigin: "anonymous" even for same-origin fonts, per the Fetch spec. Fix: Always include crossOrigin: "anonymous" for font preloads.precedence is not managed -- If you omit precedence from a <link rel="stylesheet">, React does not deduplicate or suspend for it. Fix: Add precedence to all stylesheet links you want React to manage.| Approach | When to choose |
|---|---|
| React DOM preload APIs | React 19 built-in, works with SSR and client rendering |
HTML <link> in <head> template | Static resources known at build time |
Next.js <Script> component | Next.js projects needing script loading strategies |
@next/font / next/font | Next.js font optimization with automatic subsetting |
Manual document.createElement("link") | Rare cases needing programmatic control outside React |
| Resource hints via HTTP headers | Server-level optimization (103 Early Hints) |
preload downloads the resource at high priority but does not execute or apply itpreinit downloads and executes/applies the resource immediately (scripts run, CSS is applied)preload for resources you will need soon; use preinit when you need them active right awayprefetchDNS only resolves the domain name (DNS lookup) -- cheapest optionpreconnect performs DNS + TCP + TLS handshake -- more expensive but saves more timeprefetchDNS when you might request from a domain; use preconnect when you definitely will soonhrefpreload("/fonts/brand.woff2", {
as: "font",
type: "font/woff2",
crossOrigin: "anonymous", // required for all fonts
});You must include crossOrigin: "anonymous" even for same-origin fonts, per the Fetch spec.
function NavLink({ href, children }) {
function handleMouseEnter() {
preload(`/styles${href}.css`, { as: "style" });
preload(`/images${href}-hero.jpg`, { as: "image" });
}
return (
<a href={href} onMouseEnter={handleMouseEnter}>
{children}
</a>
);
}<link rel="stylesheet" precedence="default"> tells React to manage the stylesheetprecedence value are grouped together in <head><link> tags in the HTML <head> and as 103 Early Hints if the server supports ituseEffect(() => {
const conn = (navigator as any).connection;
if (conn?.effectiveType === "4g") {
preload("/videos/hero.mp4", { as: "video" });
preload("/fonts/display.woff2", {
as: "font",
crossOrigin: "anonymous",
});
}
}, []);preinit executes scripts immediately, which may fail if the script depends on DOM elements that have not renderedpreload instead and add a <script> tag when the DOM is readypreload(href: string, options: {
as: string;
crossOrigin?: string;
type?: string;
fetchPriority?: "high" | "low" | "auto";
}): void;
preinit(href: string, options: {
as: "script" | "style";
crossOrigin?: string;
fetchPriority?: "high" | "low" | "auto";
nonce?: string;
}): void;All four functions are imported from "react-dom".
precedence attribute is typed as string on <link rel="stylesheet">"reset", "default", and "high"Reviewed by Chris St. John·Last updated Jul 7, 2026
🤖 Read the SystemsArchitect.io Blog for over 100+ cloud architecture articles 🔥