mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-22 18:43:29 +00:00
Speed up icon rendering
This commit is contained in:
@@ -5,7 +5,7 @@ import * as React from 'react';
|
||||
import { IconSymbolLoader } from './IconSymbolLoader';
|
||||
import { getIconAssetURL, useIcons } from './IconsProvider';
|
||||
import { getIconStyle } from './getIconStyle';
|
||||
import { getIconSymbolId, registerServerIconSymbol } from './symbols';
|
||||
import { getIconSymbolId, prefetchServerIconAsset, registerServerIconSymbol } from './symbols';
|
||||
import type { IconName, IconStyle } from './types';
|
||||
|
||||
/**
|
||||
@@ -55,12 +55,15 @@ export const Icon = React.forwardRef(function Icon(
|
||||
const maskId = React.useId();
|
||||
const iconInstanceId = React.useId();
|
||||
const symbolId = getIconSymbolId(iconStyle, icon);
|
||||
const iconAssetURL = getIconAssetURL(context, iconStyle, icon);
|
||||
|
||||
if (context.renderMode === 'symbol') {
|
||||
prefetchServerIconAsset(iconAssetURL);
|
||||
registerServerIconSymbol({
|
||||
style: iconStyle,
|
||||
icon,
|
||||
symbolId,
|
||||
assetURL: iconAssetURL,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -111,7 +114,7 @@ export const Icon = React.forwardRef(function Icon(
|
||||
>
|
||||
<image
|
||||
data-testid="mask-image"
|
||||
href={getIconAssetURL(context, iconStyle, icon)}
|
||||
href={iconAssetURL}
|
||||
width="100%"
|
||||
height="100%"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
|
||||
@@ -4,9 +4,11 @@ export interface RegisteredIconSymbol {
|
||||
style: string;
|
||||
icon: string;
|
||||
symbolId: string;
|
||||
assetURL?: string;
|
||||
}
|
||||
|
||||
const REGISTERED_SYMBOLS_KEY = Symbol.for('gitbook.icons.registeredSymbols');
|
||||
const PREFETCHED_ICON_ASSETS_KEY = Symbol.for('gitbook.icons.prefetchedAssets');
|
||||
|
||||
function sanitizeSymbolFragment(fragment: string): string {
|
||||
return fragment.replace(/[^a-zA-Z0-9_-]/g, '-');
|
||||
@@ -31,6 +33,18 @@ function getRegisteredSymbolsStore(): Map<string, RegisteredIconSymbol> {
|
||||
return store[REGISTERED_SYMBOLS_KEY];
|
||||
}
|
||||
|
||||
function getPrefetchedAssetsStore(): Map<string, Promise<void>> {
|
||||
const store = globalThis as typeof globalThis & {
|
||||
[PREFETCHED_ICON_ASSETS_KEY]?: Map<string, Promise<void>>;
|
||||
};
|
||||
|
||||
if (!store[PREFETCHED_ICON_ASSETS_KEY]) {
|
||||
store[PREFETCHED_ICON_ASSETS_KEY] = new Map<string, Promise<void>>();
|
||||
}
|
||||
|
||||
return store[PREFETCHED_ICON_ASSETS_KEY];
|
||||
}
|
||||
|
||||
function shouldTrackSymbolRegistrations() {
|
||||
const runtime = globalThis as typeof globalThis & { Bun?: unknown };
|
||||
|
||||
@@ -48,6 +62,27 @@ export function registerServerIconSymbol(symbol: RegisteredIconSymbol): void {
|
||||
getRegisteredSymbolsStore().set(`${symbol.style}/${symbol.icon}`, symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start fetching a raw SVG asset during SSR so sprite generation can reuse the in-flight or warm
|
||||
* request instead of waiting until the end of the render.
|
||||
*/
|
||||
export function prefetchServerIconAsset(assetURL: string): void {
|
||||
if (typeof window !== 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
const prefetchedAssets = getPrefetchedAssetsStore();
|
||||
if (prefetchedAssets.has(assetURL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const request = fetch(assetURL, { cache: 'force-cache' })
|
||||
.then(() => undefined)
|
||||
.catch(() => undefined);
|
||||
|
||||
prefetchedAssets.set(assetURL, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the currently registered server-rendered symbols in insertion order.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user