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 (
+ <>
+
+
+ >
+ )
+}
+
+export const sendGAEvent = (...args: Object[]) => {
+ if (currDataLayerName === undefined) {
+ console.warn(`@next/third-parties: GA has not been initialized`)
+ return
+ }
+
+ if (window[currDataLayerName]) {
+ window[currDataLayerName].push(...args)
+ } else {
+ console.warn(
+ `@next/third-parties: GA dataLayer ${currDataLayerName} does not exist`
+ )
+ }
+}
diff --git a/packages/third-parties/src/google/gtm.tsx b/packages/third-parties/src/google/gtm.tsx
index 5ea6510395da9..0dc9e70a6f04c 100644
--- a/packages/third-parties/src/google/gtm.tsx
+++ b/packages/third-parties/src/google/gtm.tsx
@@ -22,6 +22,7 @@ export function GoogleTagManager(props: GTMParams) {
// 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: {
diff --git a/packages/third-parties/src/google/index.tsx b/packages/third-parties/src/google/index.tsx
index e5b94408a56e9..907a2695db0df 100644
--- a/packages/third-parties/src/google/index.tsx
+++ b/packages/third-parties/src/google/index.tsx
@@ -1,3 +1,4 @@
export { default as GoogleMapsEmbed } from './google-maps-embed'
export { default as YouTubeEmbed } from './youtube-embed'
export { GoogleTagManager, sendGTMEvent } from './gtm'
+export { GoogleAnalytics, sendGAEvent } from './ga'
diff --git a/packages/third-parties/src/types/google.ts b/packages/third-parties/src/types/google.ts
index acf14f85be921..acfb05eb7c186 100644
--- a/packages/third-parties/src/types/google.ts
+++ b/packages/third-parties/src/types/google.ts
@@ -13,6 +13,11 @@ export type GTMParams = {
preview?: string
}
+export type GAParams = {
+ gaId: string
+ dataLayerName?: string
+}
+
export type GoogleMapsEmbed = {
height?: number
width?: number
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9d445bf016a58..1dea6f135ba40 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -741,7 +741,7 @@ importers:
packages/eslint-config-next:
dependencies:
'@next/eslint-plugin-next':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../eslint-plugin-next
'@rushstack/eslint-patch':
specifier: ^1.3.3
@@ -806,7 +806,7 @@ importers:
packages/next:
dependencies:
'@next/env':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../next-env
'@swc/helpers':
specifier: 0.5.2
@@ -933,19 +933,19 @@ importers:
specifier: 1.1.0
version: 1.1.0
'@next/polyfill-module':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../next-polyfill-module
'@next/polyfill-nomodule':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../next-polyfill-nomodule
'@next/react-dev-overlay':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../react-dev-overlay
'@next/react-refresh-utils':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../react-refresh-utils
'@next/swc':
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../next-swc
'@opentelemetry/api':
specifier: 1.6.0
@@ -1599,7 +1599,7 @@ importers:
version: 1.0.20
devDependencies:
next:
- specifier: 14.0.5-canary.4
+ specifier: 14.0.5-canary.6
version: link:../next
outdent:
specifier: 0.8.0
diff --git a/run-tests.js b/run-tests.js
index 38fa2cdfd4b6b..67925e4c87ee7 100644
--- a/run-tests.js
+++ b/run-tests.js
@@ -508,7 +508,8 @@ ${ENDGROUP}`)
child.on('exit', async (code, signal) => {
children.delete(child)
- if (code !== 0 || signal !== null) {
+ const isChildExitWithNonZero = code !== 0 || signal !== null
+ if (isChildExitWithNonZero) {
if (hideOutput) {
await outputSema.acquire()
const isExpanded =
@@ -550,18 +551,26 @@ ${ENDGROUP}`)
return reject(err)
}
- await fsp
- .rm(
- path.join(
- __dirname,
- 'test/traces',
- path
- .relative(path.join(__dirname, 'test'), test.file)
- .replace(/\//g, '-')
- ),
- { recursive: true, force: true }
- )
- .catch(() => {})
+
+ // If environment is CI and if this test execution is failed after retry, preserve test traces
+ // to upload into github actions artifacts for debugging purpose
+ const shouldPreserveTracesOutput =
+ process.env.CI && isRetry && isChildExitWithNonZero
+ if (!shouldPreserveTracesOutput) {
+ await fsp
+ .rm(
+ path.join(
+ __dirname,
+ 'test/traces',
+ path
+ .relative(path.join(__dirname, 'test'), test.file)
+ .replace(/\//g, '-')
+ ),
+ { recursive: true, force: true }
+ )
+ .catch(() => {})
+ }
+
resolve(new Date().getTime() - start)
})
})
diff --git a/test/e2e/app-dir/third-parties/app/ga/page.js b/test/e2e/app-dir/third-parties/app/ga/page.js
new file mode 100644
index 0000000000000..afbb6419499f0
--- /dev/null
+++ b/test/e2e/app-dir/third-parties/app/ga/page.js
@@ -0,0 +1,23 @@
+'use client'
+
+import React from 'react'
+import { GoogleAnalytics, sendGAEvent } from '@next/third-parties/google'
+
+const Page = () => {
+ const onClick = () => {
+ sendGAEvent({ event: 'buttonClicked', value: 'xyz' })
+ }
+
+ return (
+
+
+
GA
+
+
+
+ )
+}
+
+export default Page
diff --git a/test/e2e/app-dir/third-parties/basic.test.ts b/test/e2e/app-dir/third-parties/basic.test.ts
index 5d4da6ba009ab..01becc3955d89 100644
--- a/test/e2e/app-dir/third-parties/basic.test.ts
+++ b/test/e2e/app-dir/third-parties/basic.test.ts
@@ -54,5 +54,28 @@ createNextDescribe(
const dataLayer2 = await browser.eval('window.dataLayer')
expect(dataLayer2.length).toBe(2)
})
+
+ it('renders GA', async () => {
+ const browser = await next.browser('/ga')
+
+ await browser.waitForElementByCss('#_next-ga')
+ await waitFor(1000)
+
+ const gaInlineScript = await browser.elementsByCss('#_next-ga-init')
+ expect(gaInlineScript.length).toBe(1)
+
+ const gaScript = await browser.elementsByCss(
+ '[src^="https://www.googletagmanager.com/gtag/js?id=GA-XYZ"]'
+ )
+
+ expect(gaScript.length).toBe(1)
+ const dataLayer = await browser.eval('window.dataLayer')
+ expect(dataLayer.length).toBe(4)
+
+ await browser.elementByCss('#ga-send').click()
+
+ const dataLayer2 = await browser.eval('window.dataLayer')
+ expect(dataLayer2.length).toBe(5)
+ })
}
)
diff --git a/test/e2e/third-parties/index.test.ts b/test/e2e/third-parties/index.test.ts
index 176a236da7efe..e28c6b7edfede 100644
--- a/test/e2e/third-parties/index.test.ts
+++ b/test/e2e/third-parties/index.test.ts
@@ -53,5 +53,28 @@ createNextDescribe(
const dataLayer2 = await browser.eval('window.dataLayer')
expect(dataLayer2.length).toBe(2)
})
+
+ it('renders GA', async () => {
+ const browser = await next.browser('/ga')
+
+ await browser.waitForElementByCss('#_next-ga')
+ await waitFor(1000)
+
+ const gaInlineScript = await browser.elementsByCss('#_next-ga-init')
+ expect(gaInlineScript.length).toBe(1)
+
+ const gaScript = await browser.elementsByCss(
+ '[src^="https://www.googletagmanager.com/gtag/js?id=GA-XYZ"]'
+ )
+
+ expect(gaScript.length).toBe(1)
+ const dataLayer = await browser.eval('window.dataLayer')
+ expect(dataLayer.length).toBe(4)
+
+ await browser.elementByCss('#ga-send').click()
+
+ const dataLayer2 = await browser.eval('window.dataLayer')
+ expect(dataLayer2.length).toBe(5)
+ })
}
)
diff --git a/test/e2e/third-parties/pages/ga.js b/test/e2e/third-parties/pages/ga.js
new file mode 100644
index 0000000000000..74a5a8ce7697d
--- /dev/null
+++ b/test/e2e/third-parties/pages/ga.js
@@ -0,0 +1,21 @@
+import React from 'react'
+import { GoogleAnalytics, sendGAEvent } from '@next/third-parties/google'
+
+const Page = () => {
+ const onClick = () => {
+ sendGAEvent({ event: 'buttonClicked', value: 'xyz' })
+ }
+
+ return (
+
+
+
GA
+
+
+
+ )
+}
+
+export default Page
diff --git a/test/lib/browsers/playwright.ts b/test/lib/browsers/playwright.ts
index f742a95cc6d58..6e10d57d62295 100644
--- a/test/lib/browsers/playwright.ts
+++ b/test/lib/browsers/playwright.ts
@@ -39,6 +39,58 @@ export class Playwright extends BrowserInterface {
request: new Set(),
}
+ private async initContextTracing(
+ url: string,
+ page: Page,
+ context: BrowserContext
+ ) {
+ if (!tracePlaywright) {
+ return
+ }
+
+ try {
+ // Clean up if any previous traces are still active
+ await this.teardownTracing()
+
+ await context.tracing.start({
+ screenshots: true,
+ snapshots: true,
+ })
+ this.activeTrace = encodeURIComponent(url)
+
+ page.on('close', async () => {
+ await this.teardownTracing()
+ })
+ } catch (e) {
+ this.activeTrace = undefined
+ }
+ }
+
+ private async teardownTracing() {
+ if (!tracePlaywright || !this.activeTrace) {
+ return
+ }
+
+ try {
+ const traceDir = path.join(__dirname, '../../traces')
+ const traceOutputPath = path.join(
+ traceDir,
+ `${path
+ .relative(path.join(__dirname, '../../'), process.env.TEST_FILE_PATH)
+ .replace(/\//g, '-')}`,
+ `playwright-${this.activeTrace}-${Date.now()}.zip`
+ )
+
+ await fs.remove(traceOutputPath)
+ await context.tracing.stop({
+ path: traceOutputPath,
+ })
+ } catch (e) {
+ } finally {
+ this.activeTrace = undefined
+ }
+ }
+
on(event: Event, cb: (...args: any[]) => void) {
if (!this.eventCallbacks[event]) {
throw new Error(
@@ -82,6 +134,9 @@ export class Playwright extends BrowserInterface {
ignoreHTTPSErrors,
...device,
})
+ context.once('close', async () => {
+ await this.teardownTracing()
+ })
contextHasJSEnabled = javaScriptEnabled
}
return
@@ -94,6 +149,9 @@ export class Playwright extends BrowserInterface {
ignoreHTTPSErrors,
...device,
})
+ context.once('close', async () => {
+ await this.teardownTracing()
+ })
contextHasJSEnabled = javaScriptEnabled
}
@@ -134,29 +192,13 @@ export class Playwright extends BrowserInterface {
beforePageLoad?: (...args: any[]) => void
}
) {
- if (this.activeTrace) {
- const traceDir = path.join(__dirname, '../../traces')
- const traceOutputPath = path.join(
- traceDir,
- `${path
- .relative(path.join(__dirname, '../../'), process.env.TEST_FILE_PATH)
- .replace(/\//g, '-')}`,
- `playwright-${this.activeTrace}-${Date.now()}.zip`
- )
-
- await fs.remove(traceOutputPath)
- await context.tracing
- .stop({
- path: traceOutputPath,
- })
- .catch((err) => console.error('failed to write playwright trace', err))
- }
-
// clean-up existing pages
for (const oldPage of context.pages()) {
await oldPage.close()
}
+
page = await context.newPage()
+ await this.initContextTracing(url, page, context)
// in development compilation can take longer due to
// lower CPU availability in GH actions
@@ -219,13 +261,6 @@ export class Playwright extends BrowserInterface {
opts?.beforePageLoad?.(page)
- if (tracePlaywright) {
- await context.tracing.start({
- screenshots: true,
- snapshots: true,
- })
- this.activeTrace = encodeURIComponent(url)
- }
await page.goto(url, { waitUntil: 'load' })
}
diff --git a/test/lib/next-modes/base.ts b/test/lib/next-modes/base.ts
index f3c06e778e795..348624e818cf3 100644
--- a/test/lib/next-modes/base.ts
+++ b/test/lib/next-modes/base.ts
@@ -390,7 +390,9 @@ export class NextInstance {
`next-trace`
)
)
- .catch(() => {})
+ .catch((e) => {
+ require('console').error(e)
+ })
}
if (!process.env.NEXT_TEST_SKIP_CLEANUP) {