Repository: vercel/next.js
Pull request: [cache components] show when cache components is enabled in the CLI

Since it won't show in the experimental list anymore, this shows if Cache Components is enabled in the CLI (for build).

Changed files:
filename: packages/next/src/build/index.ts
patch: @@ -1115,18 +1115,20 @@ export default async function build(
       )
 
       // Always log next version first then start rest jobs
-      const { envInfo, experimentalFeatures } = await getStartServerInfo({
-        dir,
-        dev: false,
-        debugPrerender,
-      })
+      const { envInfo, experimentalFeatures, cacheComponents } =
+        await getStartServerInfo({
+          dir,
+          dev: false,
+          debugPrerender,
+        })
 
       logStartInfo({
         networkUrl: null,
         appUrl: null,
         envInfo,
         experimentalFeatures,
         logBundler: true,
+        cacheComponents,
       })
 
       const typeCheckingOptions: Parameters<typeof startTypeChecking>[0] = {

filename: packages/next/src/server/config.ts
patch: @@ -1791,15 +1791,6 @@ function enforceExperimentalFeatures(
       (isDefaultConfig && !config.cacheComponents))
   ) {
     config.cacheComponents = true
-
-    if (configuredExperimentalFeatures) {
-      addConfiguredExperimentalFeature(
-        configuredExperimentalFeatures,
-        'cacheComponents',
-        true,
-        'enabled by `__NEXT_CACHE_COMPONENTS`'
-      )
-    }
   }
 
   // TODO: Remove this once using the debug channel is the default.

filename: packages/next/src/server/lib/app-info-log.ts
patch: @@ -14,28 +14,40 @@ export function logStartInfo({
   envInfo,
   experimentalFeatures,
   logBundler,
+  cacheComponents,
 }: {
   networkUrl: string | null
   appUrl: string | null
   envInfo?: string[]
   experimentalFeatures?: ConfiguredExperimentalFeature[]
   logBundler: boolean
+  cacheComponents?: boolean
 }) {
-  let bundlerSuffix = ''
+  let versionSuffix = ''
+  const parts = []
+
   if (logBundler) {
     if (process.env.TURBOPACK) {
-      bundlerSuffix = ' (Turbopack)'
+      parts.push('Turbopack')
     } else if (process.env.NEXT_RSPACK) {
-      bundlerSuffix = ' (Rspack)'
+      parts.push('Rspack')
     } else {
-      bundlerSuffix = ' (webpack)'
+      parts.push('webpack')
     }
   }
 
+  if (cacheComponents) {
+    parts.push('Cache Components')
+  }
+
+  if (parts.length > 0) {
+    versionSuffix = ` (${parts.join(', ')})`
+  }
+
   Log.bootstrap(
     `${bold(
       purple(`${Log.prefixes.ready} Next.js ${process.env.__NEXT_VERSION}`)
-    )}${bundlerSuffix}`
+    )}${versionSuffix}`
   )
   if (appUrl) {
     Log.bootstrap(`- Local:        ${appUrl}`)
@@ -91,9 +103,11 @@ export async function getStartServerInfo({
 }): Promise<{
   envInfo?: string[]
   experimentalFeatures?: ConfiguredExperimentalFeature[]
+  cacheComponents?: boolean
 }> {
   let experimentalFeatures: ConfiguredExperimentalFeature[] = []
-  await loadConfig(
+  let cacheComponents = false
+  const config = await loadConfig(
     dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_BUILD,
     dir,
     {
@@ -107,6 +121,8 @@ export async function getStartServerInfo({
     }
   )
 
+  cacheComponents = !!config.cacheComponents
+
   // we need to reset env if we are going to create
   // the worker process with the esm loader so that the
   // initial env state is correct
@@ -119,5 +135,6 @@ export async function getStartServerInfo({
   return {
     envInfo,
     experimentalFeatures,
+    cacheComponents,
   }
 }

filename: test/production/app-dir/build-output-prerender/build-output-prerender.test.ts
patch: @@ -18,59 +18,48 @@ describe('build-output-prerender', () => {
 
       beforeAll(() => next.build())
 
-      // TODO: Re-enable this test once we move the cache components flag
-      it.skip('prints only the user-selected experimental flags (and the ones enabled via env variable)', async () => {
+      it('prints only the user-selected experimental flags (and the ones enabled via env variable)', async () => {
         if (cacheComponentsEnabled) {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (Turbopack)
+             "▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)"
             `)
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (webpack)
+             "▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)"
             `)
           }
         } else if (pprEnabled) {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (Turbopack)
+             "▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_PPR\`)"
             `)
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (webpack)
+             "▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_PPR\`)"
             `)
           }
         } else {
           if (isTurbopack) {
-            expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (Turbopack)
-                - Experiments (use with caution):
-                  ✓ cacheComponents"
-            `)
+            expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(
+              `"▲ Next.js x.y.z (Turbopack, Cache Components)"`
+            )
           } else if (isRspack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (Rspack)
-                - Experiments (use with caution):
-                  ✓ cacheComponents"
+             "▲ Next.js x.y.z (Rspack, Cache Components)"
             `)
           } else {
-            expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (webpack)
-                - Experiments (use with caution):
-                  ✓ cacheComponents"
-            `)
+            expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(
+              `"▲ Next.js x.y.z (webpack, Cache Components)"`
+            )
           }
         }
       })
@@ -116,15 +105,13 @@ describe('build-output-prerender', () => {
 
       beforeAll(() => next.build())
 
-      // TODO: Re-enable this test once we move the cache components flag
-      it.skip('prints a warning and the customized experimental flags', async () => {
+      it('prints a warning and the customized experimental flags', async () => {
         if (cacheComponentsEnabled) {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (Turbopack)
+                ▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)
@@ -133,9 +120,8 @@ describe('build-output-prerender', () => {
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (webpack)
+                ▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)
                   ⨯ serverMinification (disabled by \`--debug-prerender\`)
@@ -146,9 +132,8 @@ describe('build-output-prerender', () => {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (Turbopack)
+                ▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_PPR\`)
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)
@@ -157,9 +142,8 @@ describe('build-output-prerender', () => {
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (webpack)
+                ▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ✓ ppr (enabled by \`__NEXT_EXPERIMENTAL_PPR\`)
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ⨯ serverMinification (disabled by \`--debug-prerender\`)
@@ -170,29 +154,26 @@ describe('build-output-prerender', () => {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (Turbopack)
+                ▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)
                   ⨯ turbopackMinify (disabled by \`--debug-prerender\`)"
             `)
           } else if (isRspack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (Rspack)
+                ▲ Next.js x.y.z (Rspack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ⨯ serverMinification (disabled by \`--debug-prerender\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)"
             `)
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (webpack)
+                ▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ⨯ serverMinification (disabled by \`--debug-prerender\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)"
@@ -241,21 +222,18 @@ describe('build-output-prerender', () => {
 
       beforeAll(() => next.build())
 
-      // TODO: Re-enable this test once we move the cache components flag
-      it.skip('prints no experimental flags (unless enabled via env variable)', async () => {
+      it('prints no experimental flags (unless enabled via env variable)', async () => {
         if (cacheComponentsEnabled) {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (Turbopack)
+             "▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents (enabled by \`__NEXT_CACHE_COMPONENTS\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)"
             `)
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
-             "▲ Next.js x.y.z (webpack)
+             "▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents (enabled by \`__NEXT_CACHE_COMPONENTS\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)"
             `)
           }
@@ -300,15 +278,13 @@ describe('build-output-prerender', () => {
 
       beforeAll(() => next.build())
 
-      // TODO: Re-enable this test once we move the cache components flag
-      it.skip('prints a warning and the customized experimental flags', async () => {
+      it('prints a warning and the customized experimental flags', async () => {
         if (cacheComponentsEnabled) {
           if (isTurbopack) {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (Turbopack)
+                ▲ Next.js x.y.z (Turbopack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents (enabled by \`__NEXT_CACHE_COMPONENTS\`)
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)
                   ✓ serverSourceMaps (enabled by \`--debug-prerender\`)
@@ -317,9 +293,8 @@ describe('build-output-prerender', () => {
           } else {
             expect(getPreambleOutput(next.cliOutput)).toMatchInlineSnapshot(`
              "⚠ Prerendering is running in debug mode. Note: This may affect performance and should not be used for production.
-                ▲ Next.js x.y.z (webpack)
+                ▲ Next.js x.y.z (webpack, Cache Components)
                 - Experiments (use with caution):
-                  ✓ cacheComponents (enabled by \`__NEXT_CACHE_COMPONENTS\`)
                   ⨯ prerenderEarlyExit (disabled by \`--debug-prerender\`)
                   ✓ reactDebugChannel (enabled by \`__NEXT_EXPERIMENTAL_DEBUG_CHANNEL\`)
                   ⨯ serverMinification (disabled by \`--debug-prerender\`)