mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
codex/ledgers-react-sync
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
bcfa15d0ed |
Remove the worker thread for turbopack builds (#96862)
Avoid spawning a worker thread to run turbopack The typical arguments for worker threads are that they isolate the JS heap and enable parallelism, but turbopack does both these things by default (native heap is isolated, the js deps are minor and have a lot of overlap with existing next server deps). There is also no substantial parallelism opportunity from worker threads that aren't immediately delivered by turbopacks execution model ## Benchmarks Measured with a paired A/B harness that alternates `head` and `base` builds so thermal drift and background load cancel out, discarding a warmup build per variant and clearing `.next` before each run. Both variants are the same commit except for this change. 35 paired iterations on a default `create-next-app` (App Router, TS), Node 20.11.1, Apple silicon. | Metric | this PR | canary | Diff | 95% CI | Wins | | --- | --- | --- | --- | --- | --- | | `next-build` total | 2478 ms | 2595 ms | **-117 ms (4.5%)** | [50, 183] | 30/35 | | `run-turbopack` | 1228 ms | 1335 ms | -107 ms (8.0%) | [62, 152] | 31/35 | | overhead (total - turbopack) | 1250 ms | 1260 ms | -10 ms (0.8%) | [-27, 46] | 20/35 | | wall clock | 2775 ms | 2888 ms | -112 ms (3.9%) | [45, 180] | 30/35 | | peak RSS | 1175 MiB | 1195 MiB | **-19 MiB (1.6%)** | [3.4, 35.3] | 22/35 | Significant by both a paired t-test and a Wilcoxon signed-rank test (p = 0.0001 for total build time, p = 0.025 for RSS). The Wilcoxon is included because a couple of slow builds per run would otherwise dominate the variance. Nearly all of the saving lands inside the `run-turbopack` span rather than around it, which is expected: that span wraps the worker spawn, the IPC to marshal the build across, and the teardown, so deleting the worker removes work from inside it. The win is proportionally smaller on larger apps, where compilation dominates. On `bench/basic-app` (~400 source modules, ~19s builds) the same ~115 ms is well inside the noise -- 12 paired iterations there showed no significant difference on any metric. So this is a real but small improvement that is only user-visible on small builds: | Metric | this PR | canary | Diff | 95% CI | | --- | --- | --- | --- | --- | | `next-build` total | 19313 ms | 19436 ms | -123 ms (0.6%) | [-256, 502] | | overhead (total - turbopack) | 1424 ms | 1415 ms | +9 ms (0.6% slower) | [-52, 70] | Caveats: single machine and two fixture shapes. Peak RSS is the build process's own footprint (`/usr/bin/time -l`), which includes the worker thread's isolate but not the separately spawned static-generation workers. A CI runner with fewer cores would plausibly show a larger effect. |
||
|
|
a7b04690e6 |
gitignore .next-profiles (#95256)
### What? When profiling is enabled (`--experimental-cpu-prof` / `--internal-trace`, or the `NEXT_CPU_PROF` / `NEXT_TURBOPACK_TRACING` env vars), Next.js writes a `.gitignore` containing `*` into `.next-profiles/` as it creates the directory. This keeps the profiling output out of git and out of the way of tools that scan the project tree. ### Why? `.next-profiles` is a sibling of `.next`, so it's intentionally *not* covered by the `.gitignore` create-next-app ships. The motivation was that profiles wouldn't bloat `.next` and wouldn't be silently ignored. But a sibling dir full of large profile/trace files turns out to be a liability: - **Ecosystem tools scan it.** Tailwind v4 aggressively auto-scans files and has opened a `trace-turbopack.bin` and crashed; Turborepo <2.8.13 hashes the file and OOMs, and >=2.8.13 fails to start `dev` watchers because reading the large trace is too slow. (workflow watchers are likely affected too.) - **Turbopack NFT globbing** can read/hash the file via overly broad `fs.read` patterns. - **Accidental commits.** Pushing a multi-GB trace would be miserable for a customer helping us debug. These have each gotten point bandaids (#94587, #94570), but the real fix preserves the original motivation: a nested `.gitignore` with `*` keeps the files off git **and** makes gitignore-respecting tools (Tailwind, Turborepo) skip the whole subtree, which resolves the scanning failures. Reverting to `.next/profiles` was the alternative; the gitignore approach keeps the existing path. ### How? - `ensureProfilesDir()` (`packages/next/src/lib/profiles-dir.ts`) creates `.next-profiles` and writes the `.gitignore` (only if absent, so user edits survive). Single source of truth. - `bin/next.ts` calls a `setupProfilesDir()` helper on build/dev/start, gated on the env vars so both the CLI flags and direct env-var usage are covered. Skipped when `NEXT_TURBOPACK_TRACING_PATH` redirects trace output. - Rust keeps `create_dir_all` as a backstop for the trace dir; the `.gitignore` is written in JS only. - Docs switched from `NEXT_TURBOPACK_TRACING=1` to `next dev --internal-trace`, and the stale `trace-turbopack` filename corrected to `trace-turbopack.bin`. <!-- NEXT_JS_LLM_PR --> |
||
|
|
8141dcf12e |
Convert test/integration to isolated tests (#93247)
### What?
Converts every test under `test/integration/` to an isolated test
running through `nextTestSetup` (under `test/e2e/`, `test/production/`,
`test/development/`, or `test/unit/`), then deletes `test/integration/`
along with the legacy CI orchestration that was specific to it.
- `test/integration/` removed entirely (~327 test suites)
- New isolated suites added across the existing folders:
- `test/e2e/` — 175
- `test/production/` — 130
- `test/development/` — 43
- `test/unit/` — 1
- `.github/workflows/build_and_test.yml` and `run-tests.js` no longer
have any `integration` branches
- `nextTestSetup` gained a `baseUrl` option on `next.browser()` so a
small number of tests that drive their own proxy/static-export server
can keep using `next.browser(...)` instead of importing `next-webdriver`
directly
### Why?
`test/integration/` predated `nextTestSetup` and ran tests directly
against the source checkout via custom helpers (`launchApp`,
`nextBuild`, `nextStart`, `runNextCommand`, `webdriver`, `fetchViaHTTP`,
…). Each suite hand-rolled its own dev/start/build orchestration,
fixture mutation, and process management.
The isolated test model used by the rest of the repo gives each suite an
isolated working directory containing a packed `next.tgz` install, a
uniform `next.start()` / `next.build()` / `next.fetch()` /
`next.browser()` API, and the same lifecycle for dev, start, and deploy
modes — so a single set of assertions covers all three. Deploy-mode
skips and per-feature gates are expressed declaratively
(`skipDeployment`, `disableAutoSkewProtection`, `if (skipped) return`)
instead of branching on `process.env`.
Removing `test/integration/` lets us:
- Delete the bespoke orchestration code in the CI workflow and
`run-tests.js`
- Run every converted suite consistently in dev, start, and deploy modes
(where applicable)
- Reproduce every test locally with the same `pnpm
test-{dev,start}-{turbo,webpack}` commands; no separate `integration`
path
- Open the door to running `test/production` against deployments in the
future (the converted suites already declare `skipDeployment` so they
can be flipped on)
### How?
Mechanical conversion per suite, with targeted clean-ups:
1. **Per-suite conversion.** Each
`test/integration/<name>/test/index.test.{js,ts}` was rewritten into a
single `<name>.test.ts` under the right folder based on what the
original exercised:
- `launchApp` / dev-only assertions → `test/development/`
- `nextBuild` + `nextStart` / start-only assertions → `test/production/`
- Both → `test/e2e/`
- The one pure jsdom render check (`link-without-router`) → `test/unit/`
2. **API mapping.** Custom helpers were replaced by `nextTestSetup`
equivalents: `launchApp` → `next.start()`, `nextBuild` → `next.build()`,
`runNextCommand` → `next.runCommand`, `fetchViaHTTP` → `next.fetch`,
`webdriver(...)` → `next.browser(...)`. Fixture mutations switched from
raw `fs.writeFile`/`fs.rename` to `next.patchFile` (with the 3-arg
`runWithTempContent` callback when the change has a defined scope) and
`next.deleteFile`.
3. **Deploy-mode handling.** Suites that can't run in deploy mode (use
`patchFile` / `next.build()` / depend on local CLI output) declare
`skipDeployment: true` and early-return on the `skipped` boolean. Suites
where Vercel's edge mutates URLs (`&dpl=`, immutable assets) declare
`disableAutoSkewProtection: true`.
4. **`next.browser({ baseUrl })`.** A handful of tests
(`prerender-export`, `cdn-cache-busting`, `preload-viewport`, both
`react-virtualized` suites) need to drive a separate server (a
static-export server or an `http-proxy` instance) rather than the
Next.js process. Instead of importing `next-webdriver` directly, those
tests now pass `{ baseUrl: <port|url> }` to `next.browser()`. For the
proxy cases, the proxy was moved into `server.js` inside the fixture and
`http-proxy` declared via the `dependencies` option of `nextTestSetup`,
so the test runs with a fully isolated dependency graph.
5. **CI clean-up.** With `test/integration` gone, the `test
integration*` jobs and `integration-tests-manifest`-related logic in
`.github/workflows/build_and_test.yml` were removed, and `run-tests.js`
no longer has the `integration` test-folder branch.
6. **Validation.** The PR was iterated against multiple full CI runs;
the remaining failures on the latest run are pre-existing flakes
(segment-cache 60s `act` timeouts in turbopack-prod) or transient
infrastructure issues unrelated to the conversion.
|
||
|
|
cf328d3afe |
CPU prof: Write profiles to .next-profiles instead of .next/cpu-profiles (#92078)
## What? Writes the CPU profiles to .next-profiles. This makes sure it's not tied to `.next` / `.next/dev`. It's one consistent place for the file. |
||
|
|
fd5817d004 |
feat: add --experimental-cpu-prof flag for dev, build, and start (#87946)
## What Adds a `--experimental-cpu-prof` flag to `next dev`, `next build`, and `next start` commands to capture V8 CPU profiles for debugging performance bottlenecks. ## Why When investigating slow builds, slow dev server startups, or production server performance issues, having access to CPU profiles is invaluable. This provides a first-party way to capture these profiles without needing to manually set up the V8 inspector. ## How - Adds `--experimental-cpu-prof` flag to CLI commands - Uses V8's built-in CPU profiler via Node.js inspector module - Profiles are saved to `.next/cpu-profiles/` with descriptive filenames - Profiles are saved on process exit (Ctrl+C, SIGTERM, or normal exit) ### Profile files generated **`next dev`:** - `dev-main-*` - Parent process (dev server orchestration) - `dev-server-*` - Child server process (request handling and rendering) **`next build` (Turbopack):** - `build-main-*` - Main build orchestration process - `build-turbopack-*` - Turbopack compilation worker **`next build` (Webpack):** - `build-main-*` - Main build orchestration process - `build-webpack-client-*` - Client bundle compilation worker - `build-webpack-server-*` - Server bundle compilation worker - `build-webpack-edge-server-*` - Edge runtime compilation worker **`next start`:** - `start-main-*` - Production server process ## Changes addressing PR review comments - Removed signal handlers from `cpu-profile.ts` to prevent conflicts with CLI cleanup logic (telemetry, traces, etc.) - Added synchronous exit handler for non-signal process exits (errors, `process.exit()` calls) - CLI commands now explicitly call `saveCpuProfile()` as part of their cleanup before exiting - Replaced raw ANSI escape codes with `picocolors` library - Added comprehensive documentation about profile file naming for each command - Added build profiling test that verifies correct profile generation for both Turbopack and Webpack modes --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl> |