diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 6a238243182a0..e529404cf4602 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -700,7 +700,6 @@ jobs: uses: ./.github/workflows/build_reusable.yml with: afterBuild: | - export __NEXT_EXPERIMENTAL_PPR=true # for compatibility with the existing tests export __NEXT_EXPERIMENTAL_CACHE_COMPONENTS=true export __NEXT_EXPERIMENTAL_DEBUG_CHANNEL=true export NEXT_EXTERNAL_TESTS_FILTERS="test/experimental-tests-manifest.json" diff --git a/package.json b/package.json index a943a34524ede..baada05d5add2 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "test-storybook": "turbo run test-storybook", "with-rspack": "cross-env NEXT_RSPACK=1 NEXT_TEST_USE_RSPACK=1", "with-webpack": "cross-env IS_WEBPACK_TEST=1", - "with-experimental": "cross-env __NEXT_EXPERIMENTAL_CACHE_COMPONENTS=true __NEXT_EXPERIMENTAL_PPR=true __NEXT_EXPERIMENTAL_DEBUG_CHANNEL=true" + "with-experimental": "cross-env __NEXT_EXPERIMENTAL_CACHE_COMPONENTS=true __NEXT_EXPERIMENTAL_DEBUG_CHANNEL=true" }, "devDependencies": { "@actions/core": "1.10.1", diff --git a/packages/next/errors.json b/packages/next/errors.json index ff1a6703f20ab..d81dfe8aba204 100644 --- a/packages/next/errors.json +++ b/packages/next/errors.json @@ -862,5 +862,6 @@ "861": "Client Max Body Size must be larger than 0 bytes", "862": "Request body exceeded %s", "863": "\\`\\` received a direct child that is either a Server Component, or JSX that was loaded with React.lazy(). This is not supported. Either remove legacyBehavior, or make the direct child a Client Component that renders the Link's \\`\\` tag.", - "864": "Missing value for segment key: \"%s\" with dynamic param type: %s" + "864": "Missing value for segment key: \"%s\" with dynamic param type: %s", + "865": "`experimental.rdcForNavigations` is enabled, but `experimental.cacheComponents` is not." } diff --git a/packages/next/src/server/config-shared.ts b/packages/next/src/server/config-shared.ts index ace655145085a..3e83a2854831e 100644 --- a/packages/next/src/server/config-shared.ts +++ b/packages/next/src/server/config-shared.ts @@ -13,7 +13,7 @@ import type { SizeLimit } from '../types' import type { SupportedTestRunners } from '../cli/next-test' import type { ExperimentalPPRConfig } from './lib/experimental/ppr' import { INFINITE_CACHE } from '../lib/constants' -import { isStableBuild } from '../shared/lib/canary-only' +import { isStableBuild } from '../shared/lib/errors/canary-only-config-error' import type { FallbackRouteParam } from '../build/static-paths/types' export type NextConfigComplete = Required> & { @@ -573,8 +573,8 @@ export interface ExperimentalConfig { clientTraceMetadata?: string[] /** - * Enables experimental Partial Prerendering feature of Next.js. - * Using this feature will enable the `react@experimental` for the `app` directory. + * @deprecated This configuration option has been merged into `experimental.cacheComponents`. + * The Partial Prerendering feature is still available via `experimental.cacheComponents`. */ ppr?: ExperimentalPPRConfig diff --git a/packages/next/src/server/config.test.ts b/packages/next/src/server/config.test.ts index fc1d8b2eb70f3..fecba1324e39a 100644 --- a/packages/next/src/server/config.test.ts +++ b/packages/next/src/server/config.test.ts @@ -86,13 +86,13 @@ describe('loadConfig', () => { const loadConfigPromise = loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { customConfig: { experimental: { - ppr: true, + cacheComponents: true, }, }, }) await expect(loadConfigPromise).rejects.toThrow( - /The experimental feature "experimental.ppr" can only be enabled when using the latest canary version of Next.js./ + /The experimental feature "experimental.cacheComponents" can only be enabled when using the latest canary version of Next.js./ ) try { @@ -115,7 +115,7 @@ describe('loadConfig', () => { }, }) ).rejects.toThrow( - /The experimental feature "experimental.ppr" can only be enabled when using the latest canary version of Next.js./ + /`experimental\.ppr` has been merged into `experimental\.cacheComponents`/ ) }) @@ -157,41 +157,40 @@ describe('loadConfig', () => { delete process.env.__NEXT_VERSION }) - it('errors when cacheComponents is enabled but PPR is disabled', async () => { + it('errors when rdcForNavigations is enabled but cacheComponents is disabled', async () => { await expect( loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { customConfig: { experimental: { - cacheComponents: true, + rdcForNavigations: true, ppr: false, }, }, }) ).rejects.toThrow( - '`experimental.ppr` can not be `false` when `experimental.cacheComponents` is `true`. PPR is implicitly enabled when Cache Components is enabled.' + '`experimental.rdcForNavigations` is enabled, but `experimental.cacheComponents` is not.' ) }) - it('errors when rdcForNavigations is enabled but ppr is disabled', async () => { + it('errors when ppr is set to incremental', async () => { await expect( loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { customConfig: { experimental: { - rdcForNavigations: true, - ppr: false, + ppr: 'incremental', }, }, }) ).rejects.toThrow( - '`experimental.rdcForNavigations` is enabled, but `experimental.ppr` is not.' + /`experimental\.ppr` has been merged into `experimental\.cacheComponents`/ ) }) - it('defaults rdcForNavigations to true when ppr is enabled', async () => { + it('defaults rdcForNavigations to true when cacheComponents is enabled', async () => { const result = await loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { customConfig: { experimental: { - ppr: true, + cacheComponents: true, }, }, }) @@ -199,34 +198,6 @@ describe('loadConfig', () => { expect(result.experimental.rdcForNavigations).toBe(true) }) - it('allows explicitly disabling rdcForNavigations when ppr is enabled', async () => { - const result = await loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { - customConfig: { - experimental: { - ppr: true, - rdcForNavigations: false, - }, - }, - }) - - expect(result.experimental.rdcForNavigations).toBe(false) - }) - - it('errors when cacheComponents is enabled but PPR set to "incremental"', async () => { - await expect( - loadConfig(PHASE_PRODUCTION_BUILD, __dirname, { - customConfig: { - experimental: { - cacheComponents: true, - ppr: 'incremental', - }, - }, - }) - ).rejects.toThrow( - '`experimental.ppr` can not be `"incremental"` when `experimental.cacheComponents` is `true`. PPR is implicitly enabled when Cache Components is enabled.' - ) - }) - it('migrates experimental.dynamicIO to experimental.cacheComponents', async () => { process.env.__NEXT_VERSION = 'canary' diff --git a/packages/next/src/server/config.ts b/packages/next/src/server/config.ts index b5ef5cd02d3ac..8ec4908692d13 100644 --- a/packages/next/src/server/config.ts +++ b/packages/next/src/server/config.ts @@ -38,10 +38,14 @@ import { dset } from '../shared/lib/dset' import { normalizeZodErrors } from '../shared/lib/zod' import { HTML_LIMITED_BOT_UA_RE_STRING } from '../shared/lib/router/utils/is-bot' import { findDir } from '../lib/find-pages-dir' -import { CanaryOnlyError, isStableBuild } from '../shared/lib/canary-only' +import { + CanaryOnlyConfigError, + isStableBuild, +} from '../shared/lib/errors/canary-only-config-error' import { interopDefault } from '../lib/interop-default' import { djb2Hash } from '../shared/lib/hash' import type { NextAdapter } from '../build/adapter/build-complete' +import { HardDeprecatedConfigError } from '../shared/lib/errors/hard-deprecated-config-error' export { normalizeConfig } from './config-shared' export type { DomainLocale, NextConfig } from './config-shared' @@ -365,17 +369,23 @@ function assignDefaultsAndValidate( if (isStableBuild()) { // Prevents usage of certain experimental features outside of canary - if (result.experimental?.ppr) { - throw new CanaryOnlyError({ feature: 'experimental.ppr' }) - } else if (result.experimental?.cacheComponents) { - throw new CanaryOnlyError({ feature: 'experimental.cacheComponents' }) + if (result.experimental?.cacheComponents) { + throw new CanaryOnlyConfigError({ + feature: 'experimental.cacheComponents', + }) } else if (result.experimental?.turbopackFileSystemCacheForBuild) { - throw new CanaryOnlyError({ + throw new CanaryOnlyConfigError({ feature: 'experimental.turbopackFileSystemCacheForBuild', }) } } + if (result.experimental.ppr) { + throw new HardDeprecatedConfigError( + `\`experimental.ppr\` has been merged into \`experimental.cacheComponents\`. The Partial Prerendering feature is still available, but is now enabled via \`experimental.cacheComponents\`. Please update your ${configFileName} accordingly.` + ) + } + if (result.output === 'export') { if (result.i18n) { throw new Error( @@ -1178,6 +1188,11 @@ function assignDefaultsAndValidate( result.experimental.mcpServer = true } + // TODO: remove once we've finished migrating internally to cacheComponents. + if (result.experimental.cacheComponents) { + result.experimental.ppr = true + } + // "use cache" was originally implicitly enabled with the cacheComponents flag, so // we transfer the value for cacheComponents to the explicit useCache flag to ensure // backwards compatibility. @@ -1185,39 +1200,10 @@ function assignDefaultsAndValidate( result.experimental.useCache = result.experimental.cacheComponents } - // If cacheComponents is enabled, we also enable PPR. - if (result.experimental.cacheComponents) { - if ( - userConfig.experimental?.ppr === false || - userConfig.experimental?.ppr === 'incremental' - ) { - throw new Error( - `\`experimental.ppr\` can not be \`${JSON.stringify(userConfig.experimental?.ppr)}\` when \`experimental.cacheComponents\` is \`true\`. PPR is implicitly enabled when Cache Components is enabled.` - ) - } - - result.experimental.ppr = true - - if ( - configuredExperimentalFeatures && - // If we've already noted that the `process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS` - // has enabled the feature, we don't need to note it again. - process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS !== 'true' && - process.env.__NEXT_EXPERIMENTAL_PPR !== 'true' - ) { - addConfiguredExperimentalFeature( - configuredExperimentalFeatures, - 'ppr', - true, - 'enabled by `experimental.cacheComponents`' - ) - } - } - - // If ppr is enabled and the user hasn't configured rdcForNavigations, we - // enable it by default. + // If cacheComponents is enabled and the user hasn't configured + // rdcForNavigations, we enable it by default. if ( - result.experimental.ppr && + result.experimental.cacheComponents && userConfig.experimental?.rdcForNavigations === undefined ) { result.experimental.rdcForNavigations = true @@ -1227,15 +1213,18 @@ function assignDefaultsAndValidate( configuredExperimentalFeatures, 'rdcForNavigations', true, - 'enabled by `experimental.ppr`' + 'enabled by `experimental.cacheComponents`' ) } } - // If rdcForNavigations is enabled, but ppr is not, we throw an error. - if (result.experimental.rdcForNavigations && !result.experimental.ppr) { + // If rdcForNavigations is enabled, but cacheComponents is not, we throw an error. + if ( + result.experimental.rdcForNavigations && + !result.experimental.cacheComponents + ) { throw new Error( - '`experimental.rdcForNavigations` is enabled, but `experimental.ppr` is not.' + '`experimental.rdcForNavigations` is enabled, but `experimental.cacheComponents` is not.' ) } @@ -1714,47 +1703,9 @@ function enforceExperimentalFeatures( ) } - // TODO: Remove this once we've made Cache Components the default. - if ( - process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' && - // We do respect an explicit value in the user config. - (config.experimental.ppr === undefined || - (isDefaultConfig && !config.experimental.ppr)) - ) { - config.experimental.ppr = true - - if (configuredExperimentalFeatures) { - addConfiguredExperimentalFeature( - configuredExperimentalFeatures, - 'ppr', - true, - 'enabled by `__NEXT_EXPERIMENTAL_CACHE_COMPONENTS`' - ) - } - } - - // TODO: Remove this once we've made Cache Components the default. - if ( - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' && - // We do respect an explicit value in the user config. - (config.experimental.ppr === undefined || - (isDefaultConfig && !config.experimental.ppr)) - ) { - config.experimental.ppr = true - - if (configuredExperimentalFeatures) { - addConfiguredExperimentalFeature( - configuredExperimentalFeatures, - 'ppr', - true, - 'enabled by `__NEXT_EXPERIMENTAL_PPR`' - ) - } - } - // TODO: Remove this once we've made Client Param Parsing the default. if ( - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' && + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' && // We do respect an explicit value in the user config. (config.experimental.clientParamParsing === undefined || (isDefaultConfig && !config.experimental.clientParamParsing)) @@ -1766,7 +1717,7 @@ function enforceExperimentalFeatures( configuredExperimentalFeatures, 'clientParamParsing', true, - 'enabled by `__NEXT_EXPERIMENTAL_PPR`' + 'enabled by `__NEXT_EXPERIMENTAL_CACHE_COMPONENTS`' ) } } @@ -1790,7 +1741,7 @@ function enforceExperimentalFeatures( } } - // TODO: Remove this once we've made RDC for Navigations the default for PPR. + // TODO: Remove this once we've made RDC for Navigations the default for cache components. if ( process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' && // We do respect an explicit value in the user config. @@ -1828,25 +1779,6 @@ function enforceExperimentalFeatures( } } - // TODO: Remove this once we've made RDC for Navigations the default for PPR. - if ( - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' && - // We do respect an explicit value in the user config. - (config.experimental.rdcForNavigations === undefined || - (isDefaultConfig && !config.experimental.rdcForNavigations)) - ) { - config.experimental.rdcForNavigations = true - - if (configuredExperimentalFeatures) { - addConfiguredExperimentalFeature( - configuredExperimentalFeatures, - 'rdcForNavigations', - true, - 'enabled by `__NEXT_EXPERIMENTAL_PPR`' - ) - } - } - if ( process.env.__NEXT_ENABLE_REACT_COMPILER === 'true' && // We do respect an explicit value in the user config. diff --git a/packages/next/src/shared/lib/canary-only.ts b/packages/next/src/shared/lib/errors/canary-only-config-error.ts similarity index 92% rename from packages/next/src/shared/lib/canary-only.ts rename to packages/next/src/shared/lib/errors/canary-only-config-error.ts index d7f801743ee14..499fd2b614da5 100644 --- a/packages/next/src/shared/lib/canary-only.ts +++ b/packages/next/src/shared/lib/errors/canary-only-config-error.ts @@ -6,7 +6,7 @@ export function isStableBuild() { ) } -export class CanaryOnlyError extends Error { +export class CanaryOnlyConfigError extends Error { constructor(arg: { feature: string } | string) { if (typeof arg === 'object' && 'feature' in arg) { super( diff --git a/packages/next/src/shared/lib/errors/hard-deprecated-config-error.ts b/packages/next/src/shared/lib/errors/hard-deprecated-config-error.ts new file mode 100644 index 0000000000000..20c25f5bf04a0 --- /dev/null +++ b/packages/next/src/shared/lib/errors/hard-deprecated-config-error.ts @@ -0,0 +1,9 @@ +export class HardDeprecatedConfigError extends Error { + constructor(message: string) { + super(message) + + // This error is meant to interrupt the server start/build process + // but the stack trace isn't meaningful, as it points to internal code. + this.stack = undefined + } +} diff --git a/test/development/acceptance-app/hydration-error.test.ts b/test/development/acceptance-app/hydration-error.test.ts index d38855cb1c70c..3a797b759dce7 100644 --- a/test/development/acceptance-app/hydration-error.test.ts +++ b/test/development/acceptance-app/hydration-error.test.ts @@ -9,7 +9,7 @@ import { retry, } from 'next-test-utils' -const pprEnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' +const pprEnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' describe('Error overlay for hydration errors in App router', () => { const { next, isTurbopack } = nextTestSetup({ diff --git a/test/development/app-dir/source-mapping/next.config.js b/test/development/app-dir/source-mapping/next.config.js index 5ea19c3598410..bde58859216fc 100644 --- a/test/development/app-dir/source-mapping/next.config.js +++ b/test/development/app-dir/source-mapping/next.config.js @@ -15,7 +15,7 @@ const nextConfig = { } }, experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/development/app-dir/source-mapping/source-mapping.test.ts b/test/development/app-dir/source-mapping/source-mapping.test.ts index 0f74060679020..95176bbf187a5 100644 --- a/test/development/app-dir/source-mapping/source-mapping.test.ts +++ b/test/development/app-dir/source-mapping/source-mapping.test.ts @@ -4,7 +4,8 @@ import { retry } from 'next-test-utils' const isCacheComponentsEnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' -describe('source-mapping', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('source-mapping', () => { const { next } = nextTestSetup({ files: __dirname, }) diff --git a/test/e2e/app-dir/app-static/app-static.test.ts b/test/e2e/app-dir/app-static/app-static.test.ts index aec3d9a09b254..5bda44db2499a 100644 --- a/test/e2e/app-dir/app-static/app-static.test.ts +++ b/test/e2e/app-dir/app-static/app-static.test.ts @@ -40,7 +40,7 @@ describe('app-dir static/dynamic handling', () => { } }) - if (!process.env.__NEXT_EXPERIMENTAL_PPR) { + if (!process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { it('should respond correctly for dynamic route with dynamicParams false in layout', async () => { const res = await next.fetch('/partial-params-false/en/another') expect(res.status).toBe(200) @@ -783,7 +783,7 @@ describe('app-dir static/dynamic handling', () => { if (isNextStart) { it('should not encode dynamic parameters as search parameters in RSC data', async () => { - const data = process.env.__NEXT_EXPERIMENTAL_PPR + const data = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS ? await next.readFile('.next/server/app/blog/seb.prefetch.rsc') : await next.readFile('.next/server/app/blog/seb.rsc') @@ -3307,7 +3307,7 @@ describe('app-dir static/dynamic handling', () => { for (let i = 0; i < 5; i++) { const res = await next.fetch('/articles/non-existent') - if (process.env.__NEXT_EXPERIMENTAL_PPR && !isNextDev) { + if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS && !isNextDev) { expect(res.status).toBe(200) } else { expect(res.status).toBe(404) @@ -3522,7 +3522,7 @@ describe('app-dir static/dynamic handling', () => { }) } else { // TODO: re-implement this in a way that'll support PFPR - if (!process.env.__NEXT_EXPERIMENTAL_PPR) { + if (!process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { it('should not error with dynamic server usage with force-static', async () => { const res = await next.fetch( '/static-to-dynamic-error-forced/static-bailout-1' @@ -3563,7 +3563,7 @@ describe('app-dir static/dynamic handling', () => { ) }) - if (!process.env.__NEXT_EXPERIMENTAL_PPR) { + if (!process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { it('should properly error when dynamic = "error" page uses dynamic', async () => { const res = await next.fetch('/dynamic-error/static-bailout-1') const outputIndex = next.cliOutput.length @@ -4460,7 +4460,7 @@ describe('app-dir static/dynamic handling', () => { expect(html).toInclude('"noindex"') expect(html).toInclude('This page could not be found.') - if (process.env.__NEXT_EXPERIMENTAL_PPR && !isNextDev) { + if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS && !isNextDev) { expect(res.status).toBe(200) } else { expect(res.status).toBe(404) diff --git a/test/e2e/app-dir/app-static/app/dynamic-error/[id]/page.js b/test/e2e/app-dir/app-static/app/dynamic-error/[id]/page.js index c10d5574131d2..5d9fe34708bf7 100644 --- a/test/e2e/app-dir/app-static/app/dynamic-error/[id]/page.js +++ b/test/e2e/app-dir/app-static/app/dynamic-error/[id]/page.js @@ -5,7 +5,7 @@ export const dynamic = 'error' export default async function Page(props) { const params = await props.params // When PPR is enabled, we will bailout on parameter access. - if (!process.env.__NEXT_EXPERIMENTAL_PPR) { + if (!process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { if (params.id.includes('static-bailout')) { console.log('calling cookies', await cookies()) } diff --git a/test/e2e/app-dir/app/index.test.ts b/test/e2e/app-dir/app/index.test.ts index 14d99686d7e8b..c28443e11337e 100644 --- a/test/e2e/app-dir/app/index.test.ts +++ b/test/e2e/app-dir/app/index.test.ts @@ -7,11 +7,6 @@ import { RSC_HEADER, } from 'next/dist/client/components/app-router-headers' -// TODO: We should decide on an established pattern for gating test assertions -// on experimental flags. For example, as a first step we could all the common -// gates like this one into a single module. -const isPPREnabledByDefault = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' - describe('app dir - basic', () => { const { next, isNextDev, isNextStart, isNextDeploy } = nextTestSetup({ files: __dirname, @@ -592,7 +587,7 @@ describe('app dir - basic', () => { ;(isNextDev || // When PPR is enabled, the shared layouts re-render because we prefetch // from the root. This will be addressed before GA. - isPPREnabledByDefault + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? it.skip : it)( 'should not rerender layout when navigating between routes in the same layout', @@ -1389,7 +1384,7 @@ describe('app dir - basic', () => { ;(isNextDev || // When PPR is enabled, the shared layouts re-render because we prefetch // from the root. This will be addressed before GA. - isPPREnabledByDefault + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? it.skip : it)( 'should render the template that is a server component and rerender on navigation', diff --git a/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts b/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts index 641e156b701a2..f70f1ccdadd2a 100644 --- a/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts +++ b/test/e2e/app-dir/custom-cache-control/custom-cache-control.test.ts @@ -25,7 +25,7 @@ describe('custom-cache-control', () => { isNextDev ? 'no-store, must-revalidate' : 's-maxage=31' ) }) - ;(process.env.__NEXT_EXPERIMENTAL_PPR ? it.skip : it)( + ;(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS ? it.skip : it)( 'should have default cache-control for app-ssg another', async () => { const res = await next.fetch('/app-ssg/another') diff --git a/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts b/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts index e121434847fc3..5c4b908bcdcbd 100644 --- a/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts +++ b/test/e2e/app-dir/dynamic-data/dynamic-data.test.ts @@ -27,7 +27,7 @@ describe('dynamic-data', () => { // in dev we expect the entire page to be rendered at runtime expect($('#layout').text()).toBe('at runtime') expect($('#page').text()).toBe('at runtime') - } else if (process.env.__NEXT_EXPERIMENTAL_PPR) { + } else if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { // in PPR we expect the shell to be rendered at build and the page to be rendered at runtime expect($('#layout').text()).toBe('at buildtime') expect($('#page').text()).toBe('at runtime') @@ -57,7 +57,7 @@ describe('dynamic-data', () => { // in dev we expect the entire page to be rendered at runtime expect($('#layout').text()).toBe('at runtime') expect($('#page').text()).toBe('at runtime') - } else if (process.env.__NEXT_EXPERIMENTAL_PPR) { + } else if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { // @TODO this should actually be build but there is a bug in how we do segment level dynamic in PPR at the moment // see note in create-component-tree expect($('#layout').text()).toBe('at runtime') @@ -88,7 +88,7 @@ describe('dynamic-data', () => { // in dev we expect the entire page to be rendered at runtime expect($('#layout').text()).toBe('at runtime') expect($('#page').text()).toBe('at runtime') - } else if (process.env.__NEXT_EXPERIMENTAL_PPR) { + } else if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { // in PPR we expect the shell to be rendered at build and the page to be rendered at runtime expect($('#layout').text()).toBe('at buildtime') expect($('#page').text()).toBe('at buildtime') @@ -124,7 +124,7 @@ describe('dynamic-data', () => { expect($('#page').text()).toBe('at runtime') // we don't assert the state of the fallback because it can depend on the timing // of when streaming starts and how fast the client references resolve - } else if (process.env.__NEXT_EXPERIMENTAL_PPR) { + } else if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { // in PPR we expect the shell to be rendered at build and the page to be rendered at runtime expect($('#layout').text()).toBe('at buildtime') expect($('#page').text()).toBe('at runtime') diff --git a/test/e2e/app-dir/metadata-static-generation/metadata-static-generation.test.ts b/test/e2e/app-dir/metadata-static-generation/metadata-static-generation.test.ts index 23f0220aa78c9..43dde59b3eccb 100644 --- a/test/e2e/app-dir/metadata-static-generation/metadata-static-generation.test.ts +++ b/test/e2e/app-dir/metadata-static-generation/metadata-static-generation.test.ts @@ -1,6 +1,6 @@ import { nextTestSetup } from 'e2e-utils' -const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' +const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ;(isPPREnabled ? describe.skip : describe)( 'app-dir - metadata-static-generation', diff --git a/test/e2e/app-dir/metadata-streaming-static-generation/metadata-streaming-static-generation.test.ts b/test/e2e/app-dir/metadata-streaming-static-generation/metadata-streaming-static-generation.test.ts index 08eef67c16598..253f117a14547 100644 --- a/test/e2e/app-dir/metadata-streaming-static-generation/metadata-streaming-static-generation.test.ts +++ b/test/e2e/app-dir/metadata-streaming-static-generation/metadata-streaming-static-generation.test.ts @@ -1,7 +1,7 @@ import { nextTestSetup } from 'e2e-utils' import { retry } from 'next-test-utils' -const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' +const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' // Skip PPR test as it's covered in test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts ;(isPPREnabled ? describe.skip : describe)( diff --git a/test/e2e/app-dir/next-after-app-deploy/index.test.ts b/test/e2e/app-dir/next-after-app-deploy/index.test.ts index 896884d329895..b88cf2f33e2df 100644 --- a/test/e2e/app-dir/next-after-app-deploy/index.test.ts +++ b/test/e2e/app-dir/next-after-app-deploy/index.test.ts @@ -46,7 +46,7 @@ _describe.each(runtimes)('after() in %s runtime', (runtimeValue) => { // despite the page being static, the first two requests both cause a render // and only the second one gets cached and re-used. // we work around it by doing a dummy request to get that first "uncached" request out of the way. - if (process.env.__NEXT_EXPERIMENTAL_PPR) { + if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { await getTimestampPageData(path) } diff --git a/test/e2e/app-dir/not-found/default/default.test.ts b/test/e2e/app-dir/not-found/default/default.test.ts index b7e936d5a9bf5..047a1a9705a10 100644 --- a/test/e2e/app-dir/not-found/default/default.test.ts +++ b/test/e2e/app-dir/not-found/default/default.test.ts @@ -1,6 +1,6 @@ import { nextTestSetup } from 'e2e-utils' -const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' +const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' describe('app dir - not-found - default', () => { const { next, isNextStart } = nextTestSetup({ diff --git a/test/e2e/app-dir/ppr-errors/next.config.js b/test/e2e/app-dir/ppr-errors/next.config.js index c80c62083fa51..bc85ec9a06dc5 100644 --- a/test/e2e/app-dir/ppr-errors/next.config.js +++ b/test/e2e/app-dir/ppr-errors/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, prerenderEarlyExit: false, }, } diff --git a/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts b/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts index 8a7209bc72c52..c17d9c13fa08c 100644 --- a/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts +++ b/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts @@ -2,7 +2,8 @@ import { nextBuild } from 'next-test-utils' // In order for the global isNextStart to be set import 'e2e-utils' -describe('ppr build errors', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr build errors', () => { ;(Boolean((global as any).isNextStart) ? describe : describe.skip)( 'production only', () => { diff --git a/test/e2e/app-dir/ppr-full/next.config.js b/test/e2e/app-dir/ppr-full/next.config.js index 49ab599c5039b..dac4e8aecf44a 100644 --- a/test/e2e/app-dir/ppr-full/next.config.js +++ b/test/e2e/app-dir/ppr-full/next.config.js @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-full/ppr-full.test.ts b/test/e2e/app-dir/ppr-full/ppr-full.test.ts index 4b1bac393bf9e..cf5dc0f3ea770 100644 --- a/test/e2e/app-dir/ppr-full/ppr-full.test.ts +++ b/test/e2e/app-dir/ppr-full/ppr-full.test.ts @@ -82,7 +82,8 @@ const expectDirectives = (header: string, directives: string[]) => { expect(split.length).toEqual(directives.length) } -describe('ppr-full', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr-full', () => { const { next, isNextDev, isNextDeploy } = nextTestSetup({ files: __dirname, }) diff --git a/test/e2e/app-dir/ppr-history-replace-state/next.config.js b/test/e2e/app-dir/ppr-history-replace-state/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-history-replace-state/next.config.js +++ b/test/e2e/app-dir/ppr-history-replace-state/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-incremental/app/disabled/page.jsx b/test/e2e/app-dir/ppr-incremental/app/disabled/page.jsx deleted file mode 100644 index 8392b5a308c99..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/disabled/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../lib/page' -export const experimental_ppr = false diff --git a/test/e2e/app-dir/ppr-incremental/app/dynamic/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/dynamic/[slug]/page.jsx deleted file mode 100644 index 4289a943119a4..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/dynamic/[slug]/page.jsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from '../../../lib/page' diff --git a/test/e2e/app-dir/ppr-incremental/app/dynamic/disabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/dynamic/disabled/[slug]/page.jsx deleted file mode 100644 index f8c79f1161346..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/dynamic/disabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../lib/page' -export const experimental_ppr = false diff --git a/test/e2e/app-dir/ppr-incremental/app/dynamic/enabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/dynamic/enabled/[slug]/page.jsx deleted file mode 100644 index ceb3c03ca6ac6..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/dynamic/enabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../lib/page' -export const experimental_ppr = true diff --git a/test/e2e/app-dir/ppr-incremental/app/enabled/page.jsx b/test/e2e/app-dir/ppr-incremental/app/enabled/page.jsx deleted file mode 100644 index dd11b10cc2362..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/enabled/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../lib/page' -export const experimental_ppr = true diff --git a/test/e2e/app-dir/ppr-incremental/app/favicon.ico b/test/e2e/app-dir/ppr-incremental/app/favicon.ico deleted file mode 100644 index 4965832f2c9b0..0000000000000 Binary files a/test/e2e/app-dir/ppr-incremental/app/favicon.ico and /dev/null differ diff --git a/test/e2e/app-dir/ppr-incremental/app/layout.jsx b/test/e2e/app-dir/ppr-incremental/app/layout.jsx deleted file mode 100644 index 4ee00a218505a..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/layout.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function RootLayout({ children }) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/disabled/[slug]/page.jsx deleted file mode 100644 index 1caf61a9cde3e..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/[slug]/page.jsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from '../../../../lib/page' diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/disabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/disabled/disabled/[slug]/page.jsx deleted file mode 100644 index 60f8d726a343a..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/disabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../../lib/page' -export const experimental_ppr = false diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/enabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/disabled/enabled/[slug]/page.jsx deleted file mode 100644 index 3f8212e203117..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/enabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../../lib/page' -export const experimental_ppr = true diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/layout.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/disabled/layout.jsx deleted file mode 100644 index 9ecbd4926f98e..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/disabled/layout.jsx +++ /dev/null @@ -1,5 +0,0 @@ -export const experimental_ppr = false - -export default function Layout({ children }) { - return children -} diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/enabled/[slug]/page.jsx deleted file mode 100644 index 1caf61a9cde3e..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/[slug]/page.jsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from '../../../../lib/page' diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/disabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/enabled/disabled/[slug]/page.jsx deleted file mode 100644 index 60f8d726a343a..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/disabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../../lib/page' -export const experimental_ppr = false diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/enabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/enabled/enabled/[slug]/page.jsx deleted file mode 100644 index 3f8212e203117..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/enabled/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from '../../../../../lib/page' -export const experimental_ppr = true diff --git a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/layout.jsx b/test/e2e/app-dir/ppr-incremental/app/nested/enabled/layout.jsx deleted file mode 100644 index 2b910640eaa90..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/nested/enabled/layout.jsx +++ /dev/null @@ -1,5 +0,0 @@ -export const experimental_ppr = true - -export default function Layout({ children }) { - return children -} diff --git a/test/e2e/app-dir/ppr-incremental/app/omitted/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/omitted/[slug]/page.jsx deleted file mode 100644 index a5a689cf94ebf..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/omitted/[slug]/page.jsx +++ /dev/null @@ -1,2 +0,0 @@ -export { default, generateStaticParams } from '../../../lib/page' -export const dynamicParams = false diff --git a/test/e2e/app-dir/ppr-incremental/app/omitted/disabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/omitted/disabled/[slug]/page.jsx deleted file mode 100644 index 159def7e20d1d..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/omitted/disabled/[slug]/page.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export { default, generateStaticParams } from '../../../../lib/page' -export const experimental_ppr = false -export const dynamicParams = false diff --git a/test/e2e/app-dir/ppr-incremental/app/omitted/enabled/[slug]/page.jsx b/test/e2e/app-dir/ppr-incremental/app/omitted/enabled/[slug]/page.jsx deleted file mode 100644 index e57bf67d6b9a0..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/omitted/enabled/[slug]/page.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export { default, generateStaticParams } from '../../../../lib/page' -export const experimental_ppr = true -export const dynamicParams = false diff --git a/test/e2e/app-dir/ppr-incremental/app/page.jsx b/test/e2e/app-dir/ppr-incremental/app/page.jsx deleted file mode 100644 index 6db682e021aa0..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/page.jsx +++ /dev/null @@ -1 +0,0 @@ -export { default } from '../lib/page' diff --git a/test/e2e/app-dir/ppr-incremental/app/static/page.jsx b/test/e2e/app-dir/ppr-incremental/app/static/page.jsx deleted file mode 100644 index 921c90992c7f0..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/app/static/page.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return
Fully static page!
-} diff --git a/test/e2e/app-dir/ppr-incremental/lib/page.jsx b/test/e2e/app-dir/ppr-incremental/lib/page.jsx deleted file mode 100644 index 7fa22e25e660c..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/lib/page.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { unstable_noStore } from 'next/cache' -import Link from 'next/link' -import { Suspense } from 'react' - -function Dynamic() { - unstable_noStore() - return
Dynamic
-} - -export default function Page() { - return ( - <> -
  • - Root - Enabled - Disabled - Static -
  • - Loading...}> - - - - ) -} - -export const slugs = ['a', 'b', 'c'] - -export const generateStaticParams = () => { - return slugs.map((slug) => ({ slug })) -} diff --git a/test/e2e/app-dir/ppr-incremental/next.config.js b/test/e2e/app-dir/ppr-incremental/next.config.js deleted file mode 100644 index 4120ad23231ea..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/next.config.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @type {import('next').NextConfig} - */ -module.exports = { - experimental: { - ppr: 'incremental', - }, -} diff --git a/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts b/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts deleted file mode 100644 index 386e52b81eed5..0000000000000 --- a/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts +++ /dev/null @@ -1,205 +0,0 @@ -import { nextTestSetup, isNextDev } from 'e2e-utils' - -type Route = { - route: string - enabled: boolean - pathnames: string[] -} - -const routes: ReadonlyArray = [ - { - route: '/', - pathnames: ['/'], - enabled: false, - }, - { - route: '/disabled', - pathnames: ['/disabled'], - enabled: false, - }, - { - route: '/enabled', - pathnames: ['/enabled'], - enabled: true, - }, - { - route: '/omitted/[slug]', - pathnames: ['/omitted/a', '/omitted/b', '/omitted/c'], - enabled: false, - }, - { - route: '/omitted/disabled/[slug]', - pathnames: [ - '/omitted/disabled/a', - '/omitted/disabled/b', - '/omitted/disabled/c', - ], - enabled: false, - }, - { - route: '/omitted/enabled/[slug]', - pathnames: [ - '/omitted/enabled/a', - '/omitted/enabled/b', - '/omitted/enabled/c', - ], - enabled: true, - }, - { - route: '/dynamic/[slug]', - pathnames: ['/dynamic/a', '/dynamic/b', '/dynamic/c'], - enabled: false, - }, - { - route: '/dynamic/disabled/[slug]', - pathnames: [ - '/dynamic/disabled/a', - '/dynamic/disabled/b', - '/dynamic/disabled/c', - ], - enabled: false, - }, - { - route: '/dynamic/enabled/[slug]', - pathnames: [ - '/dynamic/enabled/a', - '/dynamic/enabled/b', - '/dynamic/enabled/c', - ], - enabled: true, - }, - { - route: '/nested/enabled/[slug]', - pathnames: ['/nested/enabled/a', '/nested/enabled/b', '/nested/enabled/c'], - enabled: true, - }, - { - route: '/nested/enabled/disabled/[slug]', - pathnames: [ - '/nested/enabled/disabled/a', - '/nested/enabled/disabled/b', - '/nested/enabled/disabled/c', - ], - enabled: false, - }, - { - route: '/nested/enabled/enabled/[slug]', - pathnames: [ - '/nested/enabled/enabled/a', - '/nested/enabled/enabled/b', - '/nested/enabled/enabled/c', - ], - enabled: true, - }, - { - route: '/nested/disabled/[slug]', - pathnames: [ - '/nested/disabled/a', - '/nested/disabled/b', - '/nested/disabled/c', - ], - enabled: false, - }, - { - route: '/nested/disabled/disabled/[slug]', - pathnames: [ - '/nested/disabled/disabled/a', - '/nested/disabled/disabled/b', - '/nested/disabled/disabled/c', - ], - enabled: false, - }, - { - route: '/nested/disabled/enabled/[slug]', - pathnames: [ - '/nested/disabled/enabled/a', - '/nested/disabled/enabled/b', - '/nested/disabled/enabled/c', - ], - enabled: true, - }, -] - -describe('ppr-incremental', () => { - // We don't perform static builds and partial prerendering in development - // mode. - if (isNextDev) return it.skip('should skip next dev', () => {}) - - const { next } = nextTestSetup({ files: __dirname }) - - describe('ppr disabled', () => { - describe.each(routes.filter(({ enabled }) => !enabled))( - '$route', - ({ pathnames }) => { - // When PPR is disabled, we won't include the fallback in the initial - // load because the dynamic render will not suspend. - describe('should render without the fallback in the initial load', () => { - it.each(pathnames)('%s', async (pathname) => { - const $ = await next.render$(pathname) - expect($('#fallback')).toHaveLength(0) - }) - }) - - describe('should not have the dynamic content hidden', () => { - it.each(pathnames)('%s', async (pathname) => { - const $ = await next.render$(pathname) - expect($('#dynamic')).toHaveLength(1) - expect($('#dynamic').parent('[hidden]')).toHaveLength(0) - }) - }) - } - ) - - it('should not trigger a dynamic request for static pages', async () => { - let rscRequests = [] - const browser = await next.browser('/', { - beforePageLoad(page) { - page.route('**/static*', async (route) => { - const request = route.request() - const headers = await request.allHeaders() - const url = new URL(request.url()) - - if (headers['rsc'] === '1') { - rscRequests.push(url.pathname) - await route.continue() - } - }) - }, - }) - - await browser.waitForIdleNetwork() - // we should see an RSC request for the initial prefetch to the static page - expect(rscRequests).toEqual(expect.arrayContaining(['/static'])) - - rscRequests = [] - - await browser.elementByCss('[href="/static"]').click() - await browser.waitForElementByCss('#static-page') - expect(rscRequests.length).toBe(0) - }) - }) - - describe('ppr enabled', () => { - describe.each(routes.filter(({ enabled }) => enabled))( - '$route', - ({ pathnames }) => { - // When PPR is enabled, we will always include the fallback in the - // initial load because the dynamic component uses `unstable_noStore()`. - describe('should render with the fallback in the initial load', () => { - it.each(pathnames)('%s', async (pathname) => { - const $ = await next.render$(pathname) - expect($('#fallback')).toHaveLength(1) - }) - }) - - describe('should have the dynamic content hidden', () => { - it.each(pathnames)('%s', async (pathname) => { - const $ = await next.render$(pathname) - expect($('#dynamic')).toHaveLength(1) - expect($('#dynamic').parent('[hidden]')).toHaveLength(1) - }) - }) - } - ) - }) -}) diff --git a/test/e2e/app-dir/ppr-metadata-blocking/next.config.js b/test/e2e/app-dir/ppr-metadata-blocking/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-metadata-blocking/next.config.js +++ b/test/e2e/app-dir/ppr-metadata-blocking/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-metadata-blocking/ppr-metadata-blocking-ppr-fallback.test.ts b/test/e2e/app-dir/ppr-metadata-blocking/ppr-metadata-blocking-ppr-fallback.test.ts index 6423037ee78ad..2d33f6f74d31e 100644 --- a/test/e2e/app-dir/ppr-metadata-blocking/ppr-metadata-blocking-ppr-fallback.test.ts +++ b/test/e2e/app-dir/ppr-metadata-blocking/ppr-metadata-blocking-ppr-fallback.test.ts @@ -4,7 +4,8 @@ function countSubstring(str: string, substr: string): number { return str.split(substr).length - 1 } -describe('ppr-metadata-blocking-ppr-fallback', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr-metadata-blocking-ppr-fallback', () => { const { next, skipped } = nextTestSetup({ files: __dirname, // Need to skip deployment because the test uses the private env cannot be used in deployment diff --git a/test/e2e/app-dir/ppr-metadata-streaming/next.config.js b/test/e2e/app-dir/ppr-metadata-streaming/next.config.js index bea0706290af6..e9480643df622 100644 --- a/test/e2e/app-dir/ppr-metadata-streaming/next.config.js +++ b/test/e2e/app-dir/ppr-metadata-streaming/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, useCache: true, }, } diff --git a/test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts b/test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts index f5b3f7f427322..c70534aabaa89 100644 --- a/test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts +++ b/test/e2e/app-dir/ppr-metadata-streaming/ppr-metadata-streaming.test.ts @@ -6,7 +6,8 @@ function countSubstring(str: string, substr: string): number { return str.split(substr).length - 1 } -describe('ppr-metadata-streaming', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr-metadata-streaming', () => { const { next, isNextDev, isNextDeploy } = nextTestSetup({ files: __dirname, }) diff --git a/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/next.config.js b/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/next.config.js +++ b/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params.test.ts b/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params.test.ts index 4c583bbdf32c6..1b1461fbcc6bd 100644 --- a/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params.test.ts +++ b/test/e2e/app-dir/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params/ppr-middleware-rewrite-force-dynamic-ssg-dynamic-params.test.ts @@ -1,7 +1,8 @@ import { nextTestSetup } from 'e2e-utils' import { expectedParams as expected } from './expected' -describe('ppr-middleware-rewrite-force-dynamic-generate-static-params', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr-middleware-rewrite-force-dynamic-generate-static-params', () => { const { next } = nextTestSetup({ files: __dirname, }) diff --git a/test/e2e/app-dir/ppr-navigations/avoid-popstate-flash/next.config.js b/test/e2e/app-dir/ppr-navigations/avoid-popstate-flash/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-navigations/avoid-popstate-flash/next.config.js +++ b/test/e2e/app-dir/ppr-navigations/avoid-popstate-flash/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/about/page.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/about/page.jsx deleted file mode 100644 index 9f500c2a9d4f3..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/about/page.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import { TestPage } from '../../../components/page' - -export const experimental_ppr = true - -export default async function Page(props) { - const params = await props.params - - const { locale } = params - - return -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/layout.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/layout.jsx deleted file mode 100644 index 9a9315cdfd84e..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/layout.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { locales } from '../../components/page' - -export async function generateStaticParams() { - return locales.map((locale) => ({ locale })) -} - -export default async function Layout(props) { - const params = await props.params - - const { locale } = params - - const { children } = props - - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/page.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/page.jsx deleted file mode 100644 index 873daac7a1ae7..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { TestPage } from '../../components/page' - -export default async function Page(props) { - const params = await props.params - - const { locale } = params - - return -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/static/page.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/static/page.jsx deleted file mode 100644 index 05e2f78bd9a0f..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/[locale]/static/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { TestPage } from '../../../components/page' - -export default async function Page(props) { - const params = await props.params - - const { locale } = params - - return -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/layout.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/layout.jsx deleted file mode 100644 index caaaf5ccdf7b1..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/layout.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export default ({ children }) => { - return children -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/app/page.jsx b/test/e2e/app-dir/ppr-navigations/incremental/app/page.jsx deleted file mode 100644 index a2fc5a8b040ea..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/app/page.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import { redirect } from 'next/navigation' -import { locales } from '../components/page' - -export default () => { - // Redirect to the default locale - return redirect(`/${locales[0]}`) -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/components/page.jsx b/test/e2e/app-dir/ppr-navigations/incremental/components/page.jsx deleted file mode 100644 index 488c9147a6b3f..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/components/page.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import { unstable_noStore } from 'next/cache' -import Link from 'next/link' -import { Suspense } from 'react' - -export const locales = ['en', 'fr'] - -export const links = [ - { href: '/', text: 'Home' }, - ...locales - .map((locale) => { - return [ - { href: `/${locale}`, text: locale }, - { href: `/${locale}/about`, text: `${locale} - About` }, - { href: `/${locale}/static`, text: `${locale} - Static` }, - ] - }) - .flat(), -] - -function Dynamic({ noDynamic = false }) { - if (!noDynamic) unstable_noStore() - return
    Dynamic
    -} - -export function TestPage({ pathname, noDynamic = false }) { - return ( -
    -
      - {links.map(({ href, text }) => ( -
    • - {text} -
    • - ))} -
    - {pathname} - Loading...
    }> - - - - ) -} diff --git a/test/e2e/app-dir/ppr-navigations/incremental/incremental.test.ts b/test/e2e/app-dir/ppr-navigations/incremental/incremental.test.ts deleted file mode 100644 index ddf8f79878966..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/incremental.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { NextInstance, nextTestSetup } from 'e2e-utils' -import { links, locales } from './components/page' -import glob from 'glob' -import { promisify } from 'node:util' -import { waitForHydration } from 'development-sandbox' -import { setTimeout } from 'node:timers/promises' - -const globp = promisify(glob) - -async function getDotNextFiles(next: NextInstance): Promise> { - const files = await globp('**/.next/**/*', { - cwd: next.testDir, - absolute: true, - }) - - return files -} - -describe('ppr-navigations incremental', () => { - const { next, isNextDev, isTurbopack, isNextDeploy } = nextTestSetup({ - files: __dirname, - }) - - it('can navigate between all the links and back without writing to disk', async () => { - const before = - !isNextDev && !isTurbopack && !isNextDeploy - ? await getDotNextFiles(next) - : [] - - const browser = await next.browser('/') - - await browser.waitForIdleNetwork() - await waitForHydration(browser) - await setTimeout(500) - - // Add a variable to the window so we can tell if it MPA navigated. If this - // value is still true at the end of the test, then we know that the page - // didn't MPA navigate. - const random = Math.random().toString(36).substring(7) - await browser.eval(`window.random = ${JSON.stringify(random)}`) - - try { - for (const { href } of links) { - // Find the link element for the href and click it. - await browser.waitForElementByCss(`a[href="${href}"]`).click() - - await browser.waitForIdleNetwork() - await waitForHydration(browser) - await setTimeout(500) - - // Wait for that page to load. - if (href === '/') { - // The root page redirects to the first locale. - await browser.waitForElementByCss(`[data-value="/${locales[0]}"]`) - } else { - await browser.waitForElementByCss(`[data-value="${href}"]`) - } - - await browser.waitForElementByCss('#dynamic', 1500) - - // Check if the page navigated. - expect(await browser.eval(`window.random`)).toBe(random) - } - } finally { - await browser.close() - } - - if (!isNextDev && !isTurbopack && !isNextDeploy) { - const after = await getDotNextFiles(next) - - // Ensure that no new files were written to disk. If this test fails, it's - // likely that there was a change to the incremental cache or file system - // cache that resulted in information like the ppr state not being properly - // propagated. - expect(after).toEqual(before) - } - }) -}) diff --git a/test/e2e/app-dir/ppr-navigations/incremental/next.config.js b/test/e2e/app-dir/ppr-navigations/incremental/next.config.js deleted file mode 100644 index 5cb1c0221aab3..0000000000000 --- a/test/e2e/app-dir/ppr-navigations/incremental/next.config.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - experimental: { - ppr: 'incremental', - }, -} diff --git a/test/e2e/app-dir/ppr-navigations/prefetch-navigation/next.config.js b/test/e2e/app-dir/ppr-navigations/prefetch-navigation/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-navigations/prefetch-navigation/next.config.js +++ b/test/e2e/app-dir/ppr-navigations/prefetch-navigation/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-navigations/prefetch-navigation/prefetch-navigation.test.ts b/test/e2e/app-dir/ppr-navigations/prefetch-navigation/prefetch-navigation.test.ts index 79205bc5cbc29..85116cced56fb 100644 --- a/test/e2e/app-dir/ppr-navigations/prefetch-navigation/prefetch-navigation.test.ts +++ b/test/e2e/app-dir/ppr-navigations/prefetch-navigation/prefetch-navigation.test.ts @@ -1,6 +1,7 @@ import { nextTestSetup } from 'e2e-utils' -describe('prefetch-navigation', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('prefetch-navigation', () => { const { next, isNextDev } = nextTestSetup({ files: __dirname, }) diff --git a/test/e2e/app-dir/ppr-navigations/search-params/next.config.js b/test/e2e/app-dir/ppr-navigations/search-params/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-navigations/search-params/next.config.js +++ b/test/e2e/app-dir/ppr-navigations/search-params/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-navigations/search-params/search-params.test.ts b/test/e2e/app-dir/ppr-navigations/search-params/search-params.test.ts index 496125ead8ffc..ffdc2a1319007 100644 --- a/test/e2e/app-dir/ppr-navigations/search-params/search-params.test.ts +++ b/test/e2e/app-dir/ppr-navigations/search-params/search-params.test.ts @@ -1,6 +1,7 @@ import { createNext } from 'e2e-utils' -describe('search-params', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('search-params', () => { if ((global as any).isNextDev) { test('ppr is disabled in dev', () => {}) return diff --git a/test/e2e/app-dir/ppr-navigations/stale-prefetch-entry/next.config.js b/test/e2e/app-dir/ppr-navigations/stale-prefetch-entry/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr-navigations/stale-prefetch-entry/next.config.js +++ b/test/e2e/app-dir/ppr-navigations/stale-prefetch-entry/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-partial-hydration/next.config.ts b/test/e2e/app-dir/ppr-partial-hydration/next.config.ts index 1f6180914624c..3970d95d89d9c 100644 --- a/test/e2e/app-dir/ppr-partial-hydration/next.config.ts +++ b/test/e2e/app-dir/ppr-partial-hydration/next.config.ts @@ -2,9 +2,7 @@ import type { NextConfig } from 'next' const nextConfig: NextConfig = { experimental: { - ppr: true, - // until the flags are merged, test both `ppr` and `cacheComponents` - // cacheComponents: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr-unstable-cache/next.config.js b/test/e2e/app-dir/ppr-unstable-cache/next.config.js index 6013aed786290..965373b19588f 100644 --- a/test/e2e/app-dir/ppr-unstable-cache/next.config.js +++ b/test/e2e/app-dir/ppr-unstable-cache/next.config.js @@ -1,5 +1,5 @@ module.exports = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr/next.config.js b/test/e2e/app-dir/ppr/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/e2e/app-dir/ppr/next.config.js +++ b/test/e2e/app-dir/ppr/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/ppr/ppr.test.ts b/test/e2e/app-dir/ppr/ppr.test.ts index 6898270205f2d..44fc8b1c2ba5d 100644 --- a/test/e2e/app-dir/ppr/ppr.test.ts +++ b/test/e2e/app-dir/ppr/ppr.test.ts @@ -2,7 +2,8 @@ import { nextTestSetup } from 'e2e-utils' import { retry, findAllTelemetryEvents } from 'next-test-utils' import stripAnsi from 'strip-ansi' -describe('ppr', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('ppr', () => { const { next, isNextDev, isNextStart } = nextTestSetup({ files: __dirname, env: { diff --git a/test/e2e/app-dir/react-max-headers-length/next.config.js b/test/e2e/app-dir/react-max-headers-length/next.config.js index 392447387f559..1befbe3f54ad4 100644 --- a/test/e2e/app-dir/react-max-headers-length/next.config.js +++ b/test/e2e/app-dir/react-max-headers-length/next.config.js @@ -7,7 +7,7 @@ const nextConfig = { : undefined, experimental: { // Emitting Link headers currently requires the experimental PPR feature. - ppr: true, + cacheComponents: true, }, } diff --git a/test/e2e/app-dir/rewrite-headers/rewrite-headers.test.ts b/test/e2e/app-dir/rewrite-headers/rewrite-headers.test.ts index 05e3fa49ba2b7..44fbef9546e21 100644 --- a/test/e2e/app-dir/rewrite-headers/rewrite-headers.test.ts +++ b/test/e2e/app-dir/rewrite-headers/rewrite-headers.test.ts @@ -42,7 +42,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -78,7 +78,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -114,7 +114,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -151,7 +151,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -187,7 +187,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -223,7 +223,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -259,7 +259,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -295,7 +295,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -339,7 +339,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } @@ -442,7 +442,7 @@ const cases: { headers: { rsc: '1', 'next-router-prefetch': '1', - ...(process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + ...(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? { 'next-router-segment-prefetch': '/_tree', } diff --git a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts index 2c1d7148dc55b..566146f8ae963 100644 --- a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts +++ b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts @@ -10,7 +10,8 @@ import { // TODO: We should decide on an established pattern for gating test assertions // on experimental flags. For example, as a first step we could all the common // gates like this one into a single module. -const isPPREnabledByDefault = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' +const isPPREnabledByDefault = + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' async function resolveStreamResponse(response: any, onData?: any) { let result = '' @@ -460,7 +461,7 @@ describe('app dir - rsc basics', () => { // TODO: (PPR) remove once PPR is stable // TODO(new-dev-overlay): remove once new dev overlay is stable const bundledReactVersionPattern = - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' ? '-experimental-' : '-canary-' diff --git a/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts b/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts index 6e91da53b1b10..a9f8677422692 100644 --- a/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts +++ b/test/e2e/app-dir/rsc-redirect/rsc-redirect.test.ts @@ -34,20 +34,21 @@ describe('rsc-redirect', () => { }) }) +// TODO: these tests aren't currently run at all during testing if (process.env.NODE_ENV === 'production') { describe.each([ - { ppr: true, segmentCache: true }, - { ppr: true, segmentCache: false }, - { ppr: false, segmentCache: true }, - { ppr: false, segmentCache: false }, + { cacheComponents: true, segmentCache: true }, + { cacheComponents: true, segmentCache: false }, + { cacheComponents: false, segmentCache: true }, + { cacheComponents: false, segmentCache: false }, ] as const)( - 'rsc-redirect /old-about -> /about (ppr: $ppr, segmentCache: $segmentCache)', - ({ ppr, segmentCache }) => { + 'rsc-redirect /old-about -> /about (cacheComponents: $cacheComponents, segmentCache: $segmentCache)', + ({ cacheComponents, segmentCache }) => { beforeAll(() => { // Write next.config.js with the current flags fs.writeFileSync( configPath, - `module.exports = { experimental: { ppr: ${ppr}, clientSegmentCache: ${segmentCache} } }\n` + `module.exports = { experimental: { cacheComponents: ${cacheComponents}, clientSegmentCache: ${segmentCache} } }\n` ) }) diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/loading.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/loading.tsx deleted file mode 100644 index 73c731c3c94a5..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Loading() { - return
    Loading dynamic content...
    -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/page.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/page.tsx deleted file mode 100644 index e662d1fbe3b44..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-with-ppr/page.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { connection } from 'next/server' - -export const experimental_ppr = true - -export default async function DynamicPage() { - await connection() - return
    Dynamic Content
    -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/loading.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/loading.tsx deleted file mode 100644 index 73c731c3c94a5..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Loading() { - return
    Loading dynamic content...
    -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/page.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/page.tsx deleted file mode 100644 index 8752988e11a82..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/dynamic-without-ppr/page.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { connection } from 'next/server' - -export default async function DynamicPage() { - await connection() - return
    Dynamic Content
    -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/layout.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/layout.tsx deleted file mode 100644 index dbce4ea8e3aeb..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/layout.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/page.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/page.tsx deleted file mode 100644 index fc5d921d5d732..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/page.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { LinkAccordion } from '../components/link-accordion' - -export default function Page() { - return ( -
    -

    - clientSegmentCache: 'client-only' -

    -

    - This page demonstrates the behavior when the experimental Segment Cache - flag is set to 'client-only' instead of true. - The new prefetching implementation is enabled on the client, but the - server will not generate any per-segment prefetching. This is useful - because the client implementation has many other improvements that are - unrelated to per-segment prefetching, like improved scheduling and - dynamic request deduping. -

    -
      -
    • - Static page -
    • -
    • - - Dynamic page (with PPR enabled) - -
    • -
    • - - Dynamic page (without PPR enabled) - -
    • -
    -
    - ) -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/static/page.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/app/static/page.tsx deleted file mode 100644 index 0a4f3cea8c64f..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/app/static/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function StaticPage() { - return
    Static Content
    -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/client-only-opt-in.test.ts b/test/e2e/app-dir/segment-cache/client-only-opt-in/client-only-opt-in.test.ts deleted file mode 100644 index e69e13f44625e..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/client-only-opt-in.test.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { nextTestSetup } from 'e2e-utils' -import type * as Playwright from 'playwright' -import { createRouterAct } from 'router-act' - -describe('segment cache prefetch scheduling', () => { - const { next, isNextDev } = nextTestSetup({ - files: __dirname, - }) - if (isNextDev) { - test('prefetching is disabled', () => {}) - return - } - - it('prefetches a static page in a single request', async () => { - let act: ReturnType - const browser = await next.browser('/', { - beforePageLoad(p: Playwright.Page) { - act = createRouterAct(p) - }, - }) - - // Because per-segment prefetching is not enabled in this app, the attempt - // to prefetch the route tree will return not just the tree but the data for - // the entire page. Although this prevents us from deduping shared layouts, - // we should seed the cache with the extra data to avoid a second request - // for the data. - const linkVisibilityToggle = await browser.elementByCss( - 'input[data-link-accordion="/static"]' - ) - await act( - async () => { - await linkVisibilityToggle.click() - }, - { - // This assertion will fail if this string appears in multiple requests. - includes: 'Static Content', - } - ) - - // When navigating to the prefetched static page, no additional requests - // are issued. - const link = await browser.elementByCss('a[href="/static"]') - await act(async () => { - await link.click() - const staticContent = await browser.elementById('static-content') - expect(await staticContent.innerHTML()).toBe('Static Content') - }, 'no-requests') - }) - - // TODO: This is disabled because, due to a recent change to metadata - // prefetches, sometimes a fully static page is requested twice unnecessarily. - // Disabling for now rather than fixing since it only happens in "client-only" - // mode, which was never properly supported or released, - // and we're about to delete. - it.skip('prefetches a dynamic page (with PPR enabled)', async () => { - let act: ReturnType - const browser = await next.browser('/', { - beforePageLoad(p: Playwright.Page) { - act = createRouterAct(p) - }, - }) - - const linkVisibilityToggle = await browser.elementByCss( - 'input[data-link-accordion="/dynamic-with-ppr"]' - ) - await act(async () => { - await linkVisibilityToggle.click() - }, [ - // This assertion will fail if this string appears in multiple requests. - { - includes: 'Loading dynamic content...', - }, - // Does not include the dynamic content - { - block: 'reject', - includes: 'Dynamic Content', - }, - ]) - - // When navigating to the prefetched dynamic page, an additional request - // is issued to fetch the dynamic content. - const link = await browser.elementByCss('a[href="/dynamic-with-ppr"]') - await act( - async () => { - await link.click() - }, - { - includes: 'Dynamic Content', - } - ) - const dynamicContent = await browser.elementById('dynamic-content') - expect(await dynamicContent.innerHTML()).toBe('Dynamic Content') - }) - - it('prefetches a dynamic page (without PPR enabled)', async () => { - let act: ReturnType - const browser = await next.browser('/', { - beforePageLoad(p: Playwright.Page) { - act = createRouterAct(p) - }, - }) - - const linkVisibilityToggle = await browser.elementByCss( - 'input[data-link-accordion="/dynamic-without-ppr"]' - ) - await act(async () => { - await linkVisibilityToggle.click() - }, [ - // This assertion will fail if this string appears in multiple requests. - { - includes: 'Loading dynamic content...', - }, - // Does not include the dynamic content - { - block: 'reject', - includes: 'Dynamic Content', - }, - ]) - - // When navigating to the prefetched dynamic page, an additional request - // is issued to fetch the dynamic content. - const link = await browser.elementByCss('a[href="/dynamic-without-ppr"]') - await act( - async () => { - await link.click() - }, - { - includes: 'Dynamic Content', - } - ) - const dynamicContent = await browser.elementById('dynamic-content') - expect(await dynamicContent.innerHTML()).toBe('Dynamic Content') - }) -}) diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/components/link-accordion.tsx b/test/e2e/app-dir/segment-cache/client-only-opt-in/components/link-accordion.tsx deleted file mode 100644 index c6848d479aef8..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/components/link-accordion.tsx +++ /dev/null @@ -1,33 +0,0 @@ -'use client' - -import Link, { type LinkProps } from 'next/link' -import { useState } from 'react' - -export function LinkAccordion({ - href, - children, - prefetch, -}: { - href: string - children: React.ReactNode - prefetch?: LinkProps['prefetch'] -}) { - const [isVisible, setIsVisible] = useState(false) - return ( - <> - setIsVisible(!isVisible)} - data-link-accordion={href} - /> - {isVisible ? ( - - {children} - - ) : ( - <>{children} (link is hidden) - )} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/client-only-opt-in/next.config.js b/test/e2e/app-dir/segment-cache/client-only-opt-in/next.config.js deleted file mode 100644 index 209191815e9e4..0000000000000 --- a/test/e2e/app-dir/segment-cache/client-only-opt-in/next.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @type {import('next').NextConfig} - */ -const nextConfig = { - experimental: { - ppr: 'incremental', - clientSegmentCache: 'client-only', - }, -} - -module.exports = nextConfig diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/[projectSlug]/monitoring/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/[projectSlug]/monitoring/page.jsx deleted file mode 100644 index bf6b50df6d8e0..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/[projectSlug]/monitoring/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { connection } from 'next/server' - -export default async function Page() { - await connection() - - return
    /[lang]/[teamSlug]/[projectSlug]/monitoring
    -} - -export const experimental_ppr = true diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/~/monitoring/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/~/monitoring/page.jsx deleted file mode 100644 index 73113af389085..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/[teamSlug]/~/monitoring/page.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import { connection } from 'next/server' - -export default async function Page() { - await connection() - - return
    /[lang]/[teamSlug]/~/monitoring
    -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/layout.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/layout.jsx deleted file mode 100644 index 088b825e33cad..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/layout.jsx +++ /dev/null @@ -1,11 +0,0 @@ -export default function RootLayout({ children, params }) { - return ( - - {children} - - ) -} - -export function generateStaticParams() { - return ['en', 'fr'].map((lang) => ({ lang })) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/loading.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/loading.jsx deleted file mode 100644 index 09367d77b06ee..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/loading.jsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Loading() { - return
    Loading...
    -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/page.jsx deleted file mode 100644 index a281b7a197c36..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/[lang]/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'next/link' - -export default function Page() { - return ( -
    - Monitoring -
    - ) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/layout.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/layout.jsx deleted file mode 100644 index 803f17d863c8a..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/layout.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function RootLayout({ children }) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/page.tsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/page.tsx deleted file mode 100644 index 72ece76bc5379..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/new/[teamSlug]/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return '/new/[teamSlug]/page.tsx' -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/[id]/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/[id]/page.jsx deleted file mode 100644 index b2b537ebca2f7..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/[id]/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { connection } from 'next/server' - -export default async function Page() { - await connection() - - return
    /prefetch-tests/[id]
    -} - -export const experimental_ppr = true diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/dynamic/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/dynamic/page.jsx deleted file mode 100644 index 9eb3f10e14e93..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/dynamic/page.jsx +++ /dev/null @@ -1,7 +0,0 @@ -import { connection } from 'next/server' - -export default async function Page() { - await connection() - - return
    /prefetch-tests/dynamic
    -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/layout.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/layout.jsx deleted file mode 100644 index 484952a22bcbe..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/layout.jsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function RootLayout({ children, params }) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/page.jsx b/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/page.jsx deleted file mode 100644 index baa9f6289f21c..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/app/prefetch-tests/page.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import Link from 'next/link' - -export default function Page() { - return ( -
    - Dynamic -
    - ) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/conflicting-routes.test.ts b/test/e2e/app-dir/segment-cache/conflicting-routes/conflicting-routes.test.ts deleted file mode 100644 index 01752a09b2ddc..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/conflicting-routes.test.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { nextTestSetup } from 'e2e-utils' -import { computeCacheBustingSearchParam } from 'next/dist/shared/lib/router/utils/cache-busting-search-param' - -describe('conflicting routes', () => { - const { next, isNextDev, isNextDeploy } = nextTestSetup({ - files: __dirname, - }) - if (isNextDev) { - test('prefetching is disabled', () => {}) - return - } - - // The server will reject prefetch requests that don't set a cache-busting - // search param. - // TODO: We should try to avoid unit tests that simulate internal client - // router requests. There are only a handful of cases that do this currently. - // In the meantime, consider moving this into a shared testing utility. - async function segmentPrefetch(url: string, segmentPath: string) { - const fetchUrl = new URL(url, 'http://localhost') - const searchParams = new URLSearchParams(fetchUrl.search) - searchParams.set( - '_rsc', - computeCacheBustingSearchParam('1', segmentPath, undefined, undefined) - ) - fetchUrl.search = searchParams.toString() - return await next.fetch(fetchUrl.pathname + fetchUrl.search, { - headers: { - rsc: '1', - 'next-router-prefetch': '1', - 'next-router-segment-prefetch': segmentPath, - }, - }) - } - - it.each([ - '/en/vercel/~/monitoring', - '/fr/vercel/~/monitoring', - '/es/vercel/~/monitoring', - ])('%s matches the right route', async (path) => { - const res = await segmentPrefetch(path, '/_tree') - expect(res.status).toBe(200) - - if (isNextDeploy) { - expect(res.headers.get('x-matched-path')).toBe( - '/[lang]/[teamSlug]/~/monitoring.prefetch.rsc' - ) - } - }) - - it('matches the right route when the original route has no dynamic params, is dynamic, and PPR is disabled', async () => { - const res = await segmentPrefetch('/prefetch-tests/dynamic', '/_tree') - expect(res.status).toBe(200) - - if (isNextDeploy) { - expect(res.headers.get('x-matched-path')).toBe( - '/prefetch-tests/dynamic.prefetch.rsc' - ) - } - }) - - it('handles conflict between App Router and Pages Router routes', async () => { - const res = await segmentPrefetch('/new/templates', '/_tree') - - expect(res.status).toBe(200) - expect(await res.text()).toContain( - // when deployed we map to an empty object to signal to - // client router it should MPA navigate - isNextDeploy ? '{}' : '/new/templates/[[...slug]].js' - ) - }) -}) diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/next.config.js b/test/e2e/app-dir/segment-cache/conflicting-routes/next.config.js deleted file mode 100644 index 1fb210a73ee9e..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/next.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @type {import('next').NextConfig} - */ -const nextConfig = { - experimental: { - ppr: 'incremental', - clientSegmentCache: true, - }, -} - -module.exports = nextConfig diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_app.js b/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_app.js deleted file mode 100644 index cf06318a0f30f..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_app.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function App({ Component, pageProps }) { - return -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_document.js b/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_document.js deleted file mode 100644 index 54e8bf3e2a290..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/_document.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Html, Head, Main, NextScript } from 'next/document' - -export default function Document() { - return ( - - - -
    - - - - ) -} diff --git a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/new/templates/[[...slug]].js b/test/e2e/app-dir/segment-cache/conflicting-routes/pages/new/templates/[[...slug]].js deleted file mode 100644 index acad19b3cc2c7..0000000000000 --- a/test/e2e/app-dir/segment-cache/conflicting-routes/pages/new/templates/[[...slug]].js +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return '/new/templates/[[...slug]].js' -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/layout.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/layout.tsx deleted file mode 100644 index dbce4ea8e3aeb..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/layout.tsx +++ /dev/null @@ -1,11 +0,0 @@ -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( - - {children} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/link-accordion.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/link-accordion.tsx deleted file mode 100644 index 40e57151e3055..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/link-accordion.tsx +++ /dev/null @@ -1,36 +0,0 @@ -'use client' - -import Link, { type LinkProps } from 'next/link' -import { useState } from 'react' - -export function LinkAccordion({ - href, - children, - prefetch, - id, -}: { - href: string - children: string - prefetch?: LinkProps['prefetch'] - id?: string -}) { - const [isVisible, setIsVisible] = useState(false) - return ( - <> - setIsVisible(!isVisible)} - data-link-accordion={href} - id={id} - /> - {isVisible ? ( - - {children} - - ) : ( - `${children} (link is hidden)` - )} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/layout.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/layout.tsx deleted file mode 100644 index cf9cbb2176600..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/layout.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { Suspense } from 'react' -import { connection } from 'next/server' - -async function DynamicContentInSharedLayout() { - await connection() - return ( -
    - Dynamic content in shared layout -
    - ) -} - -export default function SharedLayout({ - children, -}: { - children: React.ReactNode -}) { - return ( -
    - - Loading (PPR shell of shared-layout)... -
    - } - > - - - {children} - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-disabled/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-disabled/page.tsx deleted file mode 100644 index 94bb9c4715b42..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-disabled/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Suspense } from 'react' -import { connection } from 'next/server' - -async function Content() { - await connection() - return
    Dynamic page content
    -} - -export default async function Page() { - return ( - Loading page...}> - - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-enabled/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-enabled/page.tsx deleted file mode 100644 index 88abcd9dc8431..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/a/b/shared-layout/ppr-enabled/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Suspense } from 'react' -import { connection } from 'next/server' - -export const experimental_ppr = true - -async function Content() { - await connection() - return
    Dynamic page content
    -} - -export default async function Page() { - return ( - Loading page...}> - - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/layout.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/layout.tsx deleted file mode 100644 index 2806da8c0b0c7..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/layout.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function SharedLayout({ - children, -}: { - children: React.ReactNode -}) { - return
    {children}
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/loading.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/loading.tsx deleted file mode 100644 index dfcf368a51424..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/has-loading-boundary/loading.tsx +++ /dev/null @@ -1,7 +0,0 @@ -export default function Loading() { - return ( -
    - Loading (has-loading-boundary/loading.tsx)... -
    - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/page.tsx deleted file mode 100644 index bc02ad99ecf63..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/mixed-fetch-strategies/page.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { LinkAccordion } from '../link-accordion' - -export default function MixedFetchStrategies() { - return ( - <> -

    - This page tests what happens when a shared layout belongs to both a - PPR-enabled route and a non-PPR enabled route. The layout data should be - omitted when prefetching the non-PPR enabled route, because it's inside - another layout that has a loading boundary. But it should be included - when prefetching the route that has PPR enabled. -

    -
      -
    • - - Link to PPR enabled page - -
        -
      • - - Same link, but with prefetch="unstable_forceStale" - -
      • -
      -
    • -
    • - - Link to PPR disabled page - -
    • -
    - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/page.tsx deleted file mode 100644 index 1c3c2e2ac7744..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/page.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { LinkAccordion } from './link-accordion' - -export default function Page() { - return ( - <> -

    - This page is used to test that if you prefetch a link multiple times, - the prefetches are deduped by the client cache (unless/until they become - stale). The e2e associated with this page works by toggling the - visibility of the links and checking whether any prefetch requests are - issued. -

    -

    - You can test the behavior manually by opening up the network tab in the - browser's DevTools and seeing what happens when you toggle a Link's - visibility. -

    -
      -
    • - - Page with PPR enabled - -
    • -
    • - - Page with PPR enabled but has dynamic param - -
    • -
    • - - Page with PPR disabled - -
    • -
    • - - Page with PPR disabled, but has a loading boundary - -
        -
      • - - Another dynamic page that shares the same loading boundary - -
      • -
      -
    • -
    • - - Page with PPR disabled and a dynamic head, prefetch=true - -
    • -
    - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-dynamic-head/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-dynamic-head/page.tsx deleted file mode 100644 index 3d3488f4b41d5..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-dynamic-head/page.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Suspense } from 'react' -import { connection } from 'next/server' -import { Metadata } from 'next' - -export async function generateMetadata({ - searchParams, -}: { - searchParams: Promise<{ foo: string }> -}): Promise { - const { foo } = await searchParams - return { - title: 'Dynamic Title: ' + (foo ?? '(empty)'), - } -} - -async function Content() { - await connection() - return
    Page content
    -} - -export default function PPRDisabledDynamicHead() { - return ( - - - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/child/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/child/page.tsx deleted file mode 100644 index 07dd4704a4a36..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/child/page.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { connection } from 'next/server' - -export default async function PPRDisabledWithLoadingBoundaryChildPage() { - await connection() - return
    Child page content
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/loading.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/loading.tsx deleted file mode 100644 index d28ada742ee64..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/loading.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Loading() { - return
    Loading...
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/page.tsx deleted file mode 100644 index 379aaf559743a..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled-with-loading-boundary/page.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { connection } from 'next/server' - -export default async function PPRDisabledWithLoadingBoundary() { - await connection() - return
    Page content
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled/page.tsx deleted file mode 100644 index 71adef20a785a..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-disabled/page.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Suspense } from 'react' -import { connection } from 'next/server' - -async function Content() { - await connection() - return
    Page content
    -} - -export default function PPRDisabled() { - return ( - - - - ) -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/[dynamic-param]/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/[dynamic-param]/page.tsx deleted file mode 100644 index 20f9d2f245e60..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/[dynamic-param]/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Page() { - return
    Page content
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/layout.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/layout.tsx deleted file mode 100644 index 877c4a4112361..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -export const experimental_ppr = true - -export default function RootLayout({ - children, -}: { - children: React.ReactNode -}) { - return children -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/page.tsx b/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/page.tsx deleted file mode 100644 index b531e1eee30b6..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/app/ppr-enabled/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function PPREnabled() { - return
    Page content
    -} diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/next.config.js b/test/e2e/app-dir/segment-cache/incremental-opt-in/next.config.js deleted file mode 100644 index 1fb210a73ee9e..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/next.config.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @type {import('next').NextConfig} - */ -const nextConfig = { - experimental: { - ppr: 'incremental', - clientSegmentCache: true, - }, -} - -module.exports = nextConfig diff --git a/test/e2e/app-dir/segment-cache/incremental-opt-in/segment-cache-incremental-opt-in.test.ts b/test/e2e/app-dir/segment-cache/incremental-opt-in/segment-cache-incremental-opt-in.test.ts deleted file mode 100644 index 3d13c83f53a7d..0000000000000 --- a/test/e2e/app-dir/segment-cache/incremental-opt-in/segment-cache-incremental-opt-in.test.ts +++ /dev/null @@ -1,510 +0,0 @@ -import { nextTestSetup } from 'e2e-utils' -import { createRouterAct } from 'router-act' -import { Page } from 'playwright' - -describe('segment cache (incremental opt in)', () => { - const { next, isNextDev } = nextTestSetup({ - files: __dirname, - }) - if (isNextDev) { - test('ppr is disabled', () => {}) - return - } - - async function testPrefetchDeduping(linkHref) { - // This e2e test app is designed to verify that if you prefetch a link - // multiple times, the prefetches are deduped by the client cache - // (unless/until they become stale). It works by toggling the visibility of - // the links and checking whether any prefetch requests are issued. - // - // Throughout the duration of the test, we collect all the prefetch requests - // that occur. Then at the end we confirm there are no duplicates. - const prefetches = new Map() - const duplicatePrefetches = new Map() - const unexpectedResponses = [] - - let currentPage: Page - const browser = await next.browser('/', { - async beforePageLoad(page) { - currentPage = page - await page.route('**/*', async (route) => { - const request = route.request() - const headers = await request.allHeaders() - const isPrefetch = - headers['rsc'] !== undefined && - headers['next-router-prefetch'] !== undefined - if (isPrefetch) { - const url = request.url() - const prefetchInfo = { - href: new URL(url).pathname, - segment: headers['next-router-segment-prefetch'], - base: headers['next-router-state-tree'] ?? null, - } - const key = JSON.stringify(prefetchInfo) - if (prefetches.has(key)) { - duplicatePrefetches.set(key, prefetchInfo) - } else { - prefetches.set(key, prefetchInfo) - } - const response = await page.request.fetch(request, { - maxRedirects: 0, - }) - const status = response.status() - if (status !== 200) { - unexpectedResponses.push({ - status, - url, - headers: response.headers(), - response: await response.text(), - }) - } - return route.fulfill({ response }) - } - route.continue() - }) - }, - }) - - // Each link on the test page has a checkbox that controls its visibility. - // It starts off as hidden. - const checkbox = await browser.elementByCss( - `input[data-link-accordion="${linkHref}"]` - ) - // Confirm the checkbox is not checked - expect(await checkbox.isChecked()).toBe(false) - - // Click the checkbox to reveal the link and trigger a prefetch - await checkbox.click() - await browser.elementByCss(`a[href="${linkHref}"]`) - - // Toggle the visibility of the link. Prefetches are initiated on viewport, - // so if the cache does not dedupe then properly, this test will detect it. - await checkbox.click() // hide - await checkbox.click() // show - const link = await browser.elementByCss(`a[href="${linkHref}"]`) - - // Navigate to the target link - await link.click() - - // Confirm the navigation happened - await browser.elementById('page-content') - expect(new URL(await browser.url()).pathname).toBe(linkHref) - - // Wait for all pending requests to complete. - await currentPage.unrouteAll({ behavior: 'wait' }) - - // Finally, assert there were no duplicate prefetches and no unexpected - // responses. - expect(prefetches).not.toBeEmpty() - expect(duplicatePrefetches).toBeEmpty() - expect(unexpectedResponses).toBeEmpty() - } - - describe('multiple prefetches to same link are deduped', () => { - it('page with PPR enabled', () => testPrefetchDeduping('/ppr-enabled')) - it('page with PPR enabled, and has a dynamic param', () => - testPrefetchDeduping('/ppr-enabled/dynamic-param')) - it('page with PPR disabled', () => testPrefetchDeduping('/ppr-disabled')) - it('page with PPR disabled, and has a loading boundary', () => - testPrefetchDeduping('/ppr-disabled-with-loading-boundary')) - }) - - it('prefetches a dynamic route when PPR is disabled if it has a loading.tsx boundary', async () => { - let act - const browser = await next.browser('/', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Initiate a prefetch for a dynamic page with no PPR, but with a - // loading.tsx boundary. We should be able to prefetch up to the - // loading boundary. - await act(async () => { - const checkbox = await browser.elementByCss( - `input[data-link-accordion="/ppr-disabled-with-loading-boundary"]` - ) - await checkbox.click() - }, [ - // Response includes the loading boundary - { includes: 'Loading...' }, - // but it does not include the dynamic page content - { includes: 'Page content', block: 'reject' }, - ]) - - // Navigate to the page - await act( - async () => { - await browser - .elementByCss(`a[href="/ppr-disabled-with-loading-boundary"]`) - .click() - // We can immediately render the loading boundary before the network - // responds, because it was prefetched - const loadingBoundary = await browser.elementById('loading-boundary') - expect(await loadingBoundary.text()).toBe('Loading...') - }, - // The page content is fetched on navigation - { includes: 'Page content' } - ) - const pageContent = await browser.elementById('page-content') - expect(await pageContent.text()).toBe('Page content') - }) - - it( - 'skips prefetching a dynamic route when PPR is disabled if everything up ' + - 'to its loading.tsx boundary is already cached', - async () => { - let act - const browser = await next.browser('/', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Initiate a prefetch for a dynamic page with no PPR, but with a - // loading.tsx boundary. We should be able to prefetch up to the - // loading boundary. - await act(async () => { - const checkbox = await browser.elementByCss( - `input[data-link-accordion="/ppr-disabled-with-loading-boundary"]` - ) - await checkbox.click() - }, [ - // Response includes the loading boundary - { includes: 'Loading...' }, - // but it does not include the dynamic page content - { includes: 'Page content', block: 'reject' }, - ]) - - // When prefetching a different page with the same loading boundary, - // we should not need to fetch the loading boundary again - await act( - async () => { - const checkbox = await browser.elementByCss( - `input[data-link-accordion="/ppr-disabled-with-loading-boundary/child"]` - ) - await checkbox.click() - }, - { includes: 'Loading...', block: 'reject' } - ) - - // Navigate to the page - await act(async () => { - await browser - .elementByCss(`a[href="/ppr-disabled-with-loading-boundary/child"]`) - .click() - // We can immediately render the loading boundary before the network - // responds, because it was prefetched - const loadingBoundary = await browser.elementById('loading-boundary') - expect(await loadingBoundary.text()).toBe('Loading...') - }, [ - // The page content is fetched on navigation - { includes: 'Child page content' }, - // The loading boundary is not fetched on navigation, because it - // was already loaded into the cache during the prefetch for the - // other page. - { includes: 'Loading...', block: 'reject' }, - ]) - const pageContent = await browser.elementById('child-page-content') - expect(await pageContent.text()).toBe('Child page content') - } - ) - - it('skips prefetching a dynamic route when PPR is disabled if it has no loading.tsx boundary', async () => { - let act - const browser = await next.browser('/', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Initiate a prefetch for a dynamic page with no loading.tsx and no PPR. - // The route tree prefetch will tell the client that there is no loading - // boundary, and therefore the client can skip prefetching the data, since - // it would be an empty response, anyway. - await act( - async () => { - const checkbox = await browser.elementByCss( - `input[data-link-accordion="/ppr-disabled"]` - ) - await checkbox.click() - }, - // We should not prefetch the page content - { includes: 'Page content', block: 'reject' } - ) - - // Navigate to the page - await act( - async () => { - await browser.elementByCss(`a[href="/ppr-disabled"]`).click() - }, - // The page content is fetched on navigation - { includes: 'Page content' } - ) - const pageContent = await browser.elementById('page-content') - expect(await pageContent.text()).toBe('Page content') - }) - - it( - 'prefetches a shared layout on a PPR-enabled route that was previously ' + - 'omitted from a non-PPR-enabled route', - async () => { - let act - const browser = await next.browser('/mixed-fetch-strategies', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Initiate a prefetch for the PPR-disabled route first. This will not - // include the /shared-layout/ segment, because it's inside the - // loading boundary. - await act(async () => { - const checkbox = await browser.elementById('ppr-disabled') - await checkbox.click() - }) - - // Then initiate a prefetch for the PPR-enabled route. This prefetch - // should include the /shared-layout/ segment despite the presence of - // the loading boundary, and despite the earlier non-PPR attempt - await act(async () => { - const checkbox = await browser.elementById('ppr-enabled') - await checkbox.click() - }) - - // Navigate to the PPR-enabled route - await act(async () => { - const link = await browser.elementByCss('#ppr-enabled + a') - await link.click() - - // If we prefetched all the segments correctly, we should be able to - // reveal the page's loading state, before the server responds. - await browser.elementById('page-loading-boundary') - }) - } - ) - - it( - 'when a link is prefetched with , no dynamic request ' + - 'is made on navigation', - async () => { - let act - const browser = await next.browser('/mixed-fetch-strategies', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - await act( - async () => { - const checkbox = await browser.elementById( - 'ppr-enabled-prefetch-true' - ) - await checkbox.click() - }, - { - includes: 'Dynamic page content', - } - ) - - // Navigate to fully prefetched route - const link = await browser.elementByCss('#ppr-enabled-prefetch-true + a') - await act( - async () => { - await link.click() - - // We should be able to fully load the page content, including the - // dynamic data, before the server responds. - await browser.elementById('page-content') - }, - // Assert that no network requests are initiated within this block. - 'no-requests' - ) - } - ) - - it( - 'when prefetching with prefetch="unstable_forceStale", refetches cache entries that only ' + - 'contain partial data', - async () => { - let act - const browser = await next.browser('/mixed-fetch-strategies', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Prefetch a link with PPR - await act( - async () => { - const checkbox = await browser.elementById('ppr-enabled') - await checkbox.click() - }, - { includes: 'Loading (PPR shell of shared-layout)...' } - ) - - // Prefetch the same link again, this time with prefetch="unstable_forceStale" to include - // the dynamic data - await act( - async () => { - const checkbox = await browser.elementById( - 'ppr-enabled-prefetch-true' - ) - await checkbox.click() - }, - { - includes: 'Dynamic content in shared layout', - } - ) - - // Navigate to the PPR-enabled route - const link = await browser.elementByCss('#ppr-enabled-prefetch-true + a') - await act( - async () => { - await link.click() - - // If we prefetched all the segments correctly, we should be able to - // fully load the page content, including the dynamic data, before the - // server responds. - // - // If this fails, it likely means that the partial cache entry that - // resulted from prefetching the normal link () - // was not properly re-fetched when the full link () was prefetched. - await browser.elementById('page-content') - }, - // Assert that no network requests are initiated within this block. - 'no-requests' - ) - } - ) - - it( - 'when prefetching with prefetch="unstable_forceStale", refetches partial cache entries ' + - "even if there's already a pending PPR request", - async () => { - // This test is hard to describe succinctly because it involves a fairly - // complex race condition between a non-PPR prefetch, a PPR prefetch, and - // a "full" prefetch. Despite the complexity of the scenario, it's worth - // testing because could easily happen in real world conditions. - - let act - const browser = await next.browser('/mixed-fetch-strategies', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - // Initiate a prefetch for the PPR-disabled route first. This will not - // include the /shared-layout/ segment, because it's inside the - // loading boundary. - await act( - async () => { - const checkbox = await browser.elementById('ppr-disabled') - await checkbox.click() - }, - { includes: 'Loading (has-loading-boundary/loading.tsx)...' } - ) - - // Then initiate a prefetch for the PPR-enabled route. - await act(async () => { - // Create an inner act scope so we initate a prefetch but block it - // from responding. - await act( - async () => { - const checkbox = await browser.elementById('ppr-enabled') - await checkbox.click() - }, - { - // This prefetch should include the /shared-layout/ segment despite - // the presence of the loading boundary, and despite the earlier - // non-PPR attempt. - includes: 'Loading (PPR shell of shared-layout)...', - // We're going to block it from responding, so we can test what - // happens if another prefetch is initiated in the meantime. - block: true, - } - ) - - // Before the previous prefetch finishes, prefetch the same link again, - // this time with prefetch="unstable_forceStale" to include the dynamic data. - await act( - async () => { - const checkbox = await browser.elementById( - 'ppr-enabled-prefetch-true' - ) - await checkbox.click() - }, - // This prefetch should load the dynamic data in the shared layout - { - includes: 'Dynamic content in shared layout', - } - ) - }) - - // Navigate to the PPR-enabled route. - await act( - async () => { - const link = await browser.elementByCss( - '#ppr-enabled-prefetch-true + a' - ) - await link.click() - - // If we prefetched all the segments correctly, we should be able to - // fully load the page content, including the dynamic data, before the - // server responds. - // - // If this fails, it likely means that the pending cache entry that - // resulted from prefetching the normal link () - // was not properly re-fetched when the full link () was prefetched. - await browser.elementById('page-content') - }, - // Assert that no network requests are initiated within this block. - 'no-requests' - ) - } - ) - - it('fully prefetch a page with a dynamic title', async () => { - let act - const browser = await next.browser('/', { - beforePageLoad(p) { - act = createRouterAct(p) - }, - }) - - await act( - async () => { - const checkbox = await browser.elementByCss( - 'input[data-link-accordion="/ppr-disabled-dynamic-head?foo=yay"]' - ) - await checkbox.click() - }, - // Because the link is prefetched with prefetch=true, we should be able to - // prefetch the title, even though it's dynamic. - { - includes: 'Dynamic Title: yay', - // TODO: Due to a race condition, the metadata is sometimes fetched twice - // instead of once (though not more than that). The planned fix is to - // cache metadata separate from the route tree. Then we can remove - // this option. - allowMultipleResponses: true, - } - ) - - // When we navigate to the page, it should not make any additional - // network requests, because both the segment data and the head were - // fully prefetched. - await act(async () => { - const link = await browser.elementByCss( - 'a[href="/ppr-disabled-dynamic-head?foo=yay"]' - ) - await link.click() - const pageContent = await browser.elementById('page-content') - expect(await pageContent.text()).toBe('Page content') - const title = await browser.eval(() => document.title) - expect(title).toBe('Dynamic Title: yay') - }, 'no-requests') - }) -}) diff --git a/test/e2e/app-dir/static-shell-debugging/static-shell-debugging.test.ts b/test/e2e/app-dir/static-shell-debugging/static-shell-debugging.test.ts index 781816be8bbd7..c0b5d75f4ab4a 100644 --- a/test/e2e/app-dir/static-shell-debugging/static-shell-debugging.test.ts +++ b/test/e2e/app-dir/static-shell-debugging/static-shell-debugging.test.ts @@ -1,7 +1,8 @@ import { nextTestSetup } from 'e2e-utils' -describe('static-shell-debugging', () => { - const ppr = Boolean(process.env.__NEXT_EXPERIMENTAL_PPR) +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('static-shell-debugging', () => { + const ppr = Boolean(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) const context = { ppr, debugging: ppr, diff --git a/test/e2e/app-dir/sub-shell-generation-middleware/sub-shell-generation-middleware.test.ts b/test/e2e/app-dir/sub-shell-generation-middleware/sub-shell-generation-middleware.test.ts index 7180f9e73a5c3..0009d7f2ce823 100644 --- a/test/e2e/app-dir/sub-shell-generation-middleware/sub-shell-generation-middleware.test.ts +++ b/test/e2e/app-dir/sub-shell-generation-middleware/sub-shell-generation-middleware.test.ts @@ -13,10 +13,7 @@ describe('middleware-static-rewrite', () => { return } - if ( - process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' || - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' - ) { + if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true') { // Here we're validating that the correct fallback shell was used for // rendering. it('should use the correct fallback route', async () => { diff --git a/test/e2e/app-dir/use-cache-output-export/use-cache-output-export.test.ts b/test/e2e/app-dir/use-cache-output-export/use-cache-output-export.test.ts index f5e0fa2cbfdae..dc0b932c01962 100644 --- a/test/e2e/app-dir/use-cache-output-export/use-cache-output-export.test.ts +++ b/test/e2e/app-dir/use-cache-output-export/use-cache-output-export.test.ts @@ -10,7 +10,7 @@ describe('use-cache-output-export', () => { skipStart: process.env.NEXT_TEST_MODE !== 'dev', }) - if (process.env.__NEXT_EXPERIMENTAL_PPR === 'true') { + if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true') { return it.skip('for PPR', () => { // PPR is not compatible with `output: 'export'`. }) diff --git a/test/e2e/app-dir/use-cache-private/use-cache-private.test.ts b/test/e2e/app-dir/use-cache-private/use-cache-private.test.ts index cf0e4a6378b58..bc1fec7ce7328 100644 --- a/test/e2e/app-dir/use-cache-private/use-cache-private.test.ts +++ b/test/e2e/app-dir/use-cache-private/use-cache-private.test.ts @@ -1,8 +1,6 @@ import { nextTestSetup } from 'e2e-utils' -const pprEnabled = - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' || - process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' +const pprEnabled = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' describe('use-cache-private', () => { const { next, isNextDev } = nextTestSetup({ diff --git a/test/e2e/app-dir/use-cache-with-server-function-props/next.config.js b/test/e2e/app-dir/use-cache-with-server-function-props/next.config.js index bea0706290af6..e9480643df622 100644 --- a/test/e2e/app-dir/use-cache-with-server-function-props/next.config.js +++ b/test/e2e/app-dir/use-cache-with-server-function-props/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, useCache: true, }, } diff --git a/test/e2e/app-dir/use-cache/use-cache.test.ts b/test/e2e/app-dir/use-cache/use-cache.test.ts index bfb730e6c050f..bf456aebceb97 100644 --- a/test/e2e/app-dir/use-cache/use-cache.test.ts +++ b/test/e2e/app-dir/use-cache/use-cache.test.ts @@ -16,8 +16,6 @@ import { PrerenderManifest } from 'next/dist/build' const GENERIC_RSC_ERROR = 'An error occurred in the Server Components render. The specific message is omitted in production builds to avoid leaking sensitive details. A digest property is included on this error instance which may provide additional details about the nature of the error.' -const withPPR = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' - const withCacheComponents = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' @@ -451,7 +449,7 @@ describe('use-cache', () => { let prerenderedRoutes = Object.entries(prerenderManifest.routes) - if (withPPR || withCacheComponents) { + if (withCacheComponents) { // For the purpose of this test we don't consider an incomplete shell. prerenderedRoutes = prerenderedRoutes.filter(([pathname, route]) => { const filename = pathname.replace(/^\//, '').replace(/^$/, 'index') @@ -508,7 +506,7 @@ describe('use-cache', () => { }) it('should match the expected revalidate and expire configs on the prerender manifest', async () => { - const { version, routes, dynamicRoutes } = JSON.parse( + const { version, routes } = JSON.parse( await next.readFile('.next/prerender-manifest.json') ) as PrerenderManifest @@ -525,14 +523,6 @@ describe('use-cache', () => { expect(routes['/cache-life-with-dynamic'].initialExpireSeconds).toBe( 300 ) - } else if (withPPR) { - // We don't exclude dynamic caches for the legacy PPR prerendering. - expect( - routes['/cache-life-with-dynamic'].initialRevalidateSeconds - ).toBe(99) - expect(routes['/cache-life-with-dynamic'].initialExpireSeconds).toBe( - 299 - ) } // default expireTime @@ -541,12 +531,6 @@ describe('use-cache', () => { // The revalidate config from the fetch call should lower the revalidate // config for the page. expect(routes['/cache-tag'].initialRevalidateSeconds).toBe(42) - - if (withPPR) { - // cache life profile "weeks" - expect(dynamicRoutes['/[id]'].fallbackRevalidate).toBe(604800) - expect(dynamicRoutes['/[id]'].fallbackExpire).toBe(2592000) - } }) it('should match the expected stale config in the page header', async () => { @@ -562,14 +546,6 @@ describe('use-cache', () => { expect(cacheLifeWithDynamicMeta.headers['x-nextjs-stale-time']).toBe( '19' ) - } else if (withPPR) { - const cacheLifeWithDynamicMeta = JSON.parse( - await next.readFile('.next/server/app/cache-life-with-dynamic.meta') - ) - // We don't exclude dynamic caches for the legacy PPR prerendering. - expect(cacheLifeWithDynamicMeta.headers['x-nextjs-stale-time']).toBe( - '18' - ) } }) @@ -1020,7 +996,7 @@ describe('use-cache', () => { }) } - if (isNextStart && withPPR) { + if (isNextStart && withCacheComponents) { it('should exclude inner caches and omitted caches from the resume data cache (RDC)', async () => { await next.fetch('/rdc') diff --git a/test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts b/test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts index 5cf2ee50f3b22..535553e1e2945 100644 --- a/test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts +++ b/test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts @@ -63,976 +63,968 @@ describe('opentelemetry', () => { }, }, ]) { - ;(process.env.__NEXT_EXPERIMENTAL_PPR ? describe.skip : describe)( - env.name, - () => { - describe('app router', () => { - it('should handle RSC with fetch', async () => { - await next.fetch('/app/param/rsc-fetch', env.fetchInit) + ;(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS + ? describe.skip + : describe)(env.name, () => { + describe('app router', () => { + it('should handle RSC with fetch', async () => { + await next.fetch('/app/param/rsc-fetch', env.fetchInit) - await expectTrace(getCollector(), [ + await expectTrace(getCollector(), [ + { + name: 'GET /app/[param]/rsc-fetch', + attributes: { + 'http.method': 'GET', + 'http.route': '/app/[param]/rsc-fetch', + 'http.status_code': 200, + 'http.target': '/app/param/rsc-fetch', + 'next.route': '/app/[param]/rsc-fetch', + 'next.rsc': false, + 'next.span_name': 'GET /app/[param]/rsc-fetch', + 'next.span_type': 'BaseServer.handleRequest', + }, + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: 'render route (app) /app/[param]/rsc-fetch', + attributes: { + 'next.route': '/app/[param]/rsc-fetch', + 'next.span_name': + 'render route (app) /app/[param]/rsc-fetch', + 'next.span_type': 'AppRender.getBodyResult', + }, + kind: 0, + status: { code: 0 }, + spans: [ + { + name: 'build component tree', + attributes: { + 'next.span_name': 'build component tree', + 'next.span_type': 'NextNodeServer.createComponentTree', + }, + kind: 0, + status: { code: 0 }, + spans: [ + { + name: 'resolve segment modules', + attributes: { + 'next.segment': '__PAGE__', + 'next.span_name': 'resolve segment modules', + 'next.span_type': + 'NextNodeServer.getLayoutOrPageModule', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve segment modules', + attributes: { + 'next.segment': '[param]', + 'next.span_name': 'resolve segment modules', + 'next.span_type': + 'NextNodeServer.getLayoutOrPageModule', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + { + name: 'fetch GET https://example.vercel.sh/', + attributes: { + 'http.method': 'GET', + 'http.url': 'https://example.vercel.sh/', + 'net.peer.name': 'example.vercel.sh', + 'next.span_name': + 'fetch GET https://example.vercel.sh/', + 'next.span_type': 'AppRender.fetch', + }, + kind: 2, + status: { code: 0 }, + }, + { + name: 'generateMetadata /app/[param]/layout', + attributes: { + 'next.page': '/app/[param]/layout', + 'next.span_name': + 'generateMetadata /app/[param]/layout', + 'next.span_type': 'ResolveMetadata.generateMetadata', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'generateMetadata /app/[param]/rsc-fetch/page', + attributes: { + 'next.page': '/app/[param]/rsc-fetch/page', + 'next.span_name': + 'generateMetadata /app/[param]/rsc-fetch/page', + 'next.span_type': 'ResolveMetadata.generateMetadata', + }, + kind: 0, + status: { code: 0 }, + }, + { + attributes: { + 'next.clientComponentLoadCount': isNextDev ? 7 : 6, + 'next.span_type': + 'NextNodeServer.clientComponentLoading', + }, + kind: 0, + name: 'NextNodeServer.clientComponentLoading', + status: { + code: 0, + }, + }, + { + name: 'start response', + attributes: { + 'next.span_name': 'start response', + 'next.span_type': 'NextNodeServer.startResponse', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + { + name: 'resolve page components', + attributes: { + 'next.route': '/app/[param]/rsc-fetch', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + ]) + }) + + it('should propagate custom context without span', async () => { + await next.fetch('/app/param/rsc-fetch', { + ...env.fetchInit, + headers: { ...env.fetchInit?.headers, 'x-custom': 'custom1' }, + }) + + await expectTrace(getCollector(), [ + { + name: 'GET /app/[param]/rsc-fetch', + attributes: { + custom: 'custom1', + }, + }, + ]) + }) + + it('should handle RSC with fetch on edge', async () => { + await next.fetch('/app/param/rsc-fetch/edge', env.fetchInit) + + await expectTrace( + getCollector(), + [ { - name: 'GET /app/[param]/rsc-fetch', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + runtime: 'edge', + name: 'GET /app/[param]/rsc-fetch/edge', + kind: 1, attributes: { + 'next.span_name': 'GET /app/[param]/rsc-fetch/edge', + 'next.span_type': 'BaseServer.handleRequest', 'http.method': 'GET', - 'http.route': '/app/[param]/rsc-fetch', + 'http.target': '/app/param/rsc-fetch/edge?param=param', 'http.status_code': 200, - 'http.target': '/app/param/rsc-fetch', - 'next.route': '/app/[param]/rsc-fetch', - 'next.rsc': false, - 'next.span_name': 'GET /app/[param]/rsc-fetch', - 'next.span_type': 'BaseServer.handleRequest', + 'next.route': '/app/[param]/rsc-fetch/edge', + 'http.route': '/app/[param]/rsc-fetch/edge', }, - kind: 1, status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, spans: [ { - name: 'render route (app) /app/[param]/rsc-fetch', + name: 'render route (app) /app/[param]/rsc-fetch/edge', + kind: 0, attributes: { - 'next.route': '/app/[param]/rsc-fetch', 'next.span_name': - 'render route (app) /app/[param]/rsc-fetch', + 'render route (app) /app/[param]/rsc-fetch/edge', 'next.span_type': 'AppRender.getBodyResult', + 'next.route': '/app/[param]/rsc-fetch/edge', }, - kind: 0, status: { code: 0 }, spans: [ { name: 'build component tree', + kind: 0, attributes: { 'next.span_name': 'build component tree', 'next.span_type': 'NextNodeServer.createComponentTree', }, - kind: 0, status: { code: 0 }, spans: [ { name: 'resolve segment modules', + kind: 0, attributes: { - 'next.segment': '__PAGE__', 'next.span_name': 'resolve segment modules', 'next.span_type': 'NextNodeServer.getLayoutOrPageModule', + 'next.segment': '__PAGE__', }, - kind: 0, status: { code: 0 }, }, { name: 'resolve segment modules', + kind: 0, attributes: { - 'next.segment': '[param]', 'next.span_name': 'resolve segment modules', 'next.span_type': 'NextNodeServer.getLayoutOrPageModule', + 'next.segment': '[param]', }, - kind: 0, status: { code: 0 }, }, ], }, { name: 'fetch GET https://example.vercel.sh/', + kind: 2, attributes: { - 'http.method': 'GET', - 'http.url': 'https://example.vercel.sh/', - 'net.peer.name': 'example.vercel.sh', 'next.span_name': 'fetch GET https://example.vercel.sh/', 'next.span_type': 'AppRender.fetch', + 'http.url': 'https://example.vercel.sh/', + 'http.method': 'GET', + 'net.peer.name': 'example.vercel.sh', }, - kind: 2, status: { code: 0 }, }, { name: 'generateMetadata /app/[param]/layout', + kind: 0, attributes: { - 'next.page': '/app/[param]/layout', 'next.span_name': 'generateMetadata /app/[param]/layout', 'next.span_type': 'ResolveMetadata.generateMetadata', + 'next.page': '/app/[param]/layout', }, - kind: 0, status: { code: 0 }, }, { - name: 'generateMetadata /app/[param]/rsc-fetch/page', + name: 'generateMetadata /app/[param]/rsc-fetch/edge/page', + kind: 0, attributes: { - 'next.page': '/app/[param]/rsc-fetch/page', 'next.span_name': - 'generateMetadata /app/[param]/rsc-fetch/page', + 'generateMetadata /app/[param]/rsc-fetch/edge/page', 'next.span_type': 'ResolveMetadata.generateMetadata', + 'next.page': '/app/[param]/rsc-fetch/edge/page', }, - kind: 0, - status: { code: 0 }, - }, - { - attributes: { - 'next.clientComponentLoadCount': isNextDev ? 7 : 6, - 'next.span_type': - 'NextNodeServer.clientComponentLoading', - }, - kind: 0, - name: 'NextNodeServer.clientComponentLoading', - status: { - code: 0, - }, - }, - { - name: 'start response', - attributes: { - 'next.span_name': 'start response', - 'next.span_type': 'NextNodeServer.startResponse', - }, - kind: 0, status: { code: 0 }, }, ], }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/app/[param]/rsc-fetch', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, - }, ], }, - ]) + ], + true + ) + }) + + it('should handle RSC with fetch in RSC mode', async () => { + await next.fetch(`/app/param/rsc-fetch?${NEXT_RSC_UNION_QUERY}`, { + ...env.fetchInit, + headers: { + ...env.fetchInit?.headers, + Rsc: '1', + }, }) - it('should propagate custom context without span', async () => { - await next.fetch('/app/param/rsc-fetch', { - ...env.fetchInit, - headers: { ...env.fetchInit?.headers, 'x-custom': 'custom1' }, - }) + await expectTrace(getCollector(), [ + { + runtime: 'nodejs', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'RSC GET /app/[param]/rsc-fetch', + attributes: { + 'http.method': 'GET', + 'http.route': '/app/[param]/rsc-fetch', + 'http.status_code': 200, + 'http.target': `/app/param/rsc-fetch?${NEXT_RSC_UNION_QUERY}`, + 'next.route': '/app/[param]/rsc-fetch', + 'next.rsc': true, + 'next.span_name': 'RSC GET /app/[param]/rsc-fetch', + 'next.span_type': 'BaseServer.handleRequest', + }, + kind: 1, + status: { code: 0 }, + }, + ]) + }) + + it('should handle route handlers in app router', async () => { + await next.fetch('/api/app/param/data', env.fetchInit) + + await expectTrace(getCollector(), [ + { + name: 'GET /api/app/[param]/data', + attributes: { + 'http.method': 'GET', + 'http.route': '/api/app/[param]/data', + 'http.status_code': 200, + 'http.target': '/api/app/param/data', + 'next.route': '/api/app/[param]/data', + 'next.span_name': 'GET /api/app/[param]/data', + 'next.span_type': 'BaseServer.handleRequest', + }, + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: 'executing api route (app) /api/app/[param]/data', + attributes: { + 'next.route': '/api/app/[param]/data', + 'next.span_name': + 'executing api route (app) /api/app/[param]/data', + 'next.span_type': 'AppRouteRouteHandlers.runHandler', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve page components', + attributes: { + 'next.route': '/api/app/[param]/data', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'start response', + attributes: { + 'next.span_name': 'start response', + 'next.span_type': 'NextNodeServer.startResponse', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + ]) + }) + + it('should handle route handlers in app router on edge', async () => { + await next.fetch('/api/app/param/data/edge', env.fetchInit) - await expectTrace(getCollector(), [ + await expectTrace( + getCollector(), + [ { - name: 'GET /app/[param]/rsc-fetch', + runtime: 'edge', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'executing api route (app) /api/app/[param]/data/edge', attributes: { - custom: 'custom1', + 'next.route': '/api/app/[param]/data/edge', + 'next.span_name': + 'executing api route (app) /api/app/[param]/data/edge', + 'next.span_type': 'AppRouteRouteHandlers.runHandler', }, + kind: 0, + status: { code: 0 }, }, - ]) - }) + ], + true + ) + }) + + it('should trace middleware', async () => { + await next.fetch('/behind-middleware', env.fetchInit) + + await expectTrace(getCollector(), [ + { + runtime: 'edge', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'middleware GET', + attributes: { + 'http.method': 'GET', + 'http.target': '/behind-middleware', + 'next.span_name': 'middleware GET', + 'next.span_type': 'Middleware.execute', + }, + status: { code: 0 }, + spans: [], + }, + + { + runtime: 'nodejs', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'GET /behind-middleware', + attributes: { + 'http.method': 'GET', + 'http.route': '/behind-middleware', + 'http.status_code': 200, + 'http.target': '/behind-middleware', + 'next.route': '/behind-middleware', + 'next.span_name': 'GET /behind-middleware', + 'next.span_type': 'BaseServer.handleRequest', + }, + }, + ]) + }) - it('should handle RSC with fetch on edge', async () => { - await next.fetch('/app/param/rsc-fetch/edge', env.fetchInit) + it('should handle error in RSC', async () => { + await next.fetch( + '/app/param/rsc-fetch/error?status=error', + env.fetchInit + ) - await expectTrace( - getCollector(), - [ + await expectTrace(getCollector(), [ + { + name: 'GET /app/[param]/rsc-fetch/error', + attributes: { + 'http.method': 'GET', + 'http.route': '/app/[param]/rsc-fetch/error', + 'http.status_code': 500, + 'http.target': '/app/param/rsc-fetch/error?status=error', + 'next.route': '/app/[param]/rsc-fetch/error', + 'next.rsc': false, + 'next.span_name': 'GET /app/[param]/rsc-fetch/error', + 'next.span_type': 'BaseServer.handleRequest', + 'error.type': '500', + }, + kind: 1, + status: { code: 2 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ { - traceId: env.span.traceId, - parentId: env.span.rootParentId, - runtime: 'edge', - name: 'GET /app/[param]/rsc-fetch/edge', - kind: 1, + name: 'render route (app) /app/[param]/rsc-fetch/error', attributes: { - 'next.span_name': 'GET /app/[param]/rsc-fetch/edge', - 'next.span_type': 'BaseServer.handleRequest', - 'http.method': 'GET', - 'http.target': '/app/param/rsc-fetch/edge?param=param', - 'http.status_code': 200, - 'next.route': '/app/[param]/rsc-fetch/edge', - 'http.route': '/app/[param]/rsc-fetch/edge', + 'next.route': '/app/[param]/rsc-fetch/error', + 'next.span_name': + 'render route (app) /app/[param]/rsc-fetch/error', + 'next.span_type': 'AppRender.getBodyResult', }, - status: { code: 0 }, + kind: 0, + status: { code: 2 }, spans: [ { - name: 'render route (app) /app/[param]/rsc-fetch/edge', - kind: 0, + name: 'build component tree', attributes: { - 'next.span_name': - 'render route (app) /app/[param]/rsc-fetch/edge', - 'next.span_type': 'AppRender.getBodyResult', - 'next.route': '/app/[param]/rsc-fetch/edge', + 'next.span_name': 'build component tree', + 'next.span_type': 'NextNodeServer.createComponentTree', }, + kind: 0, status: { code: 0 }, spans: [ { - name: 'build component tree', - kind: 0, + name: 'resolve segment modules', attributes: { - 'next.span_name': 'build component tree', + 'next.segment': '__PAGE__', + 'next.span_name': 'resolve segment modules', 'next.span_type': - 'NextNodeServer.createComponentTree', - }, - status: { code: 0 }, - spans: [ - { - name: 'resolve segment modules', - kind: 0, - attributes: { - 'next.span_name': 'resolve segment modules', - 'next.span_type': - 'NextNodeServer.getLayoutOrPageModule', - 'next.segment': '__PAGE__', - }, - status: { code: 0 }, - }, - { - name: 'resolve segment modules', - kind: 0, - attributes: { - 'next.span_name': 'resolve segment modules', - 'next.span_type': - 'NextNodeServer.getLayoutOrPageModule', - 'next.segment': '[param]', - }, - status: { code: 0 }, - }, - ], - }, - { - name: 'fetch GET https://example.vercel.sh/', - kind: 2, - attributes: { - 'next.span_name': - 'fetch GET https://example.vercel.sh/', - 'next.span_type': 'AppRender.fetch', - 'http.url': 'https://example.vercel.sh/', - 'http.method': 'GET', - 'net.peer.name': 'example.vercel.sh', + 'NextNodeServer.getLayoutOrPageModule', }, - status: { code: 0 }, - }, - { - name: 'generateMetadata /app/[param]/layout', kind: 0, - attributes: { - 'next.span_name': - 'generateMetadata /app/[param]/layout', - 'next.span_type': - 'ResolveMetadata.generateMetadata', - 'next.page': '/app/[param]/layout', - }, status: { code: 0 }, }, { - name: 'generateMetadata /app/[param]/rsc-fetch/edge/page', - kind: 0, + name: 'resolve segment modules', attributes: { - 'next.span_name': - 'generateMetadata /app/[param]/rsc-fetch/edge/page', + 'next.segment': '[param]', + 'next.span_name': 'resolve segment modules', 'next.span_type': - 'ResolveMetadata.generateMetadata', - 'next.page': '/app/[param]/rsc-fetch/edge/page', + 'NextNodeServer.getLayoutOrPageModule', }, + kind: 0, status: { code: 0 }, }, ], }, - ], - }, - ], - true - ) - }) - - it('should handle RSC with fetch in RSC mode', async () => { - await next.fetch(`/app/param/rsc-fetch?${NEXT_RSC_UNION_QUERY}`, { - ...env.fetchInit, - headers: { - ...env.fetchInit?.headers, - Rsc: '1', - }, - }) - - await expectTrace(getCollector(), [ - { - runtime: 'nodejs', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'RSC GET /app/[param]/rsc-fetch', - attributes: { - 'http.method': 'GET', - 'http.route': '/app/[param]/rsc-fetch', - 'http.status_code': 200, - 'http.target': `/app/param/rsc-fetch?${NEXT_RSC_UNION_QUERY}`, - 'next.route': '/app/[param]/rsc-fetch', - 'next.rsc': true, - 'next.span_name': 'RSC GET /app/[param]/rsc-fetch', - 'next.span_type': 'BaseServer.handleRequest', - }, - kind: 1, - status: { code: 0 }, - }, - ]) - }) - - it('should handle route handlers in app router', async () => { - await next.fetch('/api/app/param/data', env.fetchInit) - - await expectTrace(getCollector(), [ - { - name: 'GET /api/app/[param]/data', - attributes: { - 'http.method': 'GET', - 'http.route': '/api/app/[param]/data', - 'http.status_code': 200, - 'http.target': '/api/app/param/data', - 'next.route': '/api/app/[param]/data', - 'next.span_name': 'GET /api/app/[param]/data', - 'next.span_type': 'BaseServer.handleRequest', - }, - kind: 1, - status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: 'executing api route (app) /api/app/[param]/data', - attributes: { - 'next.route': '/api/app/[param]/data', - 'next.span_name': - 'executing api route (app) /api/app/[param]/data', - 'next.span_type': 'AppRouteRouteHandlers.runHandler', + { + name: 'generateMetadata /app/[param]/layout', + attributes: { + 'next.page': '/app/[param]/layout', + 'next.span_name': + 'generateMetadata /app/[param]/layout', + 'next.span_type': 'ResolveMetadata.generateMetadata', + }, + kind: 0, + status: { code: 0 }, }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/api/app/[param]/data', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', + { + name: 'generateMetadata /app/[param]/layout', + attributes: { + 'next.page': '/app/[param]/layout', + 'next.span_name': + 'generateMetadata /app/[param]/layout', + 'next.span_type': 'ResolveMetadata.generateMetadata', + }, + kind: 0, + status: { code: 0 }, }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'start response', - attributes: { - 'next.span_name': 'start response', - 'next.span_type': 'NextNodeServer.startResponse', + { + attributes: { + 'next.clientComponentLoadCount': isNextDev ? 10 : 8, + 'next.span_type': + 'NextNodeServer.clientComponentLoading', + }, + kind: 0, + name: 'NextNodeServer.clientComponentLoading', + status: { + code: 0, + }, }, - kind: 0, - status: { code: 0 }, - }, - ], - }, - ]) - }) - - it('should handle route handlers in app router on edge', async () => { - await next.fetch('/api/app/param/data/edge', env.fetchInit) - - await expectTrace( - getCollector(), - [ + { + name: 'start response', + attributes: { + 'next.span_name': 'start response', + 'next.span_type': 'NextNodeServer.startResponse', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, { - runtime: 'edge', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'executing api route (app) /api/app/[param]/data/edge', + name: 'resolve page components', attributes: { - 'next.route': '/api/app/[param]/data/edge', - 'next.span_name': - 'executing api route (app) /api/app/[param]/data/edge', - 'next.span_type': 'AppRouteRouteHandlers.runHandler', + 'next.route': '/app/[param]/rsc-fetch/error', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', }, kind: 0, status: { code: 0 }, }, ], - true - ) - }) - - it('should trace middleware', async () => { - await next.fetch('/behind-middleware', env.fetchInit) + }, + ]) + }) + }) - await expectTrace(getCollector(), [ - { - runtime: 'edge', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'middleware GET', - attributes: { - 'http.method': 'GET', - 'http.target': '/behind-middleware', - 'next.span_name': 'middleware GET', - 'next.span_type': 'Middleware.execute', - }, - status: { code: 0 }, - spans: [], - }, + describe('pages', () => { + it('should handle getServerSideProps', async () => { + await next.fetch('/pages/param/getServerSideProps', env.fetchInit) - { - runtime: 'nodejs', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'GET /behind-middleware', - attributes: { - 'http.method': 'GET', - 'http.route': '/behind-middleware', - 'http.status_code': 200, - 'http.target': '/behind-middleware', - 'next.route': '/behind-middleware', - 'next.span_name': 'GET /behind-middleware', - 'next.span_type': 'BaseServer.handleRequest', - }, + await expectTrace(getCollector(), [ + { + name: 'GET /pages/[param]/getServerSideProps', + attributes: { + 'http.method': 'GET', + 'http.route': '/pages/[param]/getServerSideProps', + 'http.status_code': 200, + 'http.target': '/pages/param/getServerSideProps', + 'next.route': '/pages/[param]/getServerSideProps', + 'next.span_name': 'GET /pages/[param]/getServerSideProps', + 'next.span_type': 'BaseServer.handleRequest', }, - ]) - }) - - it('should handle error in RSC', async () => { - await next.fetch( - '/app/param/rsc-fetch/error?status=error', - env.fetchInit - ) - - await expectTrace(getCollector(), [ - { - name: 'GET /app/[param]/rsc-fetch/error', - attributes: { - 'http.method': 'GET', - 'http.route': '/app/[param]/rsc-fetch/error', - 'http.status_code': 500, - 'http.target': '/app/param/rsc-fetch/error?status=error', - 'next.route': '/app/[param]/rsc-fetch/error', - 'next.rsc': false, - 'next.span_name': 'GET /app/[param]/rsc-fetch/error', - 'next.span_type': 'BaseServer.handleRequest', - 'error.type': '500', - }, - kind: 1, - status: { code: 2 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: 'render route (app) /app/[param]/rsc-fetch/error', - attributes: { - 'next.route': '/app/[param]/rsc-fetch/error', - 'next.span_name': - 'render route (app) /app/[param]/rsc-fetch/error', - 'next.span_type': 'AppRender.getBodyResult', - }, - kind: 0, - status: { code: 2 }, - spans: [ - { - name: 'build component tree', - attributes: { - 'next.span_name': 'build component tree', - 'next.span_type': - 'NextNodeServer.createComponentTree', - }, - kind: 0, - status: { code: 0 }, - spans: [ - { - name: 'resolve segment modules', - attributes: { - 'next.segment': '__PAGE__', - 'next.span_name': 'resolve segment modules', - 'next.span_type': - 'NextNodeServer.getLayoutOrPageModule', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'resolve segment modules', - attributes: { - 'next.segment': '[param]', - 'next.span_name': 'resolve segment modules', - 'next.span_type': - 'NextNodeServer.getLayoutOrPageModule', - }, - kind: 0, - status: { code: 0 }, - }, - ], - }, - { - name: 'generateMetadata /app/[param]/layout', - attributes: { - 'next.page': '/app/[param]/layout', - 'next.span_name': - 'generateMetadata /app/[param]/layout', - 'next.span_type': 'ResolveMetadata.generateMetadata', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'generateMetadata /app/[param]/layout', - attributes: { - 'next.page': '/app/[param]/layout', - 'next.span_name': - 'generateMetadata /app/[param]/layout', - 'next.span_type': 'ResolveMetadata.generateMetadata', - }, - kind: 0, - status: { code: 0 }, - }, - { - attributes: { - 'next.clientComponentLoadCount': isNextDev ? 10 : 8, - 'next.span_type': - 'NextNodeServer.clientComponentLoading', - }, - kind: 0, - name: 'NextNodeServer.clientComponentLoading', - status: { - code: 0, - }, - }, - { - name: 'start response', - attributes: { - 'next.span_name': 'start response', - 'next.span_type': 'NextNodeServer.startResponse', - }, - kind: 0, - status: { code: 0 }, - }, - ], - }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/app/[param]/rsc-fetch/error', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: 'getServerSideProps /pages/[param]/getServerSideProps', + attributes: { + 'next.route': '/pages/[param]/getServerSideProps', + 'next.span_name': + 'getServerSideProps /pages/[param]/getServerSideProps', + 'next.span_type': 'Render.getServerSideProps', }, - ], - }, - ]) - }) - }) - - describe('pages', () => { - it('should handle getServerSideProps', async () => { - await next.fetch('/pages/param/getServerSideProps', env.fetchInit) - - await expectTrace(getCollector(), [ - { - name: 'GET /pages/[param]/getServerSideProps', - attributes: { - 'http.method': 'GET', - 'http.route': '/pages/[param]/getServerSideProps', - 'http.status_code': 200, - 'http.target': '/pages/param/getServerSideProps', - 'next.route': '/pages/[param]/getServerSideProps', - 'next.span_name': 'GET /pages/[param]/getServerSideProps', - 'next.span_type': 'BaseServer.handleRequest', + kind: 0, + status: { code: 0 }, }, - kind: 1, - status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: 'getServerSideProps /pages/[param]/getServerSideProps', - attributes: { - 'next.route': '/pages/[param]/getServerSideProps', - 'next.span_name': - 'getServerSideProps /pages/[param]/getServerSideProps', - 'next.span_type': 'Render.getServerSideProps', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'render route (pages) /pages/[param]/getServerSideProps', - attributes: { - 'next.route': '/pages/[param]/getServerSideProps', - 'next.span_name': - 'render route (pages) /pages/[param]/getServerSideProps', - 'next.span_type': 'Render.renderDocument', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/pages/[param]/getServerSideProps', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, + { + name: 'render route (pages) /pages/[param]/getServerSideProps', + attributes: { + 'next.route': '/pages/[param]/getServerSideProps', + 'next.span_name': + 'render route (pages) /pages/[param]/getServerSideProps', + 'next.span_type': 'Render.renderDocument', }, - ], - }, - ]) - }) - - it("should handle getStaticProps when fallback: 'blocking'", async () => { - const v = env.span.rootParentId ? '2' : '' - await next.fetch(`/pages/param/getStaticProps${v}`, env.fetchInit) - - await expectTrace(getCollector(), [ - { - name: `GET /pages/[param]/getStaticProps${v}`, - attributes: { - 'http.method': 'GET', - 'http.route': `/pages/[param]/getStaticProps${v}`, - 'http.status_code': 200, - 'http.target': `/pages/param/getStaticProps${v}`, - 'next.route': `/pages/[param]/getStaticProps${v}`, - 'next.span_name': `GET /pages/[param]/getStaticProps${v}`, - 'next.span_type': 'BaseServer.handleRequest', + kind: 0, + status: { code: 0 }, }, - kind: 1, - status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: `getStaticProps /pages/[param]/getStaticProps${v}`, - attributes: { - 'next.route': `/pages/[param]/getStaticProps${v}`, - 'next.span_name': `getStaticProps /pages/[param]/getStaticProps${v}`, - 'next.span_type': 'Render.getStaticProps', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: `render route (pages) /pages/[param]/getStaticProps${v}`, - attributes: { - 'next.route': `/pages/[param]/getStaticProps${v}`, - 'next.span_name': `render route (pages) /pages/[param]/getStaticProps${v}`, - 'next.span_type': 'Render.renderDocument', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'resolve page components', - attributes: { - 'next.route': `/pages/[param]/getStaticProps${v}`, - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, - }, - ], - }, - ]) - }) - - it('should handle getServerSideProps on edge', async () => { - await next.fetch( - '/pages/param/edge/getServerSideProps', - env.fetchInit - ) - - await expectTrace( - getCollector(), - [ { - runtime: 'edge', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'GET /pages/[param]/edge/getServerSideProps', - kind: 1, + name: 'resolve page components', attributes: { - 'next.span_name': - 'GET /pages/[param]/edge/getServerSideProps', - 'next.span_type': 'BaseServer.handleRequest', - 'http.method': 'GET', - 'http.target': - '/pages/param/edge/getServerSideProps?param=param', - 'http.status_code': 200, - 'next.route': '/pages/[param]/edge/getServerSideProps', - 'http.route': '/pages/[param]/edge/getServerSideProps', + 'next.route': '/pages/[param]/getServerSideProps', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', }, + kind: 0, status: { code: 0 }, - spans: [ - { - name: 'getServerSideProps /pages/[param]/edge/getServerSideProps', - kind: 0, - attributes: { - 'next.span_name': - 'getServerSideProps /pages/[param]/edge/getServerSideProps', - 'next.span_type': 'Render.getServerSideProps', - 'next.route': '/pages/[param]/edge/getServerSideProps', - }, - status: { code: 0 }, - }, - { - name: 'render route (pages) /pages/[param]/edge/getServerSideProps', - kind: 0, - attributes: { - 'next.span_name': - 'render route (pages) /pages/[param]/edge/getServerSideProps', - 'next.span_type': 'Render.renderDocument', - 'next.route': '/pages/[param]/edge/getServerSideProps', - }, - status: { code: 0 }, - }, - ], }, ], - true - ) - }) + }, + ]) + }) - it('should handle getServerSideProps exceptions', async () => { - await next.fetch( - '/pages/param/getServerSidePropsError', - env.fetchInit - ) + it("should handle getStaticProps when fallback: 'blocking'", async () => { + const v = env.span.rootParentId ? '2' : '' + await next.fetch(`/pages/param/getStaticProps${v}`, env.fetchInit) - await expectTrace(getCollector(), [ - { - name: 'GET /pages/[param]/getServerSidePropsError', - attributes: { - 'http.method': 'GET', - 'http.route': '/pages/[param]/getServerSidePropsError', - 'http.status_code': 500, - 'http.target': '/pages/param/getServerSidePropsError', - 'next.route': '/pages/[param]/getServerSidePropsError', - 'next.span_name': - 'GET /pages/[param]/getServerSidePropsError', - 'next.span_type': 'BaseServer.handleRequest', - 'error.type': '500', - }, - kind: 1, - status: { code: 2 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: 'getServerSideProps /pages/[param]/getServerSidePropsError', - attributes: { - 'next.route': '/pages/[param]/getServerSidePropsError', - 'next.span_name': - 'getServerSideProps /pages/[param]/getServerSidePropsError', - 'next.span_type': 'Render.getServerSideProps', - 'error.type': 'Error', - }, - kind: 0, - status: { - code: 2, - message: 'ServerSideProps error', - }, - events: [ - { - name: 'exception', - attributes: { - 'exception.type': 'Error', - 'exception.message': 'ServerSideProps error', - }, - }, - ], - }, - { - name: 'render route (pages) /_error', - attributes: { - 'next.route': '/_error', - 'next.span_name': 'render route (pages) /_error', - 'next.span_type': 'Render.renderDocument', - }, - kind: 0, - status: { code: 0 }, + await expectTrace(getCollector(), [ + { + name: `GET /pages/[param]/getStaticProps${v}`, + attributes: { + 'http.method': 'GET', + 'http.route': `/pages/[param]/getStaticProps${v}`, + 'http.status_code': 200, + 'http.target': `/pages/param/getStaticProps${v}`, + 'next.route': `/pages/[param]/getStaticProps${v}`, + 'next.span_name': `GET /pages/[param]/getStaticProps${v}`, + 'next.span_type': 'BaseServer.handleRequest', + }, + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: `getStaticProps /pages/[param]/getStaticProps${v}`, + attributes: { + 'next.route': `/pages/[param]/getStaticProps${v}`, + 'next.span_name': `getStaticProps /pages/[param]/getStaticProps${v}`, + 'next.span_type': 'Render.getStaticProps', }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/_error', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, + kind: 0, + status: { code: 0 }, + }, + { + name: `render route (pages) /pages/[param]/getStaticProps${v}`, + attributes: { + 'next.route': `/pages/[param]/getStaticProps${v}`, + 'next.span_name': `render route (pages) /pages/[param]/getStaticProps${v}`, + 'next.span_type': 'Render.renderDocument', }, - ...(isNextDev - ? [] - : [ - { - name: 'resolve page components', - attributes: { - 'next.route': '/500', - 'next.span_name': 'resolve page components', - 'next.span_type': - 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, - }, - { - name: 'resolve page components', - attributes: { - 'next.route': '/500', - 'next.span_name': 'resolve page components', - 'next.span_type': - 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, - }, - ]), - { - name: 'resolve page components', - attributes: { - 'next.route': '/pages/[param]/getServerSidePropsError', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, - status: { code: 0 }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve page components', + attributes: { + 'next.route': `/pages/[param]/getStaticProps${v}`, + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', }, - ], - }, - ]) - }) + kind: 0, + status: { code: 0 }, + }, + ], + }, + ]) + }) - it('should handle getServerSideProps returning notFound', async () => { - await next.fetch( - '/pages/param/getServerSidePropsNotFound', - env.fetchInit - ) + it('should handle getServerSideProps on edge', async () => { + await next.fetch( + '/pages/param/edge/getServerSideProps', + env.fetchInit + ) - await expectTrace(getCollector(), [ + await expectTrace( + getCollector(), + [ { - name: 'GET /pages/[param]/getServerSidePropsNotFound', + runtime: 'edge', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'GET /pages/[param]/edge/getServerSideProps', + kind: 1, attributes: { - 'http.method': 'GET', - 'http.route': '/pages/[param]/getServerSidePropsNotFound', - 'http.status_code': 404, - 'http.target': '/pages/param/getServerSidePropsNotFound', - 'next.route': '/pages/[param]/getServerSidePropsNotFound', 'next.span_name': - 'GET /pages/[param]/getServerSidePropsNotFound', + 'GET /pages/[param]/edge/getServerSideProps', 'next.span_type': 'BaseServer.handleRequest', + 'http.method': 'GET', + 'http.target': + '/pages/param/edge/getServerSideProps?param=param', + 'http.status_code': 200, + 'next.route': '/pages/[param]/edge/getServerSideProps', + 'http.route': '/pages/[param]/edge/getServerSideProps', }, - kind: 1, status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, spans: [ { - name: 'getServerSideProps /pages/[param]/getServerSidePropsNotFound', + name: 'getServerSideProps /pages/[param]/edge/getServerSideProps', + kind: 0, attributes: { - 'next.route': '/pages/[param]/getServerSidePropsNotFound', 'next.span_name': - 'getServerSideProps /pages/[param]/getServerSidePropsNotFound', + 'getServerSideProps /pages/[param]/edge/getServerSideProps', 'next.span_type': 'Render.getServerSideProps', + 'next.route': '/pages/[param]/edge/getServerSideProps', }, - kind: 0, - status: { - code: 0, - }, - }, - ...(isNextDev - ? [ - { - name: 'render route (app) /_not-found', - attributes: { - 'next.route': '/_not-found', - 'next.span_name': 'render route (app) /_not-found', - 'next.span_type': 'AppRender.getBodyResult', - }, - kind: 0, - status: { code: 0 }, - }, - ] - : []), - { - name: 'resolve page components', - attributes: { - 'next.route': '/_not-found', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', - }, - kind: 0, status: { code: 0 }, }, { - name: 'resolve page components', + name: 'render route (pages) /pages/[param]/edge/getServerSideProps', + kind: 0, attributes: { - 'next.route': '/pages/[param]/getServerSidePropsNotFound', - 'next.span_name': 'resolve page components', - 'next.span_type': 'NextNodeServer.findPageComponents', + 'next.span_name': + 'render route (pages) /pages/[param]/edge/getServerSideProps', + 'next.span_type': 'Render.renderDocument', + 'next.route': '/pages/[param]/edge/getServerSideProps', }, - kind: 0, status: { code: 0 }, }, ], }, - ]) - }) + ], + true + ) + }) - it('should handle api routes in pages', async () => { - await next.fetch('/api/pages/param/basic', env.fetchInit) + it('should handle getServerSideProps exceptions', async () => { + await next.fetch( + '/pages/param/getServerSidePropsError', + env.fetchInit + ) - await expectTrace(getCollector(), [ - { - name: 'GET /api/pages/[param]/basic', - attributes: { - 'http.method': 'GET', - 'http.route': '/api/pages/[param]/basic', - 'http.status_code': 200, - 'http.target': '/api/pages/param/basic', - 'next.route': '/api/pages/[param]/basic', - 'next.span_name': 'GET /api/pages/[param]/basic', - 'next.span_type': 'BaseServer.handleRequest', - }, - kind: 1, - status: { code: 0 }, - traceId: env.span.traceId, - parentId: env.span.rootParentId, - spans: [ - { - name: 'executing api route (pages) /api/pages/[param]/basic', - attributes: { - 'next.span_name': - 'executing api route (pages) /api/pages/[param]/basic', - 'next.span_type': 'Node.runHandler', + await expectTrace(getCollector(), [ + { + name: 'GET /pages/[param]/getServerSidePropsError', + attributes: { + 'http.method': 'GET', + 'http.route': '/pages/[param]/getServerSidePropsError', + 'http.status_code': 500, + 'http.target': '/pages/param/getServerSidePropsError', + 'next.route': '/pages/[param]/getServerSidePropsError', + 'next.span_name': 'GET /pages/[param]/getServerSidePropsError', + 'next.span_type': 'BaseServer.handleRequest', + 'error.type': '500', + }, + kind: 1, + status: { code: 2 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: 'getServerSideProps /pages/[param]/getServerSidePropsError', + attributes: { + 'next.route': '/pages/[param]/getServerSidePropsError', + 'next.span_name': + 'getServerSideProps /pages/[param]/getServerSidePropsError', + 'next.span_type': 'Render.getServerSideProps', + 'error.type': 'Error', + }, + kind: 0, + status: { + code: 2, + message: 'ServerSideProps error', + }, + events: [ + { + name: 'exception', + attributes: { + 'exception.type': 'Error', + 'exception.message': 'ServerSideProps error', + }, }, - kind: 0, - status: { code: 0 }, + ], + }, + { + name: 'render route (pages) /_error', + attributes: { + 'next.route': '/_error', + 'next.span_name': 'render route (pages) /_error', + 'next.span_type': 'Render.renderDocument', }, - ], + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve page components', + attributes: { + 'next.route': '/_error', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + ...(isNextDev + ? [] + : [ + { + name: 'resolve page components', + attributes: { + 'next.route': '/500', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve page components', + attributes: { + 'next.route': '/500', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + ]), + { + name: 'resolve page components', + attributes: { + 'next.route': '/pages/[param]/getServerSidePropsError', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + ]) + }) + + it('should handle getServerSideProps returning notFound', async () => { + await next.fetch( + '/pages/param/getServerSidePropsNotFound', + env.fetchInit + ) + + await expectTrace(getCollector(), [ + { + name: 'GET /pages/[param]/getServerSidePropsNotFound', + attributes: { + 'http.method': 'GET', + 'http.route': '/pages/[param]/getServerSidePropsNotFound', + 'http.status_code': 404, + 'http.target': '/pages/param/getServerSidePropsNotFound', + 'next.route': '/pages/[param]/getServerSidePropsNotFound', + 'next.span_name': + 'GET /pages/[param]/getServerSidePropsNotFound', + 'next.span_type': 'BaseServer.handleRequest', }, - ]) - }) + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ + { + name: 'getServerSideProps /pages/[param]/getServerSidePropsNotFound', + attributes: { + 'next.route': '/pages/[param]/getServerSidePropsNotFound', + 'next.span_name': + 'getServerSideProps /pages/[param]/getServerSidePropsNotFound', + 'next.span_type': 'Render.getServerSideProps', + }, + kind: 0, + status: { + code: 0, + }, + }, + ...(isNextDev + ? [ + { + name: 'render route (app) /_not-found', + attributes: { + 'next.route': '/_not-found', + 'next.span_name': 'render route (app) /_not-found', + 'next.span_type': 'AppRender.getBodyResult', + }, + kind: 0, + status: { code: 0 }, + }, + ] + : []), + { + name: 'resolve page components', + attributes: { + 'next.route': '/_not-found', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + { + name: 'resolve page components', + attributes: { + 'next.route': '/pages/[param]/getServerSidePropsNotFound', + 'next.span_name': 'resolve page components', + 'next.span_type': 'NextNodeServer.findPageComponents', + }, + kind: 0, + status: { code: 0 }, + }, + ], + }, + ]) + }) - it('should handle api routes in pages on edge', async () => { - await next.fetch('/api/pages/param/edge', env.fetchInit) + it('should handle api routes in pages', async () => { + await next.fetch('/api/pages/param/basic', env.fetchInit) - await expectTrace( - getCollector(), - [ + await expectTrace(getCollector(), [ + { + name: 'GET /api/pages/[param]/basic', + attributes: { + 'http.method': 'GET', + 'http.route': '/api/pages/[param]/basic', + 'http.status_code': 200, + 'http.target': '/api/pages/param/basic', + 'next.route': '/api/pages/[param]/basic', + 'next.span_name': 'GET /api/pages/[param]/basic', + 'next.span_type': 'BaseServer.handleRequest', + }, + kind: 1, + status: { code: 0 }, + traceId: env.span.traceId, + parentId: env.span.rootParentId, + spans: [ { - runtime: 'edge', - traceId: env.span.traceId, - parentId: env.span.rootParentId, - name: 'executing api route (pages) /api/pages/[param]/edge', + name: 'executing api route (pages) /api/pages/[param]/basic', attributes: { 'next.span_name': - 'executing api route (pages) /api/pages/[param]/edge', + 'executing api route (pages) /api/pages/[param]/basic', 'next.span_type': 'Node.runHandler', }, kind: 0, status: { code: 0 }, }, ], - true - ) - }) + }, + ]) }) - } - ) + + it('should handle api routes in pages on edge', async () => { + await next.fetch('/api/pages/param/edge', env.fetchInit) + + await expectTrace( + getCollector(), + [ + { + runtime: 'edge', + traceId: env.span.traceId, + parentId: env.span.rootParentId, + name: 'executing api route (pages) /api/pages/[param]/edge', + attributes: { + 'next.span_name': + 'executing api route (pages) /api/pages/[param]/edge', + 'next.span_type': 'Node.runHandler', + }, + kind: 0, + status: { code: 0 }, + }, + ], + true + ) + }) + }) + }) } }) @@ -1065,57 +1057,56 @@ describe('opentelemetry with disabled fetch tracing', () => { await collector.shutdown() await new Promise((r) => setTimeout(r, 1000)) }) - ;(process.env.__NEXT_EXPERIMENTAL_PPR ? describe.skip : describe)( - 'root context', - () => { - describe('app router with disabled fetch', () => { - it('should handle RSC with disabled fetch', async () => { - await next.fetch('/app/param/rsc-fetch') + ;(process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS + ? describe.skip + : describe)('root context', () => { + describe('app router with disabled fetch', () => { + it('should handle RSC with disabled fetch', async () => { + await next.fetch('/app/param/rsc-fetch') - await expectTrace(getCollector(), [ - { - name: 'GET /app/[param]/rsc-fetch', - traceId: '[trace-id]', - parentId: undefined, - spans: [ - { - name: 'render route (app) /app/[param]/rsc-fetch', - spans: [ - { - name: 'build component tree', - spans: [ - { - name: 'resolve segment modules', - }, - { - name: 'resolve segment modules', - }, - ], - }, - { - name: 'generateMetadata /app/[param]/layout', - }, - { - name: 'generateMetadata /app/[param]/rsc-fetch/page', - }, - { - name: 'NextNodeServer.clientComponentLoading', - }, - { - name: 'start response', - }, - ], - }, - { - name: 'resolve page components', - }, - ], - }, - ]) - }) + await expectTrace(getCollector(), [ + { + name: 'GET /app/[param]/rsc-fetch', + traceId: '[trace-id]', + parentId: undefined, + spans: [ + { + name: 'render route (app) /app/[param]/rsc-fetch', + spans: [ + { + name: 'build component tree', + spans: [ + { + name: 'resolve segment modules', + }, + { + name: 'resolve segment modules', + }, + ], + }, + { + name: 'generateMetadata /app/[param]/layout', + }, + { + name: 'generateMetadata /app/[param]/rsc-fetch/page', + }, + { + name: 'NextNodeServer.clientComponentLoading', + }, + { + name: 'start response', + }, + ], + }, + { + name: 'resolve page components', + }, + ], + }, + ]) }) - } - ) + }) + }) }) type HierSavedSpan = SavedSpan & { spans?: HierSavedSpan[] } diff --git a/test/integration/config-experimental-warning/test/index.test.js b/test/integration/config-experimental-warning/test/index.test.js index fb7e3f2ee7e68..7e0b222098468 100644 --- a/test/integration/config-experimental-warning/test/index.test.js +++ b/test/integration/config-experimental-warning/test/index.test.js @@ -143,7 +143,8 @@ describe('Config Experimental Warning', () => { expect(stdout).toMatch(' · cpus: 2') }) - it('should show the configured value for string features', async () => { + // TODO: the incremental option has been removed, update to another string feature + it.skip('should show the configured value for string features', async () => { configFile.write(` module.exports = { experimental: { diff --git a/test/lib/next-modes/base.ts b/test/lib/next-modes/base.ts index a675b495a9aff..6e0056eaff440 100644 --- a/test/lib/next-modes/base.ts +++ b/test/lib/next-modes/base.ts @@ -403,9 +403,6 @@ export class NextInstance { } // alias experimental feature flags for deployment compatibility - if (process.env.NEXT_PRIVATE_EXPERIMENTAL_PPR) { - process.env.__NEXT_EXPERIMENTAL_PPR = process.env.NEXT_PRIVATE_EXPERIMENTAL_PPR - } if (process.env.NEXT_PRIVATE_EXPERIMENTAL_CACHE_COMPONENTS) { process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS = process.env.NEXT_PRIVATE_EXPERIMENTAL_CACHE_COMPONENTS } diff --git a/test/lib/next-modes/next-deploy.ts b/test/lib/next-modes/next-deploy.ts index 374bf46cbdcf7..4a4b6a5f14957 100644 --- a/test/lib/next-modes/next-deploy.ts +++ b/test/lib/next-modes/next-deploy.ts @@ -99,11 +99,6 @@ export class NextDeployInstance extends NextInstance { ) // Add experimental feature flags - if (process.env.__NEXT_EXPERIMENTAL_PPR) { - additionalEnv.push( - `NEXT_PRIVATE_EXPERIMENTAL_PPR=${process.env.__NEXT_EXPERIMENTAL_PPR}` - ) - } if (process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS) { additionalEnv.push( diff --git a/test/production/adapter-config/adapter-config-cache-components.test.ts b/test/production/adapter-config/adapter-config-cache-components.test.ts new file mode 100644 index 0000000000000..34192952de9f8 --- /dev/null +++ b/test/production/adapter-config/adapter-config-cache-components.test.ts @@ -0,0 +1,6 @@ +process.env.TEST_CACHE_COMPONENTS = '1' + +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('adapter-config-cache-components', () => { + require('./adapter-config.test') +}) diff --git a/test/production/adapter-config/adapter-config-ppr.test.ts b/test/production/adapter-config/adapter-config-ppr.test.ts deleted file mode 100644 index 80272d1fbc909..0000000000000 --- a/test/production/adapter-config/adapter-config-ppr.test.ts +++ /dev/null @@ -1,2 +0,0 @@ -process.env.TEST_PPR = '1' -require('./adapter-config.test') diff --git a/test/production/adapter-config/next.config.mjs b/test/production/adapter-config/next.config.mjs index c5a54b98f7ac3..8f1d8dee84a43 100644 --- a/test/production/adapter-config/next.config.mjs +++ b/test/production/adapter-config/next.config.mjs @@ -5,7 +5,7 @@ const require = Module.createRequire(import.meta.url) const nextConfig = { experimental: { adapterPath: require.resolve('./my-adapter.mjs'), - ppr: Boolean(process.env.TEST_PPR), + cacheComponents: process.env.TEST_CACHE_COMPONENTS === '1', }, output: process.env.TEST_EXPORT ? 'export' : undefined, } diff --git a/test/production/app-dir/build-output-prerender/build-output-prerender.test.ts b/test/production/app-dir/build-output-prerender/build-output-prerender.test.ts index b044721605e92..eb081b1b8dcba 100644 --- a/test/production/app-dir/build-output-prerender/build-output-prerender.test.ts +++ b/test/production/app-dir/build-output-prerender/build-output-prerender.test.ts @@ -26,9 +26,8 @@ describe('build-output-prerender', () => { "▲ Next.js x.y.z (Turbopack) - Experiments (use with caution): ✓ cacheComponents - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)" `) @@ -37,9 +36,8 @@ describe('build-output-prerender', () => { "▲ Next.js x.y.z (webpack) - Experiments (use with caution): ✓ cacheComponents - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)" `) @@ -73,8 +71,7 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`)" + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`)" `) } else if (isRspack) { expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(` @@ -82,8 +79,7 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`)" + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`)" `) } else { expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(` @@ -91,8 +87,7 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`)" + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`)" `) } } @@ -147,9 +142,8 @@ describe('build-output-prerender', () => { ▲ Next.js x.y.z (Turbopack) - Experiments (use with caution): ✓ cacheComponents - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`) @@ -162,9 +156,8 @@ describe('build-output-prerender', () => { ▲ Next.js x.y.z (webpack) - Experiments (use with caution): ✓ cacheComponents - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`) @@ -210,9 +203,8 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`) + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`) ✓ serverSourceMaps (enabled by \`--debug-prerender\`) ⨯ turbopackMinify (disabled by \`--debug-prerender\`)" `) @@ -223,9 +215,8 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`) + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`) ⨯ serverMinification (disabled by \`--debug-prerender\`) ✓ serverSourceMaps (enabled by \`--debug-prerender\`)" `) @@ -236,9 +227,8 @@ describe('build-output-prerender', () => { - Experiments (use with caution): ✓ cacheComponents ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`experimental.cacheComponents\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) - ✓ rdcForNavigations (enabled by \`experimental.ppr\`) + ✓ rdcForNavigations (enabled by \`experimental.cacheComponents\`) ⨯ serverMinification (disabled by \`--debug-prerender\`) ✓ serverSourceMaps (enabled by \`--debug-prerender\`)" `) @@ -293,9 +283,8 @@ describe('build-output-prerender', () => { "▲ Next.js x.y.z (Turbopack) - Experiments (use with caution): ✓ cacheComponents (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)" `) @@ -304,9 +293,8 @@ describe('build-output-prerender', () => { "▲ Next.js x.y.z (webpack) - Experiments (use with caution): ✓ cacheComponents (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`experimental.cacheComponents\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)" `) @@ -364,9 +352,8 @@ describe('build-output-prerender', () => { ▲ Next.js x.y.z (Turbopack) - Experiments (use with caution): ✓ cacheComponents (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`) @@ -379,9 +366,8 @@ describe('build-output-prerender', () => { ▲ Next.js x.y.z (webpack) - Experiments (use with caution): ✓ cacheComponents (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) - ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_PPR\`) + ✓ clientParamParsing (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ enablePrerenderSourceMaps (enabled by \`--debug-prerender\`) - ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`) ✓ rdcForNavigations (enabled by \`__NEXT_EXPERIMENTAL_CACHE_COMPONENTS\`) ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`) diff --git a/test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts b/test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts index 5524a14c072ee..ece5aefffe43f 100644 --- a/test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts +++ b/test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts @@ -2,7 +2,8 @@ import { nextTestSetup } from 'e2e-utils' import path from 'path' describe('build-output-tree-view', () => { - describe('with mixed static and dynamic pages and app router routes', () => { + // TODO(NAR-423): Migrate to Cache Components. + describe.skip('with mixed static and dynamic pages and app router routes', () => { const { next } = nextTestSetup({ files: path.join(__dirname, 'fixtures/mixed'), skipStart: true, diff --git a/test/production/app-dir/build-output-tree-view/fixtures/mixed/next.config.js b/test/production/app-dir/build-output-tree-view/fixtures/mixed/next.config.js index 88b3464206ba2..735e19c3f3d57 100644 --- a/test/production/app-dir/build-output-tree-view/fixtures/mixed/next.config.js +++ b/test/production/app-dir/build-output-tree-view/fixtures/mixed/next.config.js @@ -4,7 +4,7 @@ const nextConfig = { experimental: { useCache: true, - ppr: true, + cacheComponents: true, }, } diff --git a/test/production/app-dir/empty-generate-static-params/empty-generate-static-params.test.ts b/test/production/app-dir/empty-generate-static-params/empty-generate-static-params.test.ts index 09920a5229a06..7e7b03b23ddc3 100644 --- a/test/production/app-dir/empty-generate-static-params/empty-generate-static-params.test.ts +++ b/test/production/app-dir/empty-generate-static-params/empty-generate-static-params.test.ts @@ -10,7 +10,8 @@ describe('empty-generate-static-params', () => { if (skipped) return it('should mark the page with empty generateStaticParams as SSG in build output', async () => { - const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + const isPPREnabled = + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' expect(next.cliOutput).toContain(`${isPPREnabled ? '◐' : '●'} /[slug]`) }) @@ -19,7 +20,8 @@ describe('empty-generate-static-params', () => { expect(firstResponse.status).toBe(200) // With PPR enabled, the initial request doesn't send back a cache header - const isPPREnabled = process.env.__NEXT_EXPERIMENTAL_PPR === 'true' + const isPPREnabled = + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS === 'true' expect(firstResponse.headers.get('x-nextjs-cache')).toBe( isPPREnabled ? null : 'MISS' diff --git a/test/production/app-dir/metadata-streaming-config/metadata-streaming-config-customized.test.ts b/test/production/app-dir/metadata-streaming-config/metadata-streaming-config-customized.test.ts index 826a95b122eb2..c040b585ea5ab 100644 --- a/test/production/app-dir/metadata-streaming-config/metadata-streaming-config-customized.test.ts +++ b/test/production/app-dir/metadata-streaming-config/metadata-streaming-config-customized.test.ts @@ -1,6 +1,7 @@ import { nextTestSetup } from 'e2e-utils' -describe('app-dir - metadata-streaming-config-customized', () => { +// TODO: the incremental option has been removed, update to use cacheComponents +describe.skip('app-dir - metadata-streaming-config-customized', () => { const { next } = nextTestSetup({ files: __dirname, skipDeployment: true, diff --git a/test/production/app-dir/metadata-streaming-config/metadata-streaming-config.test.ts b/test/production/app-dir/metadata-streaming-config/metadata-streaming-config.test.ts index 1601c422b1ee1..176e9d8e22f3c 100644 --- a/test/production/app-dir/metadata-streaming-config/metadata-streaming-config.test.ts +++ b/test/production/app-dir/metadata-streaming-config/metadata-streaming-config.test.ts @@ -1,6 +1,7 @@ import { nextTestSetup } from 'e2e-utils' -describe('app-dir - metadata-streaming-config', () => { +// TODO: the incremental option has been removed, update to use cacheComponents +describe.skip('app-dir - metadata-streaming-config', () => { const { next } = nextTestSetup({ files: __dirname, }) diff --git a/test/production/app-dir/parallel-routes-static/index.test.ts b/test/production/app-dir/parallel-routes-static/index.test.ts index c745ce3353ef2..68ea77d599df3 100644 --- a/test/production/app-dir/parallel-routes-static/index.test.ts +++ b/test/production/app-dir/parallel-routes-static/index.test.ts @@ -6,7 +6,7 @@ describe('app-dir parallel-routes-static', () => { }) it('should static generate parallel routes', async () => { - const rscExtension = process.env.__NEXT_EXPERIMENTAL_PPR + const rscExtension = process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS ? '.prefetch.rsc' : '.rsc' expect(await next.hasFile('.next/server/app/nested/foo.html')).toBe(true) diff --git a/test/production/app-dir/ppr-use-server-inserted-html/next.config.js b/test/production/app-dir/ppr-use-server-inserted-html/next.config.js index 016ac8833b57f..30a826fdacc56 100644 --- a/test/production/app-dir/ppr-use-server-inserted-html/next.config.js +++ b/test/production/app-dir/ppr-use-server-inserted-html/next.config.js @@ -3,7 +3,7 @@ */ const nextConfig = { experimental: { - ppr: true, + cacheComponents: true, }, } diff --git a/test/production/app-dir/subresource-integrity/subresource-integrity.test.ts b/test/production/app-dir/subresource-integrity/subresource-integrity.test.ts index 9d8e69723625b..e2d11397c4755 100644 --- a/test/production/app-dir/subresource-integrity/subresource-integrity.test.ts +++ b/test/production/app-dir/subresource-integrity/subresource-integrity.test.ts @@ -226,7 +226,10 @@ import cheerio from 'cheerio' `script-src 'nonce-">"'` ) - if (runtime === 'node' && process.env.__NEXT_EXPERIMENTAL_PPR) { + if ( + runtime === 'node' && + process.env.__NEXT_EXPERIMENTAL_CACHE_COMPONENTS + ) { expect(res.status).toBe(200) } else { expect(res.status).toBe(500) diff --git a/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts index 20425f2585ef7..b17724be7c481 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts @@ -13,7 +13,8 @@ import { } from 'next-test-utils' import { ChildProcess } from 'node:child_process' -describe('required server files app router', () => { +// TODO(NAR-423): Migrate to Cache Components. +describe.skip('required server files app router', () => { let next: NextInstance let server: ChildProcess let appPort: number | string @@ -55,7 +56,7 @@ describe('required server files app router', () => { nextConfig: { cacheHandler: './cache-handler.js', experimental: { - ppr: true, + cacheComponents: true, clientSegmentCache: true, clientParamParsing: true, },