Server-side rendering support with static font registration and resource management. Enables font loading in SSR environments and provides utilities for managing font resources across server contexts.
Register fonts for server-side rendering without asynchronous loading.
/**
* Register a font for server-side rendering (synchronous operation)
* @param fontFamily - Name to register the font under
* @param source - Font source (asset, URI, or FontResource)
*/
function registerStaticFont(
fontFamily: string,
source?: FontSource | null
): void;Usage Examples:
import { registerStaticFont } from 'expo-font/build/server';
// Register fonts for SSR
registerStaticFont('Inter-Regular', require('./assets/fonts/Inter-Regular.otf'));
registerStaticFont('Inter-Bold', require('./assets/fonts/Inter-Bold.otf'));
// With FontResource options
registerStaticFont('WebFont', {
uri: require('./assets/fonts/WebFont.woff2'),
display: FontDisplay.SWAP
});
// Register multiple fonts for a component
function registerAppFonts() {
const fonts = {
'CustomFont1': require('./fonts/Font1.ttf'),
'CustomFont2': require('./fonts/Font2.ttf'),
'CustomFont3': { uri: './fonts/Font3.woff2', display: FontDisplay.OPTIONAL }
};
Object.entries(fonts).forEach(([name, source]) => {
registerStaticFont(name, source);
});
}Manage font resources across server rendering contexts.
/**
* Get server resources that should be statically extracted
* @returns Array of resource identifiers for static extraction
*/
function getServerResources(): string[];
/**
* Clear server resources from global scope (cleanup between renders)
*/
function resetServerContext(): void;Usage Examples:
import {
getServerResources,
resetServerContext,
registerStaticFont
} from 'expo-font/build/server';
// Server-side rendering setup
function renderAppWithFonts(req, res) {
try {
// Register fonts for this render
registerStaticFont('AppFont', require('./fonts/AppFont.ttf'));
// Get resources that need to be included
const fontResources = getServerResources();
console.log('Required font resources:', fontResources);
// Render your app
const html = renderToString(<App />);
// Generate font CSS or preload links based on resources
const fontLinks = fontResources.map(resource =>
`<link rel="preload" href="${resource}" as="font" crossorigin>`
).join('\n');
const fullHtml = `
<html>
<head>
${fontLinks}
</head>
<body>
<div id="root">${html}</div>
</body>
</html>
`;
res.send(fullHtml);
} finally {
// Clean up for next render
resetServerContext();
}
}
// Next.js integration
export async function getServerSideProps(context) {
// Register fonts needed for this page
registerStaticFont('PageFont', require('./fonts/PageFont.ttf'));
const resources = getServerResources();
return {
props: {
fontResources: resources
}
};
}The server-side functions work seamlessly with the useFonts hook for SSR:
import { useFonts } from 'expo-font';
import { registerStaticFont } from 'expo-font/build/server';
// Server-side: fonts are registered statically
if (typeof window === 'undefined') {
registerStaticFont('MyFont', require('./MyFont.ttf'));
}
function MyComponent() {
// On server: returns [true, null] immediately (fonts pre-registered)
// On client: loads fonts asynchronously, returns loading state
const [fontsLoaded, error] = useFonts({
'MyFont': require('./MyFont.ttf')
});
if (error) throw error;
if (!fontsLoaded) return <LoadingSpinner />;
return <Text style={{ fontFamily: 'MyFont' }}>SSR-ready text</Text>;
}import {
registerStaticFont,
getServerResources,
resetServerContext
} from 'expo-font/build/server';
// Font preloading utility for SSR frameworks
class FontManager {
private static registeredFonts = new Set<string>();
static registerForSSR(fontMap: Record<string, FontSource>) {
Object.entries(fontMap).forEach(([name, source]) => {
if (!this.registeredFonts.has(name)) {
registerStaticFont(name, source);
this.registeredFonts.add(name);
}
});
}
static getPreloadLinks(): string[] {
const resources = getServerResources();
return resources.map(resource =>
`<link rel="preload" href="${resource}" as="font" type="font/woff2" crossorigin>`
);
}
static cleanup() {
resetServerContext();
this.registeredFonts.clear();
}
}
// Use in your SSR setup
function renderWithFonts(Component, props) {
// Register fonts used by component tree
FontManager.registerForSSR({
'Inter': require('./fonts/Inter.woff2'),
'Roboto': require('./fonts/Roboto.woff2')
});
const html = renderToString(<Component {...props} />);
const preloadLinks = FontManager.getPreloadLinks();
FontManager.cleanup();
return { html, preloadLinks };
}
// Critical font loading for performance
function registerCriticalFonts() {
// Register only fonts needed for above-the-fold content
registerStaticFont('PrimaryFont', {
uri: require('./fonts/Primary.woff2'),
display: FontDisplay.BLOCK // Ensure no FOUT for critical text
});
}
// Deferred font loading for non-critical content
function registerDeferredFonts() {
registerStaticFont('SecondaryFont', {
uri: require('./fonts/Secondary.woff2'),
display: FontDisplay.SWAP // Allow FOUT for non-critical text
});
}import { registerStaticFont } from 'expo-font/build/server';
// Handle registration errors
function safeRegisterFont(name: string, source: FontSource) {
try {
registerStaticFont(name, source);
console.log(`Font registered: ${name}`);
} catch (error) {
if (error.code === 'ERR_FONT_SOURCE') {
console.warn(`Invalid font source for ${name}:`, source);
} else {
console.error(`Failed to register font ${name}:`, error);
}
}
}
// Validate font sources before registration
function registerValidatedFonts(fontMap: Record<string, FontSource>) {
Object.entries(fontMap).forEach(([name, source]) => {
if (source == null) {
console.warn(`Skipping ${name}: null/undefined source`);
return;
}
safeRegisterFont(name, source);
});
}getServerSideProps or getStaticPropsgatsby-ssr.js for static generationFontDisplay.BLOCK for critical text, SWAP for non-critical