[pull] canary from vercel:canary#1098
Merged
Merged
Conversation
Introduces new shell stages and adds relevant tasks where needed. We're not changing the timing of when anything resolves yet, so this should not have any behavioral changes.
…cs slugs (#94017) ### What? Adds "Copy prompt" button to all 33 instant-guidance fix cards. Updates card links, factory `Learn more:` URLs, and overlay routing to the new docs slugs. Adds `[group]` tag prefix to CLI fix bullets so agents can map them back to card prompts. ### Why? Cards tell developers _what_ to do. The button gives agents a ready-to-paste instruction. The `[group]` tag lets agents reading CLI output find the matching card in the docs without parsing prose. ### How? - `prompt` field on all 33 `FixCard` entries. - Button replaces the external-link icon in the top-right; link moves next to the label. - Card links updated to `blocking-prerender-*` and `instant-unrendered-segment` slugs (avoids overriding upstream pages). - Variant-aware URL routing for `metadata` and `viewport` (matches existing `blocking-route` pattern). `InstantHeaderExplanation` takes a `variant` prop. - Fix bullets prefixed with their card group: `[cache]`, `[stream]`, `[block]`, etc. Tags match `<FixOption group>` in the MDX docs. - CLI bullets use `unstable_instant = false` (the current API). Overlay cards keep `instant` (aspirational). - Metadata dynamic-marker bullet now mentions the Suspense wrapper. - Merged canary: unrendered-segment errors land in the Insights tab via `isInstantNavigationError`. ### Depends on - [vercel/front#71640](vercel/front#71640) — 6 sync-IO pages - [vercel/front#71781](vercel/front#71781) — 4 metadata/viewport pages + `instant-unrendered-segment`
Reimplements app shells in runtime prefetches in terms of a staged render. when `appShells` is on: - a `next-router-prefetch: 2` request (i.e. "including link data") will have a shell stage that only includes session data. we communicate the byte offset to the client so it can rewind the response to a session fallback - a `next-router-prefetch: 3` request (i.e. "session shell") stops rendering after the shell stages, i.e. link data is never resolved. this replaces the previous `forceOmitParams` implementation. Note that In order to produce a session shell, we have to resolve static `params` and rootParams in the Runtime stage (previously, they'd resolve in the static stage). This is because params are link data and cannot be part of the session shell. We don't really need to rewind a runtime prefetch to a static stage, so this divergence in behavior shouldn't be meaningfully observable. Notable call-out: root params getters can also be called inside caches. if a cache accesses root params, then the cache depends on link data and must be excluded from the shell. We rely on existing mechanisms for tracking root param access and delay the cache appropriately in the final render.
# What Replace the `derive` macros for TaskInput with a proc macro `[turbo_tasks::task_input]` (and analogous support inside of the `turbo_tasks::value` macro. Introduce a hand written `CloneResolved` future type for TaskInput implementations that are always resolved. # Why This allows us to take advantage of the `NonLocalValue` marker trait. If a type is `NonLocalValue` then `TaskInput` can have trivial `is_resolved` and `resolve_input` implementations. This applies to the vast majority of TaskInputs but the current `derive` implementation always produces a recursive `async` `resolve_input` implementation but it is rarely needed and rustc/llvm do a bad job of optimizing it. ## Code-size impact `next-swc.darwin-arm64.node` — release profile, `pnpm swc-build-native --release`, macOS aarch64. | Metric | canary | this branch | Δ bytes | Δ % | | --- | ---: | ---: | ---: | ---: | | Raw `.node` | 124,494,592 | 124,217,280 | −277,312 | −0.22% | | Stripped (`strip -x`) | 84,294,000 | 84,013,136 | −280,864 | −0.33% | | Stripped + gzip -9 | 29,123,538 | 28,898,920 | −224,618 | −0.77% | ## Performance A similar measurement of performance was neutral | Metric | canary | temporary | Δ | % | |---|---|---|---|---| | wall time (s) | 42.659 ± 1.851 | 42.501 ± 2.028 | −0.158 | −0.4% | | user time (s) | 294.322 ± 1.834 | 293.207 ± 2.070 | −1.115 | −0.4% | | sys time (s) | 74.158 ± 4.197 | 73.543 ± 5.725 | −0.615 | −0.8% | | MaxRSS (MB) | 13650.1 ± 66.0 | 13610.1 ± 57.5 | −40.0 | −0.3% | All deltas are smaller than one standard deviation — statistically indistinguishable from noise on this benchmark, as expected for a small optimization.
## What Removes the `ArgMeta::is_resolved` function-pointer field and the 592 monomorphized `closure#3` trampolines it generated. The `TaskInput::is_resolved` check that runs on the synchronous fast path of every turbo-tasks function call now happens at the macro-generated callsite on the concrete tuple type, before erasure into `&dyn StackDynTaskInputs`. For trait calls with `filter_owned`, the check is fused into the filter functor so the filter and the resolved-check monomorphize together. ## Why The `is_resolved` method is almost always trivial after optimization but putting it behind an opaque function pointer means we always pay a small code size and perf cost. Inlining actually saves bothr `Vc` field. Bonus rename: `OwnedStackDynTaskInputs` → `BoxedDynTaskInputs`. The \"Stack\" was the trait, not the storage — the inner value is a `Box<dyn DynTaskInputs>` on the heap. ## Hot-path microcheck The synchronous wrapper for a representative 6-input turbo function (`directory_tree_to_loader_tree`) now performs the entire `is_resolved` check as ~15 register-only ARM instructions inlined into the caller — three `cmp/csel/tbnz` chains testing the discriminant byte of each `Vc<...>` input. The four trivially-resolved inputs (`FileSystemPath`, `RcStr`, `AppPage`, `AppPath`) contribute zero instructions because their `is_resolved` constant-folded to `true`. No indirect call, no downcast trampoline. ## Code-size impact Release `next-swc.darwin-arm64.node`, macOS aarch64, vs the `temporary` branch this PR is stacked on: | Metric | prior (temporary) | this PR | Δ bytes | Δ % | | --- | ---: | ---: | ---: | ---: | | Raw `.node` | 124,217,280 | 123,845,712 | −371,568 | −0.30% | | Stripped (`strip -x`) | 84,013,136 | 83,880,384 | −132,752 | −0.16% | | Stripped + gzip -9 | 28,898,920 | 28,887,624 | −11,296 | −0.04% | <!-- NEXT_JS_LLM_PR -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )