mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
### What? Error messages for the `"use cache"` directive and `after()` API (in `cookies()`, `headers()`, `connection()`) pointed to `/docs/canary/...` instead of `/docs/...`. ### Why? On canary builds, `docs/canary` links can create circular or confusing references. These APIs are stable and their docs live at the standard `/docs/app/...` path. ### How? Replaced all `nextjs.org/docs/canary/` URLs with `nextjs.org/docs/` in: - `crates/next-custom-transforms/src/transforms/server_actions.rs` — the `"use cache"` feature flag error - `crates/next-custom-transforms/tests/errors/use-cache-not-allowed/1/output.stderr` and `2/output.stderr` — matching test fixtures - `packages/next/src/server/request/cookies.ts`, `headers.ts`, `connection.ts` — `after()` errors - `packages/next/errors.json` — compiled error message index (6 occurrences) <!-- NEXT_JS_LLM_PR -->
198 lines
6.4 KiB
TypeScript
198 lines
6.4 KiB
TypeScript
import { nextTestSetup } from 'e2e-utils'
|
||
import { NextConfig } from 'next'
|
||
import {
|
||
waitForRedbox,
|
||
waitForNoRedbox,
|
||
getRedboxDescription,
|
||
getRedboxSource,
|
||
retry,
|
||
} from 'next-test-utils'
|
||
import stripAnsi from 'strip-ansi'
|
||
|
||
const nextConfigWithUseCache: NextConfig = {
|
||
experimental: { useCache: true },
|
||
}
|
||
|
||
describe('use-cache-without-experimental-flag', () => {
|
||
const { next, isNextStart, isTurbopack, skipped, isRspack } = nextTestSetup({
|
||
files: __dirname,
|
||
skipStart: process.env.NEXT_TEST_MODE !== 'dev',
|
||
skipDeployment: true,
|
||
})
|
||
|
||
if (skipped) {
|
||
return
|
||
}
|
||
|
||
if (isNextStart) {
|
||
it('should fail the build with an error', async () => {
|
||
const { cliOutput } = await next.build()
|
||
const buildOutput = getBuildOutput(cliOutput)
|
||
|
||
if (isTurbopack) {
|
||
expect(buildOutput).toContain(
|
||
'To use "use cache", please enable the feature flag `cacheComponents` in your Next.js config.'
|
||
)
|
||
expect(buildOutput).toContain(
|
||
'Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage'
|
||
)
|
||
expect(buildOutput).toContain('Ecmascript file had an error')
|
||
expect(buildOutput).toContain('./app/page.tsx:1:1')
|
||
expect(buildOutput).toContain("> 1 | 'use cache'")
|
||
expect(buildOutput).toContain('at <unknown> (./app/page.tsx:1:1)')
|
||
} else if (isRspack) {
|
||
expect(buildOutput).toMatchInlineSnapshot(`
|
||
"
|
||
./app/page.tsx
|
||
╰─▶ × Error: x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
|
||
│ |
|
||
│ | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
|
||
│
|
||
│ ,-[1:1]
|
||
│ 1 | 'use cache'
|
||
│ : ^^^^^^^^^^^
|
||
│ 2 |
|
||
│ 3 | export default async function Page() {
|
||
│ 4 | return <p>hello world</p>
|
||
│ \`----
|
||
│
|
||
|
||
Import trace for requested module:
|
||
./app/page.tsx
|
||
|
||
|
||
> Build failed because of Rspack errors
|
||
"
|
||
`)
|
||
} else {
|
||
expect(buildOutput).toMatchInlineSnapshot(`
|
||
"
|
||
./app/page.tsx
|
||
Error: x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
|
||
|
|
||
| Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
|
||
|
||
,-[1:1]
|
||
1 | 'use cache'
|
||
: ^^^^^^^^^^^
|
||
2 |
|
||
3 | export default async function Page() {
|
||
4 | return <p>hello world</p>
|
||
\`----
|
||
|
||
Import trace for requested module:
|
||
./app/page.tsx
|
||
|
||
|
||
> Build failed because of webpack errors
|
||
"
|
||
`)
|
||
}
|
||
})
|
||
} else {
|
||
it('should show a build error', async () => {
|
||
const browser = await next.browser('/')
|
||
|
||
await waitForRedbox(browser)
|
||
|
||
const errorDescription = await getRedboxDescription(browser)
|
||
const errorSource = await getRedboxSource(browser)
|
||
|
||
if (isTurbopack) {
|
||
expect(errorDescription).toMatchInlineSnapshot(
|
||
`"To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
|
||
)
|
||
} else if (isRspack) {
|
||
expect(errorDescription).toMatchInlineSnapshot(
|
||
`" ╰─▶ × Error: x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
|
||
)
|
||
} else {
|
||
expect(errorDescription).toMatchInlineSnapshot(
|
||
`" x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config."`
|
||
)
|
||
}
|
||
|
||
if (isTurbopack) {
|
||
expect(errorSource).toContain('./app/page.tsx (1:1)')
|
||
expect(errorSource).toContain(
|
||
'To use "use cache", please enable the feature flag `cacheComponents` in your Next.js config.'
|
||
)
|
||
expect(errorSource).toContain(
|
||
'Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage'
|
||
)
|
||
expect(errorSource).toContain("> 1 | 'use cache'")
|
||
expect(errorSource).toContain('Ecmascript file had an error')
|
||
} else if (isRspack) {
|
||
expect(errorSource).toMatchInlineSnapshot(`
|
||
"./app/page.tsx
|
||
╰─▶ × Error: x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
|
||
│ |
|
||
│ | Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
|
||
│
|
||
│ ,-[1:1]
|
||
│ 1 | 'use cache'
|
||
│ : ^^^^^^^^^^^
|
||
│ 2 |
|
||
│ 3 | export default async function Page() {
|
||
│ 4 | return <p>hello world</p>
|
||
│ \`----
|
||
│"
|
||
`)
|
||
} else {
|
||
expect(errorSource).toMatchInlineSnapshot(`
|
||
"./app/page.tsx
|
||
Error: x To use "use cache", please enable the feature flag \`cacheComponents\` in your Next.js config.
|
||
|
|
||
| Read more: https://nextjs.org/docs/app/api-reference/directives/use-cache#usage
|
||
|
||
,-[1:1]
|
||
1 | 'use cache'
|
||
: ^^^^^^^^^^^
|
||
2 |
|
||
3 | export default async function Page() {
|
||
4 | return <p>hello world</p>
|
||
\`----"
|
||
`)
|
||
}
|
||
})
|
||
|
||
it('should recover from the build error if useCache flag is set', async () => {
|
||
const browser = await next.browser('/')
|
||
|
||
await waitForRedbox(browser)
|
||
|
||
await next.patchFile(
|
||
'next.config.js',
|
||
`module.exports = ${JSON.stringify(nextConfigWithUseCache)}`,
|
||
() =>
|
||
retry(async () => {
|
||
expect(await browser.elementByCss('p').text()).toBe('hello world')
|
||
await waitForNoRedbox(browser)
|
||
})
|
||
)
|
||
})
|
||
}
|
||
})
|
||
|
||
function getBuildOutput(cliOutput: string): string {
|
||
const lines: string[] = []
|
||
let skipLines = true
|
||
|
||
for (const line of cliOutput.split('\n')) {
|
||
if (!skipLines) {
|
||
if (line.includes('at turbopackBuild')) {
|
||
break
|
||
}
|
||
|
||
lines.push(stripAnsi(line))
|
||
} else if (
|
||
line.includes('Build error occurred') ||
|
||
line.includes('Failed to compile')
|
||
) {
|
||
skipLines = false
|
||
}
|
||
}
|
||
|
||
return lines.join('\n')
|
||
}
|