mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
codex/fallback-root-cache
10 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5f688d274a |
[Bench] Add client-trace attribution pass and document metrics to render-pipeline (#95828)
Added a bunch of stuff to the bench. --- **New metrics in the HTTP benchmark** - Report TTFB per route (time to first body byte), next to total latency. - Report each route's document size, how many bytes are inline Flight payload, and the Flight share. **New script: `pnpm bench:render-pipeline:client`** - Loads each route in Chrome with tracing and 4x CPU throttling, and breaks down where client time goes: evaluating chunks, evaluating inline Flight scripts, compiling, background parsing, GC, time to hydration, and blocking time before hydration. - Also prints FCP/LCP/DOMContentLoaded/load from the same trace, and JS transferred vs parsed. - Off by default, separate from the timing benchmark, since tracing perturbs timing. - Hydration time comes from a small client component added to the fixture root layout that calls `performance.mark`. **Bug fixes** - The benchmark was replacing the fixture's `next.config.js` with an empty one during runs. - If the port was already taken, the benchmark could silently measure whatever server was already running there. Both scripts now refuse to start if something is already on the port. - A server that died on startup used to look like a slow server; now it errors immediately. - One failed request used to abort the whole run and throw away all results. Now it costs one sample and gets counted in `errors`. - Killing an already-dead server used to hang the script. - Bad flags now error upfront instead of crashing at the end. --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
0156307f55 |
[Bench] Extend bench app to have realistic client chunk counts (#95814)
Follow-up to https://github.com/vercel/next.js/pull/95807. Makes payload size match prod sizes closer and aligns chunk count by adding a lot of client modules. I originally thought to unify them into `client.js` or such but maybe it's good to see how compilation behaves with many small files? Which is how real projects do that. ``` === dashboard.html (fixture) vs p-overview.html (real) total KB 665 637 rows (model/I/T/other) 258/111/3/1 240/125/5/27 byte share model/I/T % 43/57/0 36/62/2 median row size B 906 106 max depth 43 53 mean depth 8.9 10.5 elements per KB(model) 7.7 5.2 pure-data byte share % 18 21 client-ref elements % 35 32 objects:elements ratio 1.18 1.23 avg props per element 2.6 3.1 median children fanout 4 4 string bytes % 50 54 median string len B 12 15 row refs per KB 0.4 0.4 encoded scalars per KB 0.7 1.2 undefined markers 247 740 === docs.html (fixture) vs nextjs-docs.html (real) total KB 487 487 rows (model/I/T/other) 72/40/7/1 55/43/2/20 byte share model/I/T % 89/8/3 94/6/0 median row size B 199 340 max depth 27 32 mean depth 22.3 12.3 elements per KB(model) 0.6 0.8 pure-data byte share % 7 9 client-ref elements % 29 33 objects:elements ratio 8.67 4.92 avg props per element 2.0 2.8 median children fanout 3 4 string bytes % 47 64 median string len B 17 35 row refs per KB 0.2 0.1 encoded scalars per KB 7.4 2.9 undefined markers 3586 1377 === blog.html (fixture) vs vercel-blog.html (real) total KB 778 797 rows (model/I/T/other) 72/39/0/1 102/53/7/14 byte share model/I/T % 93/7/0 87/8/5 median row size B 145 505 max depth 34 44 mean depth 9.6 12.2 elements per KB(model) 0.7 1.1 pure-data byte share % 92 85 client-ref elements % 38 33 objects:elements ratio 31.19 16.39 avg props per element 1.9 2.7 median children fanout 3 4 string bytes % 46 48 median string len B 6 9 row refs per KB 0.1 0.1 encoded scalars per KB 0.4 0.6 undefined markers 242 426 ``` Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
7ffacec8ef |
Add more realistic bench fixtures (#95807)
This adds more fixtures modeled after Flight payloads from real sites: - Vercel Dashboard-like (very app-y) - React Docs-like after App Router conversion (mostly MDX site) - Vercel Blog-like (passing down data from CMS) (Actual data is randomly generated with a seed) These are simplifications but I tried to incorporate the originals' corresponding quirks. Such as Vercel Dashboard having many client components; syntax highlight with many small spans in React Docs; Vercel Blog currently shipping a load of data unnecessarily on the index page. (The last one is not ideal but I think we should actually benchmark "bad" cases like this too so I kept that.) ### Screenshots <img width="1325" height="1021" alt="Screenshot 2026-07-15 at 04 29 43" src="https://github.com/user-attachments/assets/62c80722-6fd5-4884-89db-106345f6412d" /> <img width="1360" height="994" alt="Screenshot 2026-07-15 at 04 30 21" src="https://github.com/user-attachments/assets/0db93cd8-43ca-41df-b3e2-c422e0c94656" /> <img width="1368" height="991" alt="Screenshot 2026-07-15 at 04 30 43" src="https://github.com/user-attachments/assets/9369e9be-12a4-4a1e-af32-01b6fdd4a457" /> ### Comparison with real payloads ``` === dashboard.html (fixture) vs p-overview.html (real) total KB 208 637 rows (model/I/T/other) 186/48/7/1 240/125/5/27 byte share model/I/T % 92/4/4 36/62/2 median row size B 590 106 max depth 28 53 mean depth 8.4 10.5 elements per KB(model) 14.9 5.2 pure-data byte share % 24 21 client-ref elements % 41 32 objects:elements ratio 1.17 1.23 avg props per element 1.7 3.1 median children fanout 4 4 string bytes % 24 54 median string len B 10 15 row refs per KB 0.9 0.4 encoded scalars per KB 3.5 1.2 undefined markers 347 740 === docs.html (fixture) vs nextjs-docs.html (real) total KB 261 487 rows (model/I/T/other) 58/15/7/1 55/43/2/20 byte share model/I/T % 93/1/6 94/6/0 median row size B 193 340 max depth 27 32 mean depth 21.9 12.3 elements per KB(model) 0.8 0.8 pure-data byte share % 8 9 client-ref elements % 16 33 objects:elements ratio 6.26 4.92 avg props per element 1.7 2.8 median children fanout 4 4 string bytes % 47 64 median string len B 17 35 row refs per KB 0.2 0.1 encoded scalars per KB 7.5 2.9 undefined markers 1949 1377 === blog.html (fixture) vs vercel-blog.html (real) total KB 475 797 rows (model/I/T/other) 41/15/0/1 102/53/7/14 byte share model/I/T % 100/0/0 87/8/5 median row size B 426 505 max depth 34 44 mean depth 9.7 12.2 elements per KB(model) 0.8 1.1 pure-data byte share % 92 85 client-ref elements % 23 33 objects:elements ratio 28.92 16.39 avg props per element 1.9 2.7 median children fanout 3 4 string bytes % 46 48 median string len B 6 9 row refs per KB 0.1 0.1 encoded scalars per KB 0.4 0.6 undefined markers 161 426 ``` --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
836ba3708b |
Add attribute rendering benchmark (#95621)
### What? Add two dynamic routes to the render-pipeline benchmark and include both in the default route suite: - `/attributes` renders 1,000 rows with string, data, ARIA, title, and inline-style attributes. - `/tailwind` renders a realistic dashboard with dense Tailwind-style utility class names across navigation, metrics, project cards, and an activity table. ### Why? The existing benchmark routes focus on lightweight rendering or Suspense and Flight payload stress. They do not provide focused integration coverage for React Fizz attribute serialization. `/attributes` provides a synthetic stress case modeled after the upstream React benchmark for facebook/react#36899. `/tailwind` complements it with a production-like component tree and realistic class strings, including responsive, state, dark-mode, and arbitrary-value utilities. ### How? Both fixtures run through the real Next.js production-server render-pipeline harness and are forced dynamic so every request exercises server rendering. The Tailwind-style fixture contains 18 project cards, 36 activity rows, and 101 `className` attributes. It intentionally does not install or configure Tailwind because the benchmark targets React serialization of the class strings, not generated CSS or visual styling. The new routes are registered in the default stress suite and documented in the benchmark playbook and render-pipeline README. ### Verification - Prettier for all changed files - ESLint for both benchmark fixtures and `bench/render-pipeline/benchmark.ts` - Production `next build` + `next start` smoke benchmark for `/tailwind`; single-client and under-load phases completed with zero request errors - Three interleaved base/head `/attributes` runs with 500 serial and 5,000 loaded requests - `/attributes` PR-head median throughput: +8.26% single-client and +10.85% under load - `/attributes` PR-head median p95: 7.91% better single-client and 9.61% better under load - `git diff --check` <!-- NEXT_JS_LLM_PR --> |
||
|
|
ec28a4fdc6 |
Remove experimental.useNodeStreams flag as it's enabled (#93938)
### What? Remove `experimental.useNodeStreams` from the public config surface and make Node streams always-on for Node.js App Router rendering. The smaller default-on change and dedicated CI cleanup landed in #94311. The standalone compatibility update landed separately in #94347. ### Why? Node streams are now the default Node.js runtime rendering path, so the opt-in config and runtime selection plumbing are stale. Edge bundles continue to use the web-stream path because Node streams are unavailable there. ### How? - Define `__NEXT_USE_NODE_STREAMS` as true for Node.js app runtime bundles and false for edge user bundles. - Remove config, schema, runtime, export, and server plumbing for `experimental.useNodeStreams`. - Delete the obsolete env-precedence fixture. - Clean benchmark docs and scripts that still set or compare `experimental.useNodeStreams`. ### Verification - `pnpm --filter=next types` - `pnpm build-all` <!-- NEXT_JS_LLM_PR --> |
||
|
|
663c9151cf |
bench: render-pipeline benchmarks and stress routes (2/8) (#89863)
## Summary Benchmark infrastructure for measuring render pipeline performance. - **render-pipeline benchmark** (`bench/render-pipeline/`): `benchmark.ts` for profiling render paths, `analyze-profiles.ts` for CPU profile analysis - **Stress routes** (`bench/basic-app/app/streaming/`): light, medium, heavy, bulk, wide, chunkstorm variants for different streaming load profiles - **Basic app harness**: `benchmark.sh` runner script, `next.config.js` - **Minimal server**: `bench/next-minimal-server/bin/minimal-server.js` - **Docs**: `bench/BENCHMARKING.md` guide - **Config**: eslint exclusion for bench paths, package.json bench scripts ## Test plan - [ ] No runtime behavior changes - [ ] Benchmark scripts are standalone tooling --------- Co-authored-by: Tim Neutkens <tim@timneutkens.nl> |
||
|
|
a1610fecd8 |
Fix basic-app benchmark application (#60842)
Fairly basic PR that just fixes the `basic-app` benchmark application. The api route was throwing an error since it wasn't returning a `Response`, and renamed some `pages/` directory routes so they become available. |
||
|
|
5217e7eb06 |
server: re-land bundled runtimes (#55139)
see https://github.com/vercel/next.js/pull/52997 also added a fix by @jridgewell to fix turbopack Co-authored-by: Justin Ridgewell <112982+jridgewell@users.noreply.github.com> |
||
|
|
7267538e00 |
Revert "perf: add bundled rendering runtimes (#52997)" (#55117)
This reverts commit
|
||
|
|
a5b7c77c1f |
perf: add bundled rendering runtimes (#52997)
## What? In Next, rendering a route involves 3 layers: - the routing layer, which will direct the request to the correct route to render - the rendering layer, which will take a route and render it appropriately - the user layer, which contains the user code In #51831, in order to optimise the boot time of Next.js, I introduced a change that allowed the routing layer to be bundled. In this PR, I'm doing the same for the rendering layer. This is building up on @wyattjoh's work that initially split the routing and the rendering layer into separate entry-points. The benefits of having this approach is that this allows us to compartmentalise the different part of Next, optimise them individually and making sure that serving a request is as efficient as possible, e.g. rendering a `pages` route should not need code from the `app router` to be used. There are now 4 different rendering runtimes, depending on the route type: - app pages: for App Router pages - app routes: for App Router route handlers - pages: for legacy pages - pages api: for legacy API routes This change should be transparent to the end user, beside faster cold boots. ## Notable changes Doing this change required a lot of changes for Next.js under the hood in order to make the different layers play well together. ### New conventions for externals/shared modules The big issue of bundling the rendering runtimes is that the user code needs to be able to reference an instance of a module/value created in Next during the render. This is the case when the user wants to access the router context during SSR via `next/link` for example; when you call `useContext(value)` the value needs to be the exact same reference to one as the one created by `createContext` earlier. Previously, we were handling this case by making all files from Next that were affected by this `externals`, meaning that we were marking them not to be bundled. **Why not keep it this way?** The goal of this PR as stated previously was to make the rendering process as efficient as possible, so I really wanted to avoid extraneous fs reads to unoptimised code. In order to "fix" it, I introduced two new conventions to the codebase: - all files that explicitly need to be shared between a rendering runtime and the user code must be suffixed by `.shared-runtime` and exposed via adding a reference in the relevant `externals` file. At compilation time, a reference to a file ending with this will get re-written to the appropriate runtime. - all files that need to be truly externals need to be suffixed by `.external`. At compilation time, a reference to it will stay as-is. This special case is needed mostly only for the async local storages that need to be shared with all three layers of Next. As a side effect, we should be bundling more of the Next code in the user bundles, so it should be slightly more efficient. ### App route handlers are compiled on their own layer App route handlers should be compiled in their own layer, this allows us to separate more cleanly the compilation logic here (we don't need to run the RSC logic for example). ### New rendering bundles We now generate a prod and a dev bundle for: - the routing server - the app/pages SSR rendering process - the API routes process The development bundle is needed because: - there is code in Next that relies on NODE_ENV - because we opt out of the logic referencing the correct rendering runtime in dev for a `shared-runtime` file. This is because we don't need to and that Turbopack does not support rewriting an external to something that looks like this `require('foo').bar.baz` yet. We will need to fix that when Turbopack build ships. ### New development pipeline Bundling Next is now required when developing on the repo so I extended the taskfile setup to account for that. The webpack config for Next itself lives in `webpack.config.js` and contains the logic for all the new bundles generated. ### Misc changes There are some misc reshuffling in the code to better use the tree shaking abilities that we can now use. fixes NEXT-1573 Co-authored-by: Alex Kirszenberg <1621758+alexkirsz@users.noreply.github.com> |