UNPKG

remix-utils

Version:

This package contains simple utility functions to use with [React Router](https://reactrouter.com/).

126 lines 4.02 kB
/** * Combine `preloadLinkedAssets` and `preloadModuleAssets` into a single * function and preload both linked and module assets. * @param context Remix's EntryContext * @param headers The headers object to append the preload links to * @example * export default function handleRequest( * request: Request, * statusCode: number, * headers: Headers, * context: EntryContext * ) { * let markup = renderToString( * <RemixServer context={context} url={request.url} /> * ); * headers.set("Content-Type", "text/html"); * * preloadRouteAssets(context, headers); // add this line * * return new Response("<!DOCTYPE html>" + markup, { * status: statusCode, * headers: headers, * }); * } */ export function preloadRouteAssets(context, headers) { preloadLinkedAssets(context, headers); // preload links preloadModuleAssets(context, headers); // preload JS modules } /** * Preload the assets linked in the routes matching the current request. * This function will preload any `<link rel="preload" />` tag added with * `LinksFunction` and any CSS files linked with `<link rel="stylesheet" />`. * @param context Remix's EntryContext * @param headers The headers object to append the preload links to * @example * export default function handleRequest( * request: Request, * statusCode: number, * headers: Headers, * context: EntryContext * ) { * let markup = renderToString( * <RemixServer context={context} url={request.url} /> * ); * headers.set("Content-Type", "text/html"); * * preloadLinkedAssets(context, headers); // add this line * * return new Response("<!DOCTYPE html>" + markup, { * status: statusCode, * headers: headers, * }); * } */ export function preloadLinkedAssets(context, headers) { let links = context.staticHandlerContext.matches .flatMap((match) => { let route = context.routeModules[match.route.id]; if (!route) return []; if (route.links instanceof Function) return route.links(); return []; }) .map((link) => { if ("as" in link && "href" in link) { return { href: link.href, as: link.as }; } if ("rel" in link && "href" in link && link.rel === "stylesheet") return { href: link.href, as: "style" }; return null; }) .filter((link) => { return link !== null && "href" in link; }) .filter((item, index, list) => { return index === list.findIndex((link) => link.href === item.href); }); for (let link of links) { headers.append("Link", `<${link.href}>; rel=preload; as=${link.as}`); } } /** * Add Link headers to preload the JS modules in the route matching the current * request. * @param context Remix's EntryContext * @param headers The headers object to append the preload links to * @example * export default function handleRequest( * request: Request, * statusCode: number, * headers: Headers, * context: EntryContext * ) { * let markup = renderToString( * <RemixServer context={context} url={request.url} /> * ); * headers.set("Content-Type", "text/html"); * * preloadModuleAssets(context, headers); // add this line * * return new Response("<!DOCTYPE html>" + markup, { * status: statusCode, * headers: headers, * }); * } */ export function preloadModuleAssets(context, headers) { let urls = [ context.manifest.url, context.manifest.entry.module, ...context.manifest.entry.imports, ]; for (let match of context.staticHandlerContext.matches) { let route = context.manifest.routes[match.route.id]; if (!route) { continue; } urls.push(route.module, ...(route.imports ?? [])); } for (let url of urls) { headers.append("Link", `<${url}>; rel=preload; as=script; crossorigin=anonymous`); } } //# sourceMappingURL=preload-route-assets.js.map