diff --git a/.github/workflows/build_reusable.yml b/.github/workflows/build_reusable.yml index 6e8778def5f29..322a2572cf756 100644 --- a/.github/workflows/build_reusable.yml +++ b/.github/workflows/build_reusable.yml @@ -178,6 +178,7 @@ jobs: with: name: test-reports path: | + test/traces test/test-junit-report test/turbopack-test-junit-report if-no-files-found: ignore diff --git a/docs/02-app/01-building-your-application/01-routing/10-route-handlers.mdx b/docs/02-app/01-building-your-application/01-routing/10-route-handlers.mdx index 68350063f82a1..cff5fcce7a5a5 100644 --- a/docs/02-app/01-building-your-application/01-routing/10-route-handlers.mdx +++ b/docs/02-app/01-building-your-application/01-routing/10-route-handlers.mdx @@ -25,12 +25,12 @@ Route Handlers allow you to create custom request handlers for a given route usi Route Handlers are defined in a [`route.js|ts` file](/docs/app/api-reference/file-conventions/route) inside the `app` directory: ```ts filename="app/api/route.ts" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request: Request) {} ``` ```js filename="app/api/route.js" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request) {} ``` @@ -575,7 +575,7 @@ Since `formData` data are all strings, you may want to use [`zod-form-data`](htt You can set CORS headers on a `Response` using the standard Web API methods: ```ts filename="app/api/route.ts" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request: Request) { return new Response('Hello, Next.js!', { @@ -590,7 +590,7 @@ export async function GET(request: Request) { ``` ```js filename="app/api/route.js" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET(request) { return new Response('Hello, Next.js!', { @@ -619,7 +619,7 @@ export const runtime = 'edge' // 'nodejs' is the default You can use Route Handlers to return non-UI content. Note that [`sitemap.xml`](/docs/app/api-reference/file-conventions/metadata/sitemap#generate-a-sitemap), [`robots.txt`](/docs/app/api-reference/file-conventions/metadata/robots#generate-a-robots-file), [`app icons`](/docs/app/api-reference/file-conventions/metadata/app-icons#generate-icons-using-code-js-ts-tsx), and [open graph images](/docs/app/api-reference/file-conventions/metadata/opengraph-image) all have built-in support. ```ts filename="app/rss.xml/route.ts" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET() { return new Response(` @@ -636,7 +636,7 @@ export async function GET() { ``` ```js filename="app/rss.xml/route.js" switcher -export const dynamic = 'force-dynamic' // defaults to force-static +export const dynamic = 'force-dynamic' // defaults to auto export async function GET() { return new Response(` diff --git a/docs/02-app/02-api-reference/05-next-config-js/webpack.mdx b/docs/02-app/02-api-reference/05-next-config-js/webpack.mdx index 2b97900791f53..2359c2aea77cb 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/webpack.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/webpack.mdx @@ -16,7 +16,6 @@ Before continuing to add custom webpack configuration to your application make s - [CSS modules](/docs/app/building-your-application/styling/css-modules) - [Sass/SCSS imports](/docs/app/building-your-application/styling/sass) - [Sass/SCSS modules](/docs/app/building-your-application/styling/sass) -- [preact](https://github.com/vercel/next.js/tree/canary/examples/using-preact) @@ -26,7 +25,6 @@ Before continuing to add custom webpack configuration to your application make s - [CSS modules](/docs/pages/building-your-application/styling/css-modules) - [Sass/SCSS imports](/docs/pages/building-your-application/styling/sass) - [Sass/SCSS modules](/docs/pages/building-your-application/styling/sass) -- [preact](https://github.com/vercel/next.js/tree/canary/examples/using-preact) - [Customizing babel configuration](/docs/pages/building-your-application/configuring/babel) diff --git a/lerna.json b/lerna.json index 7ec56a14752e2..9b5082fefe8ab 100644 --- a/lerna.json +++ b/lerna.json @@ -16,5 +16,5 @@ "registry": "https://registry.npmjs.org/" } }, - "version": "14.0.5-canary.4" + "version": "14.0.5-canary.6" } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index b507649f58783..92a8d8f4b04e9 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -1,6 +1,6 @@ { "name": "create-next-app", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "keywords": [ "react", "next", diff --git a/packages/eslint-config-next/package.json b/packages/eslint-config-next/package.json index 2ee358c63f323..1ac6dc820d329 100644 --- a/packages/eslint-config-next/package.json +++ b/packages/eslint-config-next/package.json @@ -1,6 +1,6 @@ { "name": "eslint-config-next", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "ESLint configuration used by Next.js.", "main": "index.js", "license": "MIT", @@ -10,7 +10,7 @@ }, "homepage": "https://nextjs.org/docs/app/building-your-application/configuring/eslint#eslint-config", "dependencies": { - "@next/eslint-plugin-next": "14.0.5-canary.4", + "@next/eslint-plugin-next": "14.0.5-canary.6", "@rushstack/eslint-patch": "^1.3.3", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "eslint-import-resolver-node": "^0.3.6", diff --git a/packages/eslint-plugin-next/package.json b/packages/eslint-plugin-next/package.json index df8e165d8203d..0099bce16cc13 100644 --- a/packages/eslint-plugin-next/package.json +++ b/packages/eslint-plugin-next/package.json @@ -1,6 +1,6 @@ { "name": "@next/eslint-plugin-next", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "ESLint plugin for Next.js.", "main": "dist/index.js", "license": "MIT", diff --git a/packages/font/package.json b/packages/font/package.json index 62f2689561a84..dfee30bba26bc 100644 --- a/packages/font/package.json +++ b/packages/font/package.json @@ -1,6 +1,6 @@ { "name": "@next/font", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "repository": { "url": "vercel/next.js", "directory": "packages/font" diff --git a/packages/font/src/google/font-data.json b/packages/font/src/google/font-data.json index ab6941e8ce533..7dae1baa51c9f 100644 --- a/packages/font/src/google/font-data.json +++ b/packages/font/src/google/font-data.json @@ -103,6 +103,26 @@ ], "subsets": ["cyrillic", "cyrillic-ext", "greek", "latin", "latin-ext"] }, + "Afacad": { + "weights": ["400", "500", "600", "700", "variable"], + "styles": ["normal", "italic"], + "axes": [ + { + "tag": "wght", + "min": 400, + "max": 700, + "defaultValue": 400 + } + ], + "subsets": [ + "cyrillic-ext", + "latin", + "latin-ext", + "math", + "symbols", + "vietnamese" + ] + }, "Agbalumo": { "weights": ["400"], "styles": ["normal"], @@ -5328,6 +5348,25 @@ "styles": ["normal"], "subsets": ["devanagari", "latin", "latin-ext"] }, + "Kalnia": { + "weights": ["100", "200", "300", "400", "500", "600", "700", "variable"], + "styles": ["normal"], + "axes": [ + { + "tag": "wdth", + "min": 100, + "max": 125, + "defaultValue": 100 + }, + { + "tag": "wght", + "min": 100, + "max": 700, + "defaultValue": 400 + } + ], + "subsets": ["latin", "latin-ext", "math"] + }, "Kameron": { "weights": ["400", "500", "600", "700", "variable"], "styles": ["normal"], @@ -11225,6 +11264,19 @@ "styles": ["normal"], "subsets": ["cyrillic", "latin", "latin-ext"] }, + "Rethink Sans": { + "weights": ["400", "500", "600", "700", "800", "variable"], + "styles": ["normal", "italic"], + "axes": [ + { + "tag": "wght", + "min": 400, + "max": 800, + "defaultValue": 400 + } + ], + "subsets": ["latin", "latin-ext"] + }, "Revalia": { "weights": ["400"], "styles": ["normal"], diff --git a/packages/font/src/google/index.ts b/packages/font/src/google/index.ts index 85dee698275a2..39445e9744bed 100644 --- a/packages/font/src/google/index.ts +++ b/packages/font/src/google/index.ts @@ -190,6 +190,26 @@ export declare function Advent_Pro< subsets?: Array<'cyrillic' | 'cyrillic-ext' | 'greek' | 'latin' | 'latin-ext'> axes?: 'wdth'[] }): T extends undefined ? NextFont : NextFontWithVariable +export declare function Afacad< + T extends CssVariable | undefined = undefined +>(options?: { + weight?: + | '400' + | '500' + | '600' + | '700' + | 'variable' + | Array<'400' | '500' | '600' | '700'> + style?: 'normal' | 'italic' | Array<'normal' | 'italic'> + display?: Display + variable?: T + preload?: boolean + fallback?: string[] + adjustFontFallback?: boolean + subsets?: Array< + 'cyrillic-ext' | 'latin' | 'latin-ext' | 'math' | 'symbols' | 'vietnamese' + > +}): T extends undefined ? NextFont : NextFontWithVariable export declare function Agbalumo< T extends CssVariable | undefined = undefined >(options: { @@ -9539,6 +9559,28 @@ export declare function Kalam< adjustFontFallback?: boolean subsets?: Array<'devanagari' | 'latin' | 'latin-ext'> }): T extends undefined ? NextFont : NextFontWithVariable +export declare function Kalnia< + T extends CssVariable | undefined = undefined +>(options?: { + weight?: + | '100' + | '200' + | '300' + | '400' + | '500' + | '600' + | '700' + | 'variable' + | Array<'100' | '200' | '300' | '400' | '500' | '600' | '700'> + style?: 'normal' | Array<'normal'> + display?: Display + variable?: T + preload?: boolean + fallback?: string[] + adjustFontFallback?: boolean + subsets?: Array<'latin' | 'latin-ext' | 'math'> + axes?: 'wdth'[] +}): T extends undefined ? NextFont : NextFontWithVariable export declare function Kameron< T extends CssVariable | undefined = undefined >(options?: { @@ -19158,6 +19200,25 @@ export declare function Reggae_One< adjustFontFallback?: boolean subsets?: Array<'cyrillic' | 'latin' | 'latin-ext'> }): T extends undefined ? NextFont : NextFontWithVariable +export declare function Rethink_Sans< + T extends CssVariable | undefined = undefined +>(options?: { + weight?: + | '400' + | '500' + | '600' + | '700' + | '800' + | 'variable' + | Array<'400' | '500' | '600' | '700' | '800'> + style?: 'normal' | 'italic' | Array<'normal' | 'italic'> + display?: Display + variable?: T + preload?: boolean + fallback?: string[] + adjustFontFallback?: boolean + subsets?: Array<'latin' | 'latin-ext'> +}): T extends undefined ? NextFont : NextFontWithVariable export declare function Revalia< T extends CssVariable | undefined = undefined >(options: { diff --git a/packages/next-bundle-analyzer/package.json b/packages/next-bundle-analyzer/package.json index a2d383f556d0a..9608712d466d1 100644 --- a/packages/next-bundle-analyzer/package.json +++ b/packages/next-bundle-analyzer/package.json @@ -1,6 +1,6 @@ { "name": "@next/bundle-analyzer", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "main": "index.js", "types": "index.d.ts", "license": "MIT", diff --git a/packages/next-codemod/package.json b/packages/next-codemod/package.json index 51afd1b3db8aa..27dfd6b528b39 100644 --- a/packages/next-codemod/package.json +++ b/packages/next-codemod/package.json @@ -1,6 +1,6 @@ { "name": "@next/codemod", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "license": "MIT", "repository": { "type": "git", diff --git a/packages/next-env/package.json b/packages/next-env/package.json index 4bcd4e6c95cf2..a993b624663b7 100644 --- a/packages/next-env/package.json +++ b/packages/next-env/package.json @@ -1,6 +1,6 @@ { "name": "@next/env", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "keywords": [ "react", "next", diff --git a/packages/next-mdx/package.json b/packages/next-mdx/package.json index 5887bdb5d8f28..637200d3d03a6 100644 --- a/packages/next-mdx/package.json +++ b/packages/next-mdx/package.json @@ -1,6 +1,6 @@ { "name": "@next/mdx", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "main": "index.js", "license": "MIT", "repository": { diff --git a/packages/next-plugin-storybook/package.json b/packages/next-plugin-storybook/package.json index a470566d72103..2496053d1ec8c 100644 --- a/packages/next-plugin-storybook/package.json +++ b/packages/next-plugin-storybook/package.json @@ -1,6 +1,6 @@ { "name": "@next/plugin-storybook", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "repository": { "url": "vercel/next.js", "directory": "packages/next-plugin-storybook" diff --git a/packages/next-polyfill-module/package.json b/packages/next-polyfill-module/package.json index c2804e9cd4687..5faca4b109fd7 100644 --- a/packages/next-polyfill-module/package.json +++ b/packages/next-polyfill-module/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-module", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "A standard library polyfill for ES Modules supporting browsers (Edge 16+, Firefox 60+, Chrome 61+, Safari 10.1+)", "main": "dist/polyfill-module.js", "license": "MIT", diff --git a/packages/next-polyfill-nomodule/package.json b/packages/next-polyfill-nomodule/package.json index 2bc1f781ccd02..5a4d0dfff299b 100644 --- a/packages/next-polyfill-nomodule/package.json +++ b/packages/next-polyfill-nomodule/package.json @@ -1,6 +1,6 @@ { "name": "@next/polyfill-nomodule", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "A polyfill for non-dead, nomodule browsers.", "main": "dist/polyfill-nomodule.js", "license": "MIT", diff --git a/packages/next-swc/package.json b/packages/next-swc/package.json index d0c5b9ee61750..a8a419900eb9e 100644 --- a/packages/next-swc/package.json +++ b/packages/next-swc/package.json @@ -1,6 +1,6 @@ { "name": "@next/swc", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "private": true, "scripts": { "clean": "node ../../scripts/rm.mjs native", diff --git a/packages/next/package.json b/packages/next/package.json index e3342b9cee4e1..7cef33fe5cc1c 100644 --- a/packages/next/package.json +++ b/packages/next/package.json @@ -1,6 +1,6 @@ { "name": "next", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "The React Framework", "main": "./dist/server/next.js", "license": "MIT", @@ -92,7 +92,7 @@ ] }, "dependencies": { - "@next/env": "14.0.5-canary.4", + "@next/env": "14.0.5-canary.6", "@swc/helpers": "0.5.2", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -147,11 +147,11 @@ "@mswjs/interceptors": "0.23.0", "@napi-rs/cli": "2.16.2", "@napi-rs/triples": "1.1.0", - "@next/polyfill-module": "14.0.5-canary.4", - "@next/polyfill-nomodule": "14.0.5-canary.4", - "@next/react-dev-overlay": "14.0.5-canary.4", - "@next/react-refresh-utils": "14.0.5-canary.4", - "@next/swc": "14.0.5-canary.4", + "@next/polyfill-module": "14.0.5-canary.6", + "@next/polyfill-nomodule": "14.0.5-canary.6", + "@next/react-dev-overlay": "14.0.5-canary.6", + "@next/react-refresh-utils": "14.0.5-canary.6", + "@next/swc": "14.0.5-canary.6", "@opentelemetry/api": "1.6.0", "@playwright/test": "^1.35.1", "@taskr/clear": "1.1.0", diff --git a/packages/next/src/build/utils.ts b/packages/next/src/build/utils.ts index 9accdee7157f1..5fc6cc5f4d7d4 100644 --- a/packages/next/src/build/utils.ts +++ b/packages/next/src/build/utils.ts @@ -21,6 +21,8 @@ import type { import type { WebpackLayerName } from '../lib/constants' import type { AppPageModule } from '../server/future/route-modules/app-page/module' import type { RouteModule } from '../server/future/route-modules/route-module' +import type { LoaderTree } from '../server/lib/app-dir-module' +import type { NextComponentType } from '../shared/lib/utils' import '../server/require-hook' import '../server/node-polyfill-crypto' @@ -1140,14 +1142,21 @@ export type AppConfig = { fetchCache?: 'force-cache' | 'only-cache' preferredRegion?: string } -export type GenerateParams = Array<{ + +type Params = Record + +type GenerateStaticParams = (options: { params?: Params }) => Promise + +type GenerateParamsResult = { config?: AppConfig isDynamicSegment?: boolean segmentPath: string getStaticPaths?: GetStaticPaths - generateStaticParams?: any + generateStaticParams?: GenerateStaticParams isLayout?: boolean -}> +} + +export type GenerateParamsResults = GenerateParamsResult[] export const collectAppConfig = (mod: any): AppConfig | undefined => { let hasConfig = false @@ -1177,56 +1186,81 @@ export const collectAppConfig = (mod: any): AppConfig | undefined => { return hasConfig ? config : undefined } -export const collectGenerateParams = async ( - segment: any, - parentSegments: string[] = [], - generateParams: GenerateParams = [] -): Promise => { - if (!Array.isArray(segment)) return generateParams - const isLayout = !!segment[2]?.layout - const mod = await (isLayout - ? segment[2]?.layout?.[0]?.() - : segment[2]?.page?.[0]?.()) - const config = collectAppConfig(mod) - const page: string | undefined = segment[0] - const isClientComponent = isClientReference(mod) - const isDynamicSegment = /^\[.+\]$/.test(page || '') - const { generateStaticParams, getStaticPaths } = mod || {} - - //console.log({parentSegments, page, isDynamicSegment, isClientComponent, generateStaticParams}) - if (isDynamicSegment && isClientComponent && generateStaticParams) { - throw new Error( - `Page "${page}" cannot export "generateStaticParams()" because it is a client component` - ) - } +/** + * Walks the loader tree and collects the generate parameters for each segment. + * + * @param tree the loader tree + * @returns the generate parameters for each segment + */ +export async function collectGenerateParams(tree: LoaderTree) { + const generateParams: GenerateParamsResults = [] + const parentSegments: string[] = [] + + let currentLoaderTree = tree + while (currentLoaderTree) { + const [ + // TODO: check if this is ever undefined + page = '', + parallelRoutes, + components, + ] = currentLoaderTree + + // If the segment doesn't have any components, then skip it. + if (!components) continue + + const isLayout = !!components.layout + const mod = await (isLayout + ? components.layout?.[0]?.() + : components.page?.[0]?.()) + + if (page) { + parentSegments.push(page) + } + + const config = mod ? collectAppConfig(mod) : undefined + const isClientComponent = isClientReference(mod) + + const isDynamicSegment = /^\[.+\]$/.test(page) + + const { generateStaticParams, getStaticPaths } = mod || {} - const result = { - isLayout, - isDynamicSegment, - segmentPath: `/${parentSegments.join('/')}${ + if (isDynamicSegment && isClientComponent && generateStaticParams) { + throw new Error( + `Page "${page}" cannot export "generateStaticParams()" because it is a client component` + ) + } + + const segmentPath = `/${parentSegments.join('/')}${ page && parentSegments.length > 0 ? '/' : '' - }${page}`, - config, - getStaticPaths: isClientComponent ? undefined : getStaticPaths, - generateStaticParams: isClientComponent ? undefined : generateStaticParams, - } + }${page}` + + const result: GenerateParamsResult = { + isLayout, + isDynamicSegment, + segmentPath, + config, + getStaticPaths: !isClientComponent ? getStaticPaths : undefined, + generateStaticParams: !isClientComponent + ? generateStaticParams + : undefined, + } - if (page) { - parentSegments.push(page) - } + // If the configuration contributes to the static generation, then add it + // to the list. + if ( + result.config || + result.generateStaticParams || + result.getStaticPaths || + isDynamicSegment + ) { + generateParams.push(result) + } - if (result.config || result.generateStaticParams || result.getStaticPaths) { - generateParams.push(result) - } else if (isDynamicSegment) { - // It is a dynamic route, but no config was provided - generateParams.push(result) + // Use this route's parallel route children as the next segment. + currentLoaderTree = parallelRoutes.children } - return collectGenerateParams( - segment[1]?.children, - parentSegments, - generateParams - ) + return generateParams } export async function buildAppStaticPaths({ @@ -1246,7 +1280,7 @@ export async function buildAppStaticPaths({ dir: string page: string configFileName: string - generateParams: GenerateParams + generateParams: GenerateParamsResults incrementalCacheHandlerPath?: string distDir: string isrFlushToDisk?: boolean @@ -1317,18 +1351,18 @@ export async function buildAppStaticPaths({ } else { // if generateStaticParams is being used we iterate over them // collecting them from each level - type Params = Array> let hadAllParamsGenerated = false const buildParams = async ( - paramsItems: Params = [{}], + paramsItems: Params[] = [{}], idx = 0 - ): Promise => { + ): Promise => { const curGenerate = generateParams[idx] if (idx === generateParams.length) { return paramsItems } + if ( typeof curGenerate.generateStaticParams !== 'function' && idx < generateParams.length @@ -1343,22 +1377,27 @@ export async function buildAppStaticPaths({ } hadAllParamsGenerated = true - const newParams = [] + const newParams: Params[] = [] - for (const params of paramsItems) { - const result = await curGenerate.generateStaticParams({ params }) - // TODO: validate the result is valid here or wait for - // buildStaticPaths to validate? - for (const item of result) { - newParams.push({ ...params, ...item }) + if (curGenerate.generateStaticParams) { + for (const params of paramsItems) { + const result = await curGenerate.generateStaticParams({ + params, + }) + // TODO: validate the result is valid here or wait for buildStaticPaths to validate? + for (const item of result) { + newParams.push({ ...params, ...item }) + } } } if (idx < generateParams.length) { return buildParams(newParams, idx + 1) } + return newParams } + const builtParams = await buildParams() const fallback = !generateParams.some( // TODO: dynamic params should be allowed @@ -1499,7 +1538,7 @@ export async function isPageStatic({ isAppPath: pageType === 'app', }) } - const Comp = componentsResult.Component || {} + const Comp = componentsResult.Component as NextComponentType | undefined let staticPathsResult: GetStaticPathsResult | undefined const routeModule: RouteModule = @@ -1512,7 +1551,7 @@ export async function isPageStatic({ const { tree } = ComponentMod - const generateParams: GenerateParams = + const generateParams: GenerateParamsResults = routeModule && isAppRouteRouteModule(routeModule) ? [ { @@ -1604,7 +1643,7 @@ export async function isPageStatic({ } } - const hasGetInitialProps = !!(Comp as any).getInitialProps + const hasGetInitialProps = !!Comp?.getInitialProps const hasStaticProps = !!componentsResult.getStaticProps const hasStaticPaths = !!componentsResult.getStaticPaths const hasServerProps = !!componentsResult.getServerSideProps diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index f99f449a32c44..522d55fc61aea 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -13,7 +13,6 @@ import { AppRouterContext, LayoutRouterContext, GlobalLayoutRouterContext, - CacheStates, } from '../../shared/lib/app-router-context.shared-runtime' import type { CacheNode, @@ -149,8 +148,7 @@ function HistoryUpdater({ } export const createEmptyCacheNode = () => ({ - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), }) diff --git a/packages/next/src/client/components/layout-router.tsx b/packages/next/src/client/components/layout-router.tsx index 9401adab52a50..9deacefcc3706 100644 --- a/packages/next/src/client/components/layout-router.tsx +++ b/packages/next/src/client/components/layout-router.tsx @@ -12,7 +12,6 @@ import type { FocusAndScrollRef } from './router-reducer/router-reducer-types' import React, { useContext, use, startTransition, Suspense } from 'react' import ReactDOM from 'react-dom' import { - CacheStates, LayoutRouterContext, GlobalLayoutRouterContext, TemplateContext, @@ -338,8 +337,16 @@ function InnerLayoutRouter({ // Read segment path from the parallel router cache node. let childNode = childNodes.get(cacheKey) - // When childNode is not available during rendering client-side we need to fetch it from the server. - if (!childNode || childNode.status === CacheStates.LAZY_INITIALIZED) { + // When data is not available during rendering client-side we need to fetch + // it from the server. + if ( + !childNode || + // Check if this is a lazy cache entry that has not yet initiated a + // data request. + // + // TODO: An eventual goal of PPR is to remove this case entirely. + (childNode.subTreeData === null && childNode.lazyData === null) + ) { /** * Router state with refetch marker added */ @@ -347,22 +354,15 @@ function InnerLayoutRouter({ const refetchTree = walkAddRefetch(['', ...segmentPath], fullTree) childNode = { - status: CacheStates.DATA_FETCH, - data: fetchServerResponse( + lazyData: fetchServerResponse( new URL(url, location.origin), refetchTree, context.nextUrl, buildId ), subTreeData: null, - head: - childNode && childNode.status === CacheStates.LAZY_INITIALIZED - ? childNode.head - : undefined, - parallelRoutes: - childNode && childNode.status === CacheStates.LAZY_INITIALIZED - ? childNode.parallelRoutes - : new Map(), + head: childNode ? childNode.head : undefined, + parallelRoutes: childNode ? childNode.parallelRoutes : new Map(), } /** @@ -377,20 +377,20 @@ function InnerLayoutRouter({ } // This case should never happen so it throws an error. It indicates there's a bug in the Next.js. - if (childNode.subTreeData && childNode.data) { - throw new Error('Child node should not have both subTreeData and data') + if (childNode.subTreeData && childNode.lazyData) { + throw new Error('Child node should not have both subTreeData and lazyData') } // If cache node has a data request we have to unwrap response by `use` and update the cache. - if (childNode.data) { + if (childNode.lazyData) { /** * Flight response data */ // When the data has not resolved yet `use` will suspend here. - const [flightData, overrideCanonicalUrl] = use(childNode.data) + const [flightData, overrideCanonicalUrl] = use(childNode.lazyData) // segmentPath from the server does not match the layout's segmentPath - childNode.data = null + childNode.lazyData = null // setTimeout is used to start a new transition during render, this is an intentional hack around React. setTimeout(() => { @@ -402,7 +402,7 @@ function InnerLayoutRouter({ use(createInfinitePromise()) } - // If cache node has no subTreeData and no data request we have to infinitely suspend as the data will likely flow in from another place. + // If cache node has no subTreeData and no lazy data request we have to infinitely suspend as the data will likely flow in from another place. // TODO-APP: double check users can't return null in a component that will kick in here. if (!childNode.subTreeData) { use(createInfinitePromise()) diff --git a/packages/next/src/client/components/router-reducer/apply-flight-data.ts b/packages/next/src/client/components/router-reducer/apply-flight-data.ts index accdcd89aefa9..f72365b297edb 100644 --- a/packages/next/src/client/components/router-reducer/apply-flight-data.ts +++ b/packages/next/src/client/components/router-reducer/apply-flight-data.ts @@ -1,4 +1,3 @@ -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightDataPath } from '../../../server/app-render/types' import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head' @@ -20,7 +19,6 @@ export function applyFlightData( if (flightDataPath.length === 3) { const subTreeData = cacheNodeSeedData[2] - cache.status = CacheStates.READY cache.subTreeData = subTreeData fillLazyItemsTillLeafWithHead( cache, @@ -32,7 +30,6 @@ export function applyFlightData( ) } else { // Copy subTreeData for the root node of the cache. - cache.status = CacheStates.READY cache.subTreeData = existingCache.subTreeData cache.parallelRoutes = new Map(existingCache.parallelRoutes) // Create a copy of the existing cache with the subTreeData applied. diff --git a/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx b/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx index 274b9b7f7af5f..4004d3a19eded 100644 --- a/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx +++ b/packages/next/src/client/components/router-reducer/create-initial-router-state.test.tsx @@ -1,6 +1,5 @@ import React from 'react' import type { FlightRouterState } from '../../../server/app-render/types' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from './create-initial-router-state' @@ -56,8 +55,7 @@ describe('createInitialRouterState', () => { }) const expectedCache: CacheNode = { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: children, parallelRoutes: new Map([ [ @@ -66,7 +64,6 @@ describe('createInitialRouterState', () => { [ 'linking', { - status: CacheStates.LAZY_INITIALIZED, parallelRoutes: new Map([ [ 'children', @@ -74,8 +71,7 @@ describe('createInitialRouterState', () => { [ '', { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: Test, @@ -84,7 +80,7 @@ describe('createInitialRouterState', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: null, }, ], diff --git a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts index 8e2c6402a1548..a00149d410e99 100644 --- a/packages/next/src/client/components/router-reducer/create-initial-router-state.ts +++ b/packages/next/src/client/components/router-reducer/create-initial-router-state.ts @@ -5,7 +5,6 @@ import type { CacheNodeSeedData, } from '../../../server/app-render/types' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import { createHrefFromUrl } from './create-href-from-url' import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head' import { extractPathFromFlightRouterState } from './compute-changed-path' @@ -34,8 +33,7 @@ export function createInitialRouterState({ const subTreeData = initialSeedData[2] const cache: CacheNode = { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: subTreeData, // 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, diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx index 64570b73dda61..6ee61cee245fa 100644 --- a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx +++ b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.test.tsx @@ -1,7 +1,6 @@ import React from 'react' import type { FetchServerResponseResult } from './fetch-server-response' import { fillCacheWithDataProperty } from './fill-cache-with-data-property' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' describe('fillCacheWithDataProperty', () => { @@ -23,14 +22,12 @@ describe('fillCacheWithDataProperty', () => { .flat() const cache: CacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } const existingCache: CacheNode = { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Root layout, parallelRoutes: new Map([ [ @@ -39,8 +36,7 @@ describe('fillCacheWithDataProperty', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -49,8 +45,7 @@ describe('fillCacheWithDataProperty', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -71,37 +66,33 @@ describe('fillCacheWithDataProperty', () => { expect(cache).toMatchInlineSnapshot(` { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Page , }, }, }, - "status": "READY", "subTreeData": Linking , }, "dashboard" => { - "data": Promise {}, + "lazyData": Promise {}, "parallelRoutes": Map {}, - "status": "DATAFETCH", "subTreeData": null, }, }, }, - "status": "LAZYINITIALIZED", "subTreeData": null, } `) diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts index 27ecd0042a7ae..eaf5795f6a84a 100644 --- a/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts +++ b/packages/next/src/client/components/router-reducer/fill-cache-with-data-property.ts @@ -1,6 +1,5 @@ import type { FetchServerResponseResult } from './fetch-server-response' import type { FlightSegmentPath } from '../../../server/app-render/types' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import { createRouterCacheKey } from './create-router-cache-key' @@ -35,12 +34,11 @@ export function fillCacheWithDataProperty( if (isLastEntry) { if ( !childCacheNode || - !childCacheNode.data || + !childCacheNode.lazyData || childCacheNode === existingChildCacheNode ) { childSegmentMap.set(cacheKey, { - status: CacheStates.DATA_FETCH, - data: fetchResponse(), + lazyData: fetchResponse(), subTreeData: null, parallelRoutes: new Map(), }) @@ -52,8 +50,7 @@ export function fillCacheWithDataProperty( // Start fetch in the place where the existing cache doesn't have the data yet. if (!childCacheNode) { childSegmentMap.set(cacheKey, { - status: CacheStates.DATA_FETCH, - data: fetchResponse(), + lazyData: fetchResponse(), subTreeData: null, parallelRoutes: new Map(), }) @@ -63,8 +60,7 @@ export function fillCacheWithDataProperty( if (childCacheNode === existingChildCacheNode) { childCacheNode = { - status: childCacheNode.status, - data: childCacheNode.data, + lazyData: childCacheNode.lazyData, subTreeData: childCacheNode.subTreeData, parallelRoutes: new Map(childCacheNode.parallelRoutes), } as CacheNode diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx index cd6d5e561cba4..5b477051b4bd1 100644 --- a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx +++ b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.test.tsx @@ -1,6 +1,5 @@ import React from 'react' import { fillCacheWithNewSubTreeData } from './fill-cache-with-new-subtree-data' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightData } from '../../../server/app-render/types' @@ -28,14 +27,12 @@ const getFlightData = (): FlightData => { describe('fillCacheWithNewSubtreeData', () => { it('should apply subTreeData and head property', () => { const cache: CacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } const existingCache: CacheNode = { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Root layout, parallelRoutes: new Map([ [ @@ -44,8 +41,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -54,8 +50,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -82,8 +77,7 @@ describe('fillCacheWithNewSubtreeData', () => { fillCacheWithNewSubTreeData(cache, existingCache, flightDataPath, false) const expectedCache: CacheNode = { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([ [ @@ -92,8 +86,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -103,8 +96,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -112,7 +104,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ 'about', { - data: null, + lazyData: null, parallelRoutes: new Map([ [ 'children', @@ -120,8 +112,7 @@ describe('fillCacheWithNewSubtreeData', () => { [ '', { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -135,7 +126,6 @@ describe('fillCacheWithNewSubtreeData', () => { ], ]), subTreeData:

SubTreeData Injected!

, - status: CacheStates.READY, }, ], ]), diff --git a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts index 4668dfd8f48ac..65e98c4763e96 100644 --- a/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts +++ b/packages/next/src/client/components/router-reducer/fill-cache-with-new-subtree-data.ts @@ -1,4 +1,3 @@ -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightDataPath, @@ -43,14 +42,13 @@ export function fillCacheWithNewSubTreeData( if (isLastEntry) { if ( !childCacheNode || - !childCacheNode.data || + !childCacheNode.lazyData || childCacheNode === existingChildCacheNode ) { const seedData: CacheNodeSeedData = flightDataPath[3] const subTreeData = seedData[2] childCacheNode = { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData, // Ensure segments other than the one we got data for are preserved. parallelRoutes: existingChildCacheNode @@ -88,8 +86,7 @@ export function fillCacheWithNewSubTreeData( if (childCacheNode === existingChildCacheNode) { childCacheNode = { - status: childCacheNode.status, - data: childCacheNode.data, + lazyData: childCacheNode.lazyData, subTreeData: childCacheNode.subTreeData, parallelRoutes: new Map(childCacheNode.parallelRoutes), } as CacheNode diff --git a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx index 824c58c31090b..0cd9d85fe36a5 100644 --- a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx +++ b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.test.tsx @@ -1,6 +1,5 @@ import React from 'react' import { fillLazyItemsTillLeafWithHead } from './fill-lazy-items-till-leaf-with-head' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightData } from '../../../server/app-render/types' @@ -37,14 +36,12 @@ const getFlightData = (): FlightData => { describe('fillLazyItemsTillLeafWithHead', () => { it('should fill lazy items till leaf with head', () => { const cache: CacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } const existingCache: CacheNode = { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Root layout, parallelRoutes: new Map([ [ @@ -53,8 +50,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -63,8 +59,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -97,8 +92,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { ) const expectedCache: CacheNode = { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([ [ @@ -107,8 +101,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { [ 'linking', { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([ [ @@ -117,7 +110,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { [ 'about', { - data: null, + lazyData: null, parallelRoutes: new Map([ [ 'children', @@ -125,8 +118,7 @@ describe('fillLazyItemsTillLeafWithHead', () => { [ '', { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -140,14 +132,12 @@ describe('fillLazyItemsTillLeafWithHead', () => { ], ]), subTreeData: null, - status: CacheStates.LAZY_INITIALIZED, }, ], [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, diff --git a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts index 12f4a712ae114..90630f4bb9918 100644 --- a/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts +++ b/packages/next/src/client/components/router-reducer/fill-lazy-items-till-leaf-with-head.ts @@ -1,4 +1,3 @@ -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightRouterState, @@ -52,8 +51,7 @@ export function fillLazyItemsTillLeafWithHead( // New data was sent from the server. const seedNode = parallelSeedData[2] newCacheNode = { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: seedNode, parallelRoutes: new Map(existingCacheNode?.parallelRoutes), } @@ -61,8 +59,7 @@ export function fillLazyItemsTillLeafWithHead( // No new data was sent from the server, but the existing cache node // was prefetched, so we should reuse that. newCacheNode = { - status: existingCacheNode.status, - data: existingCacheNode.data, + lazyData: existingCacheNode.lazyData, subTreeData: existingCacheNode.subTreeData, parallelRoutes: new Map(existingCacheNode.parallelRoutes), } as CacheNode @@ -70,8 +67,7 @@ export function fillLazyItemsTillLeafWithHead( // No data available for this node. This will trigger a lazy fetch // during render. newCacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(existingCacheNode?.parallelRoutes), } @@ -99,8 +95,7 @@ export function fillLazyItemsTillLeafWithHead( // New data was sent from the server. const seedNode = parallelSeedData[2] newCacheNode = { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: seedNode, parallelRoutes: new Map(), } @@ -108,8 +103,7 @@ export function fillLazyItemsTillLeafWithHead( // No data available for this node. This will trigger a lazy fetch // during render. newCacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx index 08bdcd2c4ad78..a68cca2b6ff52 100644 --- a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx +++ b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.test.tsx @@ -1,7 +1,6 @@ import React from 'react' import type { FlightData } from '../../../server/app-render/types' import { invalidateCacheBelowFlightSegmentPath } from './invalidate-cache-below-flight-segmentpath' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import { fillCacheWithNewSubTreeData } from './fill-cache-with-new-subtree-data' @@ -29,14 +28,12 @@ const getFlightData = (): FlightData => { describe('invalidateCacheBelowFlightSegmentPath', () => { it('should invalidate cache below flight segment path', () => { const cache: CacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } const existingCache: CacheNode = { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Root layout, parallelRoutes: new Map([ [ @@ -45,8 +42,7 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -55,8 +51,7 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -81,10 +76,7 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { const flightDataPath = flightData[0] const flightSegmentPath = flightDataPath.slice(0, -3) - // @ts-expect-error TODO-APP: investigate why this is not a TS error in router-reducer. - cache.status = CacheStates.READY // Copy subTreeData for the root node of the cache. - // @ts-expect-error TODO-APP: investigate why this is not a TS error in router-reducer. cache.subTreeData = existingCache.subTreeData // Create a copy of the existing cache with the subTreeData applied. fillCacheWithNewSubTreeData(cache, existingCache, flightDataPath, false) @@ -97,7 +89,7 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { ) const expectedCache: CacheNode = { - data: null, + lazyData: null, parallelRoutes: new Map([ [ 'children', @@ -105,7 +97,7 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { [ 'linking', { - data: null, + lazyData: null, parallelRoutes: new Map([ [ 'children', @@ -113,23 +105,20 @@ describe('invalidateCacheBelowFlightSegmentPath', () => { [ '', { - data: null, + lazyData: null, parallelRoutes: new Map(), - status: CacheStates.READY, subTreeData: Page, }, ], ]), ], ]), - status: CacheStates.READY, subTreeData: Linking, }, ], ]), ], ]), - status: CacheStates.READY, subTreeData: <>Root layout, } diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts index d637d850b145a..cb9f6c658103e 100644 --- a/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts +++ b/packages/next/src/client/components/router-reducer/invalidate-cache-below-flight-segmentpath.ts @@ -47,8 +47,7 @@ export function invalidateCacheBelowFlightSegmentPath( if (childCacheNode === existingChildCacheNode) { childCacheNode = { - status: childCacheNode.status, - data: childCacheNode.data, + lazyData: childCacheNode.lazyData, subTreeData: childCacheNode.subTreeData, parallelRoutes: new Map(childCacheNode.parallelRoutes), } as CacheNode diff --git a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx index c365d6ae9765e..c4816ab247c8e 100644 --- a/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx +++ b/packages/next/src/client/components/router-reducer/invalidate-cache-by-router-state.test.tsx @@ -1,20 +1,17 @@ import React from 'react' import { invalidateCacheByRouterState } from './invalidate-cache-by-router-state' -import { CacheStates } from '../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../shared/lib/app-router-context.shared-runtime' import type { FlightRouterState } from '../../../server/app-render/types' describe('invalidateCacheByRouterState', () => { it('should invalidate the cache by router state', () => { const cache: CacheNode = { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), } const existingCache: CacheNode = { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Root layout, parallelRoutes: new Map([ [ @@ -23,8 +20,7 @@ describe('invalidateCacheByRouterState', () => { [ 'linking', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Linking, parallelRoutes: new Map([ [ @@ -33,8 +29,7 @@ describe('invalidateCacheByRouterState', () => { [ '', { - data: null, - status: CacheStates.READY, + lazyData: null, subTreeData: <>Page, parallelRoutes: new Map(), }, @@ -72,8 +67,7 @@ describe('invalidateCacheByRouterState', () => { invalidateCacheByRouterState(cache, existingCache, routerState) const expectedCache: CacheNode = { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([['children', new Map()]]), } diff --git a/packages/next/src/client/components/router-reducer/reducers/fast-refresh-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/fast-refresh-reducer.ts index 41293852a8468..5929959b3a322 100644 --- a/packages/next/src/client/components/router-reducer/reducers/fast-refresh-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/fast-refresh-reducer.ts @@ -28,14 +28,14 @@ function fastRefreshReducerImpl( const cache: CacheNode = createEmptyCacheNode() // TODO-APP: verify that `href` is not an external url. // Fetch data from the root of the tree. - cache.data = fetchServerResponse( + cache.lazyData = fetchServerResponse( new URL(href, origin), [state.tree[0], state.tree[1], state.tree[2], 'refetch'], state.nextUrl, state.buildId ) - return cache.data.then( + return cache.lazyData.then( ([flightData, canonicalUrlOverride]) => { // Handle case when navigating to page in `pages` from `app` if (typeof flightData === 'string') { @@ -47,8 +47,8 @@ function fastRefreshReducerImpl( ) } - // Remove cache.data as it has been resolved at this point. - cache.data = null + // Remove cache.lazyData as it has been resolved at this point. + cache.lazyData = null let currentTree = state.tree let currentCache = state.cache diff --git a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx index f3eaaad8a5c64..b7d73c1b6080f 100644 --- a/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/find-head-in-cache.test.tsx @@ -1,6 +1,5 @@ import React from 'react' import type { FlightRouterState } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { findHeadInCache } from './find-head-in-cache' @@ -27,8 +26,7 @@ describe('findHeadInCache', () => { ] const cache: CacheNode = { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([ [ @@ -37,8 +35,7 @@ describe('findHeadInCache', () => { [ 'linking', { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map([ [ @@ -47,7 +44,7 @@ describe('findHeadInCache', () => { [ 'about', { - data: null, + lazyData: null, parallelRoutes: new Map([ [ 'children', @@ -55,8 +52,7 @@ describe('findHeadInCache', () => { [ '', { - data: null, - status: CacheStates.LAZY_INITIALIZED, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -70,15 +66,13 @@ describe('findHeadInCache', () => { ], ]), subTreeData: null, - status: CacheStates.LAZY_INITIALIZED, }, ], // TODO-APP: this segment should be preserved when creating the new cache // [ // '', // { - // data: null, - // status: CacheStates.READY, + // lazyData: null, // subTreeData: <>Page, // parallelRoutes: new Map(), // }, diff --git a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx index b76a2932f9b64..2062375b3f09e 100644 --- a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.test.tsx @@ -2,7 +2,6 @@ import React from 'react' import type { fetchServerResponse as fetchServerResponseType } from '../fetch-server-response' import type { FlightData } from '../../../../server/app-render/types' import type { FlightRouterState } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from '../create-initial-router-state' import { @@ -133,7 +132,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -141,8 +139,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -150,7 +147,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -183,53 +180,48 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "about" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, "head": About page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

About Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -326,7 +318,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -334,8 +325,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -343,7 +333,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -377,53 +367,48 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "about" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, "head": About page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

About Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -520,7 +505,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -528,8 +512,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -537,7 +520,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -574,31 +557,28 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -657,7 +637,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -665,8 +644,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -674,7 +652,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -711,31 +689,28 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -794,7 +769,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -802,8 +776,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -811,7 +784,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -845,31 +818,28 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -952,7 +922,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -960,8 +929,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -969,7 +937,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -1040,53 +1008,48 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "about" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, "head": About page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

About Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -1199,7 +1162,6 @@ describe('navigateReducer', () => { [ 'parallel-tab-bar', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'audience', @@ -1207,8 +1169,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Audience Page, parallelRoutes: new Map(), }, @@ -1221,8 +1182,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Views Page, parallelRoutes: new Map(), }, @@ -1235,8 +1195,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Children Page, parallelRoutes: new Map(), }, @@ -1244,7 +1203,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Layout level, }, ], @@ -1278,47 +1237,43 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "parallel-tab-bar" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "audience" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Audience Page , }, "demographics" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, "head": Demographics Head , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, "views" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Views Page , @@ -1326,21 +1281,18 @@ describe('navigateReducer', () => { }, "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Children Page , }, }, }, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData": @@ -1453,7 +1405,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -1461,8 +1412,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -1470,7 +1420,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -1504,31 +1454,28 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -1587,7 +1534,6 @@ describe('navigateReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -1595,8 +1541,7 @@ describe('navigateReducer', () => { [ '__PAGE__', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -1604,7 +1549,7 @@ describe('navigateReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -1637,53 +1582,48 @@ describe('navigateReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "about" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "__PAGE__" => { - "data": null, "head": About page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

About Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": diff --git a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts index 32c70df6d24d9..93ef67d668357 100644 --- a/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts @@ -1,4 +1,3 @@ -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import type { FlightRouterState, @@ -78,7 +77,6 @@ function addRefetchToLeafSegments( ) { let appliedPatch = false - newCache.status = CacheStates.READY newCache.subTreeData = currentCache.subTreeData newCache.parallelRoutes = new Map(currentCache.parallelRoutes) @@ -239,7 +237,6 @@ export function navigateReducer( ) if (hardNavigate) { - cache.status = CacheStates.READY // Copy subTreeData for the root node of the cache. cache.subTreeData = currentCache.subTreeData diff --git a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx index a30b46e811183..cc2e42ec2550a 100644 --- a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.test.tsx @@ -2,7 +2,6 @@ import React from 'react' import type { fetchServerResponse as fetchServerResponseType } from '../fetch-server-response' import type { FlightData } from '../../../../server/app-render/types' import type { FlightRouterState } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from '../create-initial-router-state' import { ACTION_PREFETCH, PrefetchKind } from '../router-reducer-types' @@ -87,7 +86,6 @@ describe('prefetchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -95,8 +93,7 @@ describe('prefetchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -104,7 +101,7 @@ describe('prefetchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -183,8 +180,7 @@ describe('prefetchReducer', () => { }, canonicalUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -229,7 +225,6 @@ describe('prefetchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -237,8 +232,7 @@ describe('prefetchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -246,7 +240,7 @@ describe('prefetchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -339,8 +333,7 @@ describe('prefetchReducer', () => { }, canonicalUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( diff --git a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx index 2622dd3a33e3c..3061f438d03c9 100644 --- a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.test.tsx @@ -2,7 +2,6 @@ import React from 'react' import type { fetchServerResponse } from '../fetch-server-response' import type { FlightData } from '../../../../server/app-render/types' import type { FlightRouterState } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from '../create-initial-router-state' import { ACTION_REFRESH } from '../router-reducer-types' @@ -98,7 +97,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -106,8 +104,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -115,7 +112,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -159,8 +156,7 @@ describe('refreshReducer', () => { canonicalUrl: '/linking', nextUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -176,7 +172,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.LAZY_INITIALIZED, parallelRoutes: new Map([ [ 'children', @@ -184,8 +179,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -198,7 +192,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: null, }, ], @@ -241,7 +235,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -249,8 +242,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -258,7 +250,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -316,8 +308,7 @@ describe('refreshReducer', () => { canonicalUrl: '/linking', nextUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -333,7 +324,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.LAZY_INITIALIZED, parallelRoutes: new Map([ [ 'children', @@ -341,8 +331,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -355,7 +344,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: null, }, ], @@ -398,7 +387,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -406,8 +394,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -415,14 +402,13 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], [ 'about', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -430,8 +416,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>About page, parallelRoutes: new Map(), }, @@ -439,7 +424,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>About layout level, }, ], @@ -497,8 +482,7 @@ describe('refreshReducer', () => { canonicalUrl: '/linking', nextUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -514,7 +498,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.LAZY_INITIALIZED, parallelRoutes: new Map([ [ 'children', @@ -522,8 +505,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -536,7 +518,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: null, }, ], @@ -579,7 +561,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -587,8 +568,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -596,14 +576,13 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], [ 'about', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -611,8 +590,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>About page, parallelRoutes: new Map(), }, @@ -620,7 +598,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>About layout level, }, ], @@ -727,8 +705,7 @@ describe('refreshReducer', () => { canonicalUrl: '/linking', nextUrl: '/linking', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -744,7 +721,6 @@ describe('refreshReducer', () => { [ 'linking', { - status: CacheStates.LAZY_INITIALIZED, parallelRoutes: new Map([ [ 'children', @@ -752,8 +728,7 @@ describe('refreshReducer', () => { [ '', { - status: CacheStates.LAZY_INITIALIZED, - data: null, + lazyData: null, subTreeData: null, parallelRoutes: new Map(), head: ( @@ -766,7 +741,7 @@ describe('refreshReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: null, }, ], diff --git a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts index a06db76f9b70c..c3c239157b4a6 100644 --- a/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/refresh-reducer.ts @@ -10,10 +10,7 @@ import type { } from '../router-reducer-types' import { handleExternalUrl } from './navigate-reducer' import { handleMutable } from '../handle-mutable' -import { - CacheStates, - type CacheNode, -} from '../../../../shared/lib/app-router-context.shared-runtime' +import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head' import { createEmptyCacheNode } from '../../app-router' @@ -32,14 +29,14 @@ export function refreshReducer( const cache: CacheNode = createEmptyCacheNode() // TODO-APP: verify that `href` is not an external url. // Fetch data from the root of the tree. - cache.data = fetchServerResponse( + cache.lazyData = fetchServerResponse( new URL(href, origin), [currentTree[0], currentTree[1], currentTree[2], 'refetch'], state.nextUrl, state.buildId ) - return cache.data.then( + return cache.lazyData.then( ([flightData, canonicalUrlOverride]) => { // Handle case when navigating to page in `pages` from `app` if (typeof flightData === 'string') { @@ -51,8 +48,8 @@ export function refreshReducer( ) } - // Remove cache.data as it has been resolved at this point. - cache.data = null + // Remove cache.lazyData as it has been resolved at this point. + cache.lazyData = null for (const flightDataPath of flightData) { // FlightDataPath with more than two items means unexpected Flight data was returned @@ -98,7 +95,6 @@ export function refreshReducer( // Handles case where prefetch only returns the router tree patch without rendered components. if (cacheNodeSeedData !== null) { const subTreeData = cacheNodeSeedData[2] - cache.status = CacheStates.READY cache.subTreeData = subTreeData fillLazyItemsTillLeafWithHead( cache, diff --git a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx index 50b1d2be335e9..5ae62da8e7b64 100644 --- a/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/restore-reducer.test.tsx @@ -1,6 +1,5 @@ import React from 'react' import type { FlightRouterState } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from '../create-initial-router-state' import { ACTION_RESTORE } from '../router-reducer-types' @@ -54,7 +53,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -62,8 +60,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -71,7 +68,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -134,8 +131,7 @@ describe('serverPatchReducer', () => { canonicalUrl: '/linking/about', nextUrl: '/linking/about', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -149,7 +145,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -157,8 +152,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -166,7 +160,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -209,7 +203,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -217,8 +210,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -226,7 +218,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -302,8 +294,7 @@ describe('serverPatchReducer', () => { canonicalUrl: '/linking/about', nextUrl: '/linking/about', cache: { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: ( @@ -317,7 +308,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -325,8 +315,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -334,7 +323,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], diff --git a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts index 3fd988a3bb510..596c6e41d1222 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/server-action-reducer.ts @@ -33,10 +33,7 @@ import { createHrefFromUrl } from '../create-href-from-url' import { handleExternalUrl } from './navigate-reducer' import { applyRouterStatePatchToTree } from '../apply-router-state-patch-to-tree' import { isNavigatingToNewRootLayout } from '../is-navigating-to-new-root-layout' -import { - CacheStates, - type CacheNode, -} from '../../../../shared/lib/app-router-context.shared-runtime' +import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { handleMutable } from '../handle-mutable' import { fillLazyItemsTillLeafWithHead } from '../fill-lazy-items-till-leaf-with-head' import { createEmptyCacheNode } from '../../app-router' @@ -247,7 +244,6 @@ export function serverActionReducer( // Handles case where prefetch only returns the router tree patch without rendered components. if (subTreeData !== null) { const cache: CacheNode = createEmptyCacheNode() - cache.status = CacheStates.READY cache.subTreeData = subTreeData fillLazyItemsTillLeafWithHead( cache, diff --git a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx index 2e758ea0cfa11..120bac2d7c8ea 100644 --- a/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx +++ b/packages/next/src/client/components/router-reducer/reducers/server-patch-reducer.test.tsx @@ -4,7 +4,6 @@ import type { FlightData, FlightRouterState, } from '../../../../server/app-render/types' -import { CacheStates } from '../../../../shared/lib/app-router-context.shared-runtime' import type { CacheNode } from '../../../../shared/lib/app-router-context.shared-runtime' import { createInitialRouterState } from '../create-initial-router-state' import { ACTION_SERVER_PATCH, ACTION_NAVIGATE } from '../router-reducer-types' @@ -105,7 +104,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -113,8 +111,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -122,7 +119,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -166,53 +163,48 @@ describe('serverPatchReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "somewhere-else" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, "head": Somewhere page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

Somewhere Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": @@ -276,7 +268,6 @@ describe('serverPatchReducer', () => { [ 'linking', { - status: CacheStates.READY, parallelRoutes: new Map([ [ 'children', @@ -284,8 +275,7 @@ describe('serverPatchReducer', () => { [ '', { - status: CacheStates.READY, - data: null, + lazyData: null, subTreeData: <>Linking page, parallelRoutes: new Map(), }, @@ -293,7 +283,7 @@ describe('serverPatchReducer', () => { ]), ], ]), - data: null, + lazyData: null, subTreeData: <>Linking layout level, }, ], @@ -349,75 +339,68 @@ describe('serverPatchReducer', () => { { "buildId": "development", "cache": { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "linking" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, + "lazyData": null, "parallelRoutes": Map {}, - "status": "READY", "subTreeData": Linking page , }, "about" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, "head": About page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

About Page!

, }, "somewhere-else" => { - "data": null, + "lazyData": null, "parallelRoutes": Map { "children" => Map { "" => { - "data": null, "head": Somewhere page! , + "lazyData": null, "parallelRoutes": Map {}, - "status": "LAZYINITIALIZED", "subTreeData": null, }, }, }, - "status": "READY", "subTreeData":

Somewhere Page!

, }, }, }, - "status": "READY", "subTreeData": Linking layout level , }, }, }, - "status": "READY", "subTreeData": diff --git a/packages/next/src/server/dev/static-paths-worker.ts b/packages/next/src/server/dev/static-paths-worker.ts index 32f052193584a..080f0cd32e665 100644 --- a/packages/next/src/server/dev/static-paths-worker.ts +++ b/packages/next/src/server/dev/static-paths-worker.ts @@ -8,7 +8,7 @@ import { buildStaticPaths, collectGenerateParams, } from '../../build/utils' -import type { GenerateParams } from '../../build/utils' +import type { GenerateParamsResults } from '../../build/utils' import { loadComponents } from '../load-components' import { setHttpClientAndAgentOptions } from '../setup-http-agent-env' import type { IncrementalCache } from '../lib/incremental-cache' @@ -83,7 +83,7 @@ export async function loadStaticPaths({ if (isAppPath) { const { routeModule } = components - const generateParams: GenerateParams = + const generateParams: GenerateParamsResults = routeModule && isAppRouteRouteModule(routeModule) ? [ { diff --git a/packages/next/src/shared/lib/app-router-context.shared-runtime.ts b/packages/next/src/shared/lib/app-router-context.shared-runtime.ts index 6b6ee05e900c8..e05ce65db1273 100644 --- a/packages/next/src/shared/lib/app-router-context.shared-runtime.ts +++ b/packages/next/src/shared/lib/app-router-context.shared-runtime.ts @@ -13,59 +13,57 @@ import React from 'react' export type ChildSegmentMap = Map -// eslint-disable-next-line no-shadow -export enum CacheStates { - LAZY_INITIALIZED = 'LAZYINITIALIZED', - DATA_FETCH = 'DATAFETCH', - READY = 'READY', -} - /** * Cache node used in app-router / layout-router. */ -export type CacheNode = - | { - status: CacheStates.DATA_FETCH - /** - * In-flight request for this node. - */ - data: Promise | null - head?: React.ReactNode - /** - * React Component for this node. - */ - subTreeData: null - /** - * Child parallel routes. - */ - parallelRoutes: Map - } - | { - status: CacheStates.READY - /** - * In-flight request for this node. - */ - data: null - head?: React.ReactNode - /** - * React Component for this node. - */ - subTreeData: React.ReactNode - /** - * Child parallel routes. - */ - parallelRoutes: Map - } - | { - status: CacheStates.LAZY_INITIALIZED - data: null - head?: React.ReactNode - subTreeData: null - /** - * Child parallel routes. - */ - parallelRoutes: Map - } +export type CacheNode = ReadyCacheNode | LazyCacheNode + +export type LazyCacheNode = { + /** + * When subtreeData is null, this is a lazily-initialized cache node. + * + * If the app attempts to render it, it triggers a lazy data fetch, + * postpones the render, and schedules an update to a new tree. + * + * TODO: This mechanism should not be used when PPR is enabled, though it + * currently is in some cases until we've implemented partial + * segment fetching. + */ + subTreeData: null + + /** + * A pending response for the lazy data fetch. If this is not present + * during render, it is lazily created. + */ + lazyData: Promise | null + + head?: React.ReactNode + /** + * Child parallel routes. + */ + parallelRoutes: Map +} + +export type ReadyCacheNode = { + /** + * When subtreeData is not null, it represents the RSC data for the + * corresponding segment. + * + * `null` is a valid React Node but because segment data is always a + * component, we can use `null` to represent empty. + * + * TODO: For additional type safety, update this type to + * Exclude. Need to update createEmptyCacheNode to + * accept subTreeData as an argument, or just inline the callers. + */ + subTreeData: React.ReactNode + /** + * There should never be a lazy data request in this case. + */ + lazyData: null + head?: React.ReactNode + parallelRoutes: Map +} export interface NavigateOptions { scroll?: boolean diff --git a/packages/react-dev-overlay/package.json b/packages/react-dev-overlay/package.json index 468c81219d961..801c3d0b9fbd3 100644 --- a/packages/react-dev-overlay/package.json +++ b/packages/react-dev-overlay/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-dev-overlay", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "A development-only overlay for developing React applications.", "repository": { "url": "vercel/next.js", diff --git a/packages/react-refresh-utils/package.json b/packages/react-refresh-utils/package.json index 86fdcb0a395c3..0dee386fcd720 100644 --- a/packages/react-refresh-utils/package.json +++ b/packages/react-refresh-utils/package.json @@ -1,6 +1,6 @@ { "name": "@next/react-refresh-utils", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "description": "An experimental package providing utilities for React Refresh.", "repository": { "url": "vercel/next.js", diff --git a/packages/third-parties/package.json b/packages/third-parties/package.json index c171893943e7f..80da33f7717f6 100644 --- a/packages/third-parties/package.json +++ b/packages/third-parties/package.json @@ -1,6 +1,6 @@ { "name": "@next/third-parties", - "version": "14.0.5-canary.4", + "version": "14.0.5-canary.6", "repository": { "url": "vercel/next.js", "directory": "packages/third-parties" @@ -25,7 +25,7 @@ "third-party-capital": "1.0.20" }, "devDependencies": { - "next": "14.0.5-canary.4", + "next": "14.0.5-canary.6", "outdent": "0.8.0", "prettier": "2.5.1" }, diff --git a/packages/third-parties/src/google/ga.tsx b/packages/third-parties/src/google/ga.tsx new file mode 100644 index 0000000000000..448325a4aeb59 --- /dev/null +++ b/packages/third-parties/src/google/ga.tsx @@ -0,0 +1,70 @@ +'use client' +// TODO: Evaluate import 'client only' +import React, { useEffect } from 'react' +import Script from 'next/script' + +import type { GAParams } from '../types/google' + +declare global { + interface Window { + dataLayer?: Object[] + } +} + +let currDataLayerName: string | undefined = undefined + +export function GoogleAnalytics(props: GAParams) { + const { gaId, dataLayerName = 'dataLayer' } = props + + if (currDataLayerName === undefined) { + currDataLayerName = dataLayerName + } + + useEffect(() => { + // performance.mark is being used as a feature use signal. While it is traditionally used for performance + // benchmarking it is low overhead and thus considered safe to use in production and it is a widely available + // existing API. + // The performance measurement will be handled by Chrome Aurora + + performance.mark('mark_feature_usage', { + detail: { + feature: 'next-third-parties-ga', + }, + }) + }, []) + + return ( + <> +