mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
eacb749030
## Summary - upgrade `@rspack/core` to `2.0.0-rc.0` - sync the in-tree next rspack Rust binding/toolchain with newer rspack releases - align Next server runtime selection so `NEXT_RSPACK` uses the turbo-like app runtime path - include missing compiled `@next/react-refresh-utils` output in `ncc-compiled` ## What is done - `@next/rspack` Rust binding builds locally - `packages/next` builds locally - rspack-related tests are running and have been reduced to deeper runtime compatibility failures ## Rspack test investigation Latest checked CI run: `build-and-test` run `27129243230` at head `484e7bf1b30655a9f94d0855b9e00774b4b38cd0`. Confirmed Rspack / webpack parity gaps: - `test/e2e/edge-runtime-configurable-guards/edge-runtime-configurable-guards.test.ts`: Rspack does not expose the webpack parser hooks used by `MiddlewarePlugin`. The current Rspack path falls back to SWC analysis in `finishModules`, which can report diagnostics but cannot apply the parser-time transforms that wrap `eval` / `new Function`, track `InnerGraph` usage for used vs unused dynamic code, or apply `unstable_allowDynamic` with webpack parity. Dev therefore misses the expected dynamic-code runtime warnings and also reports false `process.cwd` Edge warnings from Next internals; prod fails allowed/unused dynamic-code cases. - `test/development/middleware-overrides-node.js-api/middleware-overrides-node.js-api.test.ts`: same parser-hook limitation. Webpack can observe that `process.cwd` is overwritten before use, while the Rspack SWC fallback statically flags `process.cwd` as an unsupported Edge Node API. - `test/production/css-features/css-compilation.test.ts`: the CSS is minified and prefixed as expected, but the Rspack lightningcss path currently does not expose/control source map generation the way this test expects, so emitted CSS has no `sourceMappingURL` comment or `.map` file to assert. - `test/e2e/app-dir/server-source-maps/server-source-maps.test.ts`: invalid source maps are not handled with the same graceful diagnostic as webpack/Node source-map handling. Rspack logs the raw `webpack-internal` frame for the damaged map case instead of surfacing the expected `Invalid source map. Only conformant source maps...` message with the cause. - `test/e2e/app-dir/parallel-routes-revalidation/parallel-routes-revalidation.test.ts`: raw CI output observed a dev-mode timeout waiting for `networkidle` after refresh/back/forward lazy fetching. This was not the final structured failure in the latest run, but it remains a Rspack dev parity follow-up around router cache lazy fetches and network settling. - `test/e2e/middleware-src/middleware-src.test.ts`: after the test adds root middleware files, Rspack dev still lets `src/middleware` participate; the expected behavior is that only the root middleware runs. - `test/e2e/env-config/env-config.test.ts`: changing `.env` logs `Reload env:` but the client keeps the previous `NEXT_PUBLIC_` value, pointing at an Rspack dev env invalidation/HMR gap. - `test/e2e/app-dir/use-cache-without-experimental-flag/use-cache-without-experimental-flag.test.ts`: after enabling the `useCache` flag, the dev server does not finish restarting, pointing at build-error recovery/restart parity. - `test/development/app-dir/server-navigation-error/server-navigation-error.test.ts`: middleware navigation-error cases hit `ERR_CONNECTION_REFUSED`, consistent with the Rspack dev server exiting or restarting unexpectedly during those error flows. - `test/e2e/opentelemetry/instrumentation/opentelemetry.test.ts`: the custom-server dev process exits before the SDK handle is initialized, then cleanup fails on `shutdown`; this needs follow-up in Rspack dev/custom-server startup. - `test/e2e/next-image-new/app-dir/app-dir.test.ts`: after toggling image source, `onLoadingComplete` still reports the previous image dimensions/source, pointing at an Rspack dev image/HMR or asset invalidation parity issue. - `test/e2e/node-cli-args/node-cli-args.test.ts`: on Node `20.19.x`, `node --experimental-network-inspection` resolves instead of rejecting. This looks like a Node-version behavior change rather than an Rspack compiler issue. Not attributed to this Rspack upgrade: - `test/e2e/app-dir/instant-navigation-testing-api/instant-navigation-testing-api.test.ts` was marked by `scripts/pr-status.js` as a known flaky test across branches. - `test/production/app-dir/build-output-prerender/build-output-prerender.test.ts` ran in the webpack prod job and only differs by prerender error ordering in the inline snapshot. <!-- NEXT_JS_LLM_PR --> --------- Co-authored-by: Benjamin Woodruff <benjamin.woodruff@vercel.com>
162 lines
5.5 KiB
TypeScript
162 lines
5.5 KiB
TypeScript
import { nextTestSetup, isNextDev, isNextStart, isRspack } from 'e2e-utils'
|
|
import { retry } from 'next-test-utils'
|
|
import stripAnsi from 'next/dist/compiled/strip-ansi'
|
|
|
|
const EVAL_ERROR = `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime`
|
|
const DYNAMIC_CODE_ERROR = `Dynamic Code Evaluation (e. g. 'eval', 'new Function', 'WebAssembly.compile') not allowed in Edge Runtime`
|
|
const WASM_COMPILE_ERROR = `Dynamic WASM code generation (e. g. 'WebAssembly.compile') not allowed in Edge Runtime`
|
|
const WASM_INSTANTIATE_ERROR = `Dynamic WASM code generation ('WebAssembly.instantiate' with a buffer parameter) not allowed in Edge Runtime`
|
|
|
|
jest.setTimeout(1000 * 60 * 2)
|
|
|
|
type NextFetchResponse = Awaited<
|
|
ReturnType<ReturnType<typeof nextTestSetup>['next']['fetch']>
|
|
>
|
|
|
|
describe('Page using eval in development mode', () => {
|
|
if (!isNextDev) {
|
|
it('only runs in dev mode', () => {})
|
|
return
|
|
}
|
|
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
it('does not issue dynamic code evaluation warnings', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const html = await next.render('/')
|
|
expect(html).toMatch(/>.*?100.*?and.*?100.*?<\//)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).not.toContain(EVAL_ERROR)
|
|
expect(output).not.toContain(DYNAMIC_CODE_ERROR)
|
|
expect(output).not.toContain(WASM_COMPILE_ERROR)
|
|
expect(output).not.toContain(WASM_INSTANTIATE_ERROR)
|
|
})
|
|
})
|
|
})
|
|
|
|
describe.each([
|
|
{
|
|
title: 'Middleware',
|
|
computeRoute(useCase: string) {
|
|
return `/${useCase}`
|
|
},
|
|
async extractValue(response: NextFetchResponse) {
|
|
return JSON.parse(response.headers.get('data')!).value
|
|
},
|
|
},
|
|
{
|
|
title: 'Edge route',
|
|
computeRoute(useCase: string) {
|
|
return `/api/route?case=${useCase}`
|
|
},
|
|
async extractValue(response: NextFetchResponse) {
|
|
return (await response.json()).value
|
|
},
|
|
},
|
|
])(
|
|
'$title usage of dynamic code evaluation',
|
|
({ extractValue, computeRoute, title }) => {
|
|
if (isNextDev) {
|
|
const { next } = nextTestSetup({
|
|
files: __dirname,
|
|
})
|
|
|
|
it('shows a warning when running code with eval', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const res = await next.fetch(computeRoute('using-eval'))
|
|
expect(await extractValue(res)).toEqual(100)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).toContain(EVAL_ERROR)
|
|
})
|
|
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).toContain("eval('100')")
|
|
})
|
|
|
|
it('does not show warning when no code uses eval', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const res = await next.fetch(computeRoute('not-using-eval'))
|
|
expect(await extractValue(res)).toEqual(100)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).not.toContain('Dynamic Code Evaluation')
|
|
})
|
|
})
|
|
|
|
it('shows a warning when running WebAssembly.compile', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const res = await next.fetch(computeRoute('using-webassembly-compile'))
|
|
expect(await extractValue(res)).toEqual(81)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).toContain(WASM_COMPILE_ERROR)
|
|
})
|
|
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).toContain('WebAssembly.compile')
|
|
})
|
|
|
|
it('shows a warning when running WebAssembly.instantiate with a buffer parameter', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const res = await next.fetch(
|
|
computeRoute('using-webassembly-instantiate-with-buffer')
|
|
)
|
|
expect(await extractValue(res)).toEqual(81)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).toContain(WASM_INSTANTIATE_ERROR)
|
|
})
|
|
|
|
const output = stripAnsi(next.cliOutput.slice(outputIndex))
|
|
expect(output).toContain('WebAssembly.instantiate(SQUARE_WASM_BUFFER')
|
|
})
|
|
|
|
it('does not show a warning when running WebAssembly.instantiate with a module parameter', async () => {
|
|
const outputIndex = next.cliOutput.length
|
|
const res = await next.fetch(
|
|
computeRoute('using-webassembly-instantiate')
|
|
)
|
|
expect(await extractValue(res)).toEqual(81)
|
|
|
|
await retry(async () => {
|
|
const output = next.cliOutput.slice(outputIndex)
|
|
expect(output).not.toContain(WASM_INSTANTIATE_ERROR)
|
|
expect(output).not.toContain('DynamicWasmCodeGenerationWarning')
|
|
})
|
|
})
|
|
}
|
|
|
|
if (isNextStart) {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: __dirname,
|
|
skipStart: true,
|
|
})
|
|
|
|
it('should have middleware warning during build', async () => {
|
|
const { cliOutput } = await next.build()
|
|
|
|
if (isTurbopack) {
|
|
expect(cliOutput).toContain(`Ecmascript file had an error`)
|
|
} else if (isRspack) {
|
|
expect(cliOutput).toContain(`Failed to compile`)
|
|
} else {
|
|
expect(cliOutput).toContain(`Failed to compile`)
|
|
expect(cliOutput).toContain(`Used by usingEval, usingEvalSync`)
|
|
expect(cliOutput).toContain(`Used by usingWebAssemblyCompile`)
|
|
}
|
|
|
|
expect(cliOutput).toContain(DYNAMIC_CODE_ERROR)
|
|
})
|
|
}
|
|
}
|
|
)
|