Skip to content

[pull] canary from vercel:canary - #1318

Merged
pull[bot] merged 7 commits into
code:canaryfrom
vercel:canary
Aug 19, 2026
Merged

[pull] canary from vercel:canary#1318
pull[bot] merged 7 commits into
code:canaryfrom
vercel:canary

Conversation

@pull

@pull pull Bot commented Aug 19, 2026

Copy link
Copy Markdown

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 : )

gnoff and others added 7 commits August 19, 2026 09:32
## Summary

After a fallback-shell cache prerender completes, snapshot whether its
timeout fired and then abort the existing timeout controller when it
participates in an `AbortSignal.any()` composite. This triggers the
composite so React removes its abort listener; no additional controller
or signal is needed. Cache prerenders without a dynamic-access source
keep their existing direct timeout signal.

Node retains non-empty composite abort signals while they have abort
listeners. React attaches such a listener during `prerender()` and
removes it when the signal aborts, so aborting the already-owned timeout
source releases the successful render. Snapshotting `didTimeout` first
keeps cleanup aborts distinct from real timeouts.

This preserves the early aborted-prerender guard from #96426, which
prevents a cache fill that starts after its outer prerender aborts from
caching an empty React stream.

Fixes #97363
Related #97464
Alternative to #97391

## Verification

- `pnpm --filter=next build`
- `pnpm test-start-turbo
test/e2e/app-dir/use-cache-after-uncached-io/use-cache-after-uncached-io.test.ts`
- `pnpm test-start-turbo
test/e2e/app-dir/use-cache-hanging/use-cache-hanging.test.ts`
- Actual vendored React `prerender()` GC probe on Node 20.19.5 and
22.20.0: valid preludes, no cleanup errors, and 0/100 composite signals
retained while their source controllers remained reachable.

<!-- NEXT_JS_LLM -->
LCP can be affected if the LCP element is sitting within a Suspense
boundary, even if its nothing but static content, if the static content
is "too large".

Apps should prefer, as long as possible, to not have a Suspense boundary
around the LCP element.

-
https://react.dev/reference/react/Suspense#what-activates-a-suspense-boundary

> Waiting for a large boundary’s HTML to arrive during streaming server
rendering. Sending HTML takes time, so a boundary with enough content
activates even when nothing in it suspends. React reveals the content as
the HTML arrives.
Closes #92082

This is now a proper compile-time constant:
```js
import { IS_DEV } from './other'
if (IS_DEV) { // statically evaluates to `true`
  console.log('x')
} else {
  require("library") // not bundled
}
console.log(IS_DEV); // is replaced with console.log(true);
```
```typescript
// other.ts
export const SOME_VALUE = 'x'

const node_env = process.env.NODE_ENV
const development_ent = 'development'
export const IS_DEV = node_env === development_ent
```

You can use code to compute constants just fine, and use any existing
constants such as `process.env.NODE_ENV`.
Currently, you can't use imports to other constants modules, but we can
add that later on.

We can't perform this constants check for every single import, so you
need to either
- have `UPPER_CASE` import names as in the example above
- or use `import { lower } from './other' with { turbopackConstants:
'true' }`

Then that referenced module will be analyzed for constants, and if the
referenced export is a constant, it will participate in constant
inlining just as `process.env.FOO`.

This also works fine with barrel imports, you can still do `import {
IS_DEV } from './barrel.js'` and it will find the `constants.js` file
which in itself will indeed only have constants exports.

Because it's not always opt-in at the import site, we can't
automatically make non-constant exports an error. For that you have to
add `'use turbopack: constants'` at the top of the module, which will
make it an error if any constant import references that module, and the
module has any non-constant exports:
```
error - [analysis] /turbopack/crates/turbopack-tests/tests/snapshot/comptime/cross-module/input/other.constants.js:8:7 
Export NO_CONSTANT is not a constant
  
       4 | const development_ent = 'development'
       5 | 
       6 | export const IS_DEV = node_env === development_ent
       7 | 
         +        v--------------------------------v
       8 + export const NO_CONSTANT = globalThis.foo
         +        ^--------------------------------^
       9 | 
  
  It was analyzed to be FreeVar(globalThis)["foo"]
  
  
  Import trace:
    test:
      ./turbopack/crates/turbopack-tests/tests/snapshot/comptime/cross-module/input/other.constants.js
      ./turbopack/crates/turbopack-tests/tests/snapshot/comptime/cross-module/input/index.js
```

Some prior art:
https://rspack.rs/blog/announcing-1-5#const-inline-optimization,
https://rspack.rs/config/optimization#optimizationinlineexports

No compile-time impact on a big app:
```
canary dfbc3dc: 
438.11s user, 68.35s system, 801% cpu, 1:03.22 total
439.44s user, 71.47s system, 756% cpu, 1:07.56 total
440.32s user, 68.57s system, 750% cpu, 1:07.81 total

constants 2d7eb82
433.22s user, 65.44s system, 800% cpu, 1:02.32 total
440.52s user, 67.68s system, 770% cpu, 1:05.95 total
433.13s user, 69.47s system, 776% cpu, 1:04.74 total
```

a8620556af64ef550373cca1e1fc701a1a8583cc
@pull pull Bot locked and limited conversation to collaborators Aug 19, 2026
@pull pull Bot added the ⤵️ pull label Aug 19, 2026
@pull
pull Bot merged commit 8c23ca9 into code:canary Aug 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants