Skip to content

Commit

Permalink
add layerAssets property to FlightDataPath (#66354)
Browse files Browse the repository at this point in the history
This adds a new `layerAssets` property (containing styles and script
tags) to `FlightDataPath`. Previously these were lumped in with the
`head` node, but we intentionally only ever render a single `head`, to
avoid duplicating metadata. This would mean `<AppRouter />` would only
ever render imported stylesheets for a single page in a racey way.
However, since Float handles hoisting and deduping these style tags,
we're safe to render them for each segment.

This PR introduces no change in behavior, aside from sending
`layerAssets` down from the server and storing it in the client router
cache. These nodes aren't rendered -- this is done in #66300.
  • Loading branch information
ztanner committed Jun 3, 2024
1 parent be7d0c9 commit 312eb61
Show file tree
Hide file tree
Showing 25 changed files with 238 additions and 55 deletions.
5 changes: 5 additions & 0 deletions packages/next/src/client/components/app-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ type AppRouterProps = Omit<
> & {
buildId: string
initialHead: ReactNode
initialLayerAssets: ReactNode
assetPrefix: string
missingSlots: Set<string>
}
Expand Down Expand Up @@ -183,6 +184,8 @@ export function createEmptyCacheNode(): CacheNode {
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand Down Expand Up @@ -307,6 +310,7 @@ function Router({
initialParallelRoutes,
location: !isServer ? window.location : null,
initialHead,
initialLayerAssets: null,
couldBeIntercepted,
}),
[
Expand Down Expand Up @@ -656,6 +660,7 @@ function Router({
let content = (
<RedirectBoundary>
{head}
{/* {cache.layerAssets} */}
{cache.rsc}
<AppRouterAnnouncer tree={tree} />
</RedirectBoundary>
Expand Down
3 changes: 3 additions & 0 deletions packages/next/src/client/components/layout-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ function InnerLayoutRouter({
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand Down Expand Up @@ -466,6 +468,7 @@ function InnerLayoutRouter({
loading: childNode.loading,
}}
>
{/* {childNode.layerAssets} */}
{resolvedRsc}
</LayoutRouterContext.Provider>
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ export function applyFlightData(
prefetchEntry?: PrefetchCacheEntry
): boolean {
// The one before last item is the router state tree patch
const [treePatch, cacheNodeSeedData, head] = flightDataPath.slice(-3)
const [treePatch, cacheNodeSeedData, head, layerAssets] =
flightDataPath.slice(-4)

// Handles case where prefetch only returns the router tree patch without rendered components.
if (cacheNodeSeedData === null) {
return false
}

if (flightDataPath.length === 3) {
if (flightDataPath.length === 4) {
const rsc = cacheNodeSeedData[2]
const loading = cacheNodeSeedData[3]
cache.loading = loading
Expand All @@ -35,6 +36,7 @@ export function applyFlightData(
treePatch,
cacheNodeSeedData,
head,
layerAssets,
prefetchEntry
)
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ describe('clearCacheNodeDataForSegmentPath', () => {
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand All @@ -27,6 +29,8 @@ describe('clearCacheNodeDataForSegmentPath', () => {
rsc: <>Root layout</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -42,6 +46,8 @@ describe('clearCacheNodeDataForSegmentPath', () => {
prefetchRsc: null,
lazyDataResolved: false,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
loading: null,
parallelRoutes: new Map([
Expand All @@ -55,6 +61,8 @@ describe('clearCacheNodeDataForSegmentPath', () => {
rsc: <>Page</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand All @@ -76,25 +84,29 @@ describe('clearCacheNodeDataForSegmentPath', () => {
expect(cache).toMatchInlineSnapshot(`
{
"head": null,
"layerAssets": null,
"lazyData": null,
"lazyDataResolved": false,
"loading": null,
"parallelRoutes": Map {
"children" => Map {
"linking" => {
"head": null,
"layerAssets": null,
"lazyData": null,
"lazyDataResolved": false,
"loading": null,
"parallelRoutes": Map {
"children" => Map {
"" => {
"head": null,
"layerAssets": null,
"lazyData": null,
"lazyDataResolved": false,
"loading": null,
"parallelRoutes": Map {},
"prefetchHead": null,
"prefetchLayerAssets": null,
"prefetchRsc": null,
"rsc": <React.Fragment>
Page
Expand All @@ -103,24 +115,28 @@ describe('clearCacheNodeDataForSegmentPath', () => {
},
},
"prefetchHead": null,
"prefetchLayerAssets": null,
"prefetchRsc": null,
"rsc": <React.Fragment>
Linking
</React.Fragment>,
},
"dashboard" => {
"head": null,
"layerAssets": null,
"lazyData": null,
"lazyDataResolved": false,
"loading": null,
"parallelRoutes": Map {},
"prefetchHead": null,
"prefetchLayerAssets": null,
"prefetchRsc": null,
"rsc": null,
},
},
},
"prefetchHead": null,
"prefetchLayerAssets": null,
"prefetchRsc": null,
"rsc": null,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export function clearCacheNodeDataForSegmentPath(
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand All @@ -57,6 +59,8 @@ export function clearCacheNodeDataForSegmentPath(
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
parallelRoutes: new Map(),
lazyDataResolved: false,
Expand All @@ -72,6 +76,8 @@ export function clearCacheNodeDataForSegmentPath(
rsc: childCacheNode.rsc,
prefetchRsc: childCacheNode.prefetchRsc,
head: childCacheNode.head,
layerAssets: childCacheNode.layerAssets,
prefetchLayerAssets: childCacheNode.prefetchLayerAssets,
prefetchHead: childCacheNode.prefetchHead,
parallelRoutes: new Map(childCacheNode.parallelRoutes),
lazyDataResolved: childCacheNode.lazyDataResolved,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe('createInitialRouterState', () => {
initialParallelRoutes,
location: new URL('/linking', 'https://localhost') as any,
initialHead: <title>Test</title>,
initialLayerAssets: null,
couldBeIntercepted: false,
})

Expand All @@ -52,13 +53,16 @@ describe('createInitialRouterState', () => {
initialParallelRoutes,
location: new URL('/linking', 'https://localhost') as any,
initialHead: <title>Test</title>,
initialLayerAssets: null,
})

const expectedCache: CacheNode = {
lazyData: null,
rsc: children,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -82,6 +86,8 @@ describe('createInitialRouterState', () => {
parallelRoutes: new Map(),
loading: null,
head: <title>Test</title>,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
},
Expand All @@ -93,6 +99,8 @@ describe('createInitialRouterState', () => {
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface InitialRouterStateParameters {
initialParallelRoutes: CacheNode['parallelRoutes']
location: Location | null
initialHead: ReactNode
initialLayerAssets: ReactNode
couldBeIntercepted?: boolean
}

Expand All @@ -32,6 +33,7 @@ export function createInitialRouterState({
initialParallelRoutes,
location,
initialHead,
initialLayerAssets,
couldBeIntercepted,
}: InitialRouterStateParameters) {
const isServer = !location
Expand All @@ -42,6 +44,8 @@ export function createInitialRouterState({
rsc: rsc,
prefetchRsc: null,
head: null,
layerAssets: initialLayerAssets,
prefetchLayerAssets: null,
prefetchHead: null,
// The cache gets seeded during the first render. `initialParallelRoutes` ensures the cache from the first render is there during the second render.
parallelRoutes: isServer ? new Map() : initialParallelRoutes,
Expand All @@ -68,7 +72,8 @@ export function createInitialRouterState({
undefined,
initialTree,
initialSeedData,
initialHead
initialHead,
initialLayerAssets
)
}

Expand Down Expand Up @@ -106,7 +111,9 @@ export function createInitialRouterState({
location.origin
)

const initialFlightData: FlightData = [['', initialTree, null, null]]
const initialFlightData: FlightData = [
['', initialTree, null, null, initialLayerAssets],
]
createPrefetchCacheEntryForInitialLoad({
url,
kind: PrefetchKind.AUTO,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
loading: null,
parallelRoutes: new Map(),
Expand All @@ -41,6 +43,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: <>Root layout</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -55,6 +59,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: <>Linking</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -69,6 +75,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: <>Page</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand Down Expand Up @@ -101,6 +109,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: null,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -115,6 +125,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: <>Linking</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -130,6 +142,8 @@ describe('fillCacheWithNewSubtreeData', () => {
rsc: <>Page</>,
prefetchRsc: null,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
lazyDataResolved: false,
loading: null,
Expand All @@ -142,6 +156,8 @@ describe('fillCacheWithNewSubtreeData', () => {
lazyData: null,
lazyDataResolved: false,
head: null,
layerAssets: null,
prefetchLayerAssets: null,
prefetchHead: null,
loading: null,
parallelRoutes: new Map([
Expand All @@ -162,6 +178,8 @@ describe('fillCacheWithNewSubtreeData', () => {
<title>Head Injected!</title>
</>
),
layerAssets: null,
prefetchLayerAssets: null,
},
],
]),
Expand Down
Loading

0 comments on commit 312eb61

Please sign in to comment.