From 27fd91eb80b76e88ce1d3139aa74cf7a20ccec3d Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Wed, 8 May 2024 00:22:55 +0200 Subject: [PATCH 1/6] Preload all chunks --- .../src/shared/lib/lazy-dynamic/loadable.tsx | 4 +- .../lib/lazy-dynamic/preload-chunks.tsx | 62 +++++++++++++++++++ .../shared/lib/lazy-dynamic/preload-css.tsx | 47 -------------- .../next/src/shared/lib/lazy-dynamic/types.ts | 1 - 4 files changed, 64 insertions(+), 50 deletions(-) create mode 100644 packages/next/src/shared/lib/lazy-dynamic/preload-chunks.tsx delete mode 100644 packages/next/src/shared/lib/lazy-dynamic/preload-css.tsx diff --git a/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx b/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx index 1aa448a61e366..31b6e459e93d8 100644 --- a/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx +++ b/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx @@ -1,7 +1,7 @@ import { Suspense, lazy } from 'react' import { BailoutToCSR } from './dynamic-bailout-to-csr' import type { ComponentModule } from './types' -import { PreloadCss } from './preload-css' +import { PreloadChunks } from './preload-chunks' // Normalize loader to return the module as form { default: Component } for `React.lazy`. // Also for backward compatible since next/dynamic allows to resolve a component directly with loader @@ -52,7 +52,7 @@ function Loadable(options: LoadableOptions) { <> {/* During SSR, we need to preload the CSS from the dynamic component to avoid flash of unstyled content */} {typeof window === 'undefined' ? ( - + ) : null} diff --git a/packages/next/src/shared/lib/lazy-dynamic/preload-chunks.tsx b/packages/next/src/shared/lib/lazy-dynamic/preload-chunks.tsx new file mode 100644 index 0000000000000..1d60e6f8c90f6 --- /dev/null +++ b/packages/next/src/shared/lib/lazy-dynamic/preload-chunks.tsx @@ -0,0 +1,62 @@ +'use client' + +import { getExpectedRequestStore } from '../../../client/components/request-async-storage.external' + +export function PreloadChunks({ + moduleIds, +}: { + moduleIds: string[] | undefined +}) { + // Early return in client compilation and only load requestStore on server side + if (typeof window !== 'undefined') { + return null + } + + const requestStore = getExpectedRequestStore('next/dynamic preload') + const allFiles = [] + + // Search the current dynamic call unique key id in react loadable manifest, + // and find the corresponding CSS files to preload + if (requestStore.reactLoadableManifest && moduleIds) { + const manifest = requestStore.reactLoadableManifest + for (const key of moduleIds) { + if (!manifest[key]) continue + const chunks = manifest[key].files + allFiles.push(...chunks) + } + } + + if (allFiles.length === 0) { + return null + } + + return ( + <> + {allFiles.map((chunk) => { + const href = `${requestStore.assetPrefix}/_next/${encodeURI(chunk)}` + if (chunk.endsWith('.css')) { + return ( + + ) + } else { + return ( +