Skip to content

Commit 766b7cb

Browse files
authored
Stabilize unstable_io (vercel#93621)
Removes the unstable prefix from `unstable_io`. Since this was only shipped in canaries with the unstable prefix we are going to just remove it without retaining the unstable prefix simultaneously.
1 parent 3009937 commit 766b7cb

26 files changed

Lines changed: 100 additions & 100 deletions

File tree

docs/01-app/03-api-reference/04-functions/unstable_io.mdx renamed to docs/01-app/03-api-reference/04-functions/io.mdx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
---
2-
title: unstable_io
3-
description: API Reference for the unstable_io function.
2+
title: io
3+
description: API Reference for the io function.
44
version: draft
55
---
66

7-
`unstable_io()` informs Next.js that an IO operation will follow this call. When [Cache Components](/docs/app/api-reference/config/next-config-js/cacheComponents) is not enabled or when rendering in Pages Router, signifying IO in this way is not meaningful and the call will always resolve immediately. When Cache Components is enabled, you may be required to add `await unstable_io()` preceding synchronous IO that is encountered while prerendering pages (`new Date()` for example). Additionally, if you want to avoid having genuine uncached IO invoked while prerendering, you shield it by preceeding it with `await unstable_io()`.
7+
`io()` informs Next.js that an IO operation will follow this call. When [Cache Components](/docs/app/api-reference/config/next-config-js/cacheComponents) is not enabled or when rendering in Pages Router, signifying IO in this way is not meaningful and the call will always resolve immediately. When Cache Components is enabled, you may be required to add `await io()` preceding synchronous IO that is encountered while prerendering pages (`new Date()` for example). Additionally, if you want to avoid having genuine uncached IO invoked while prerendering, you shield it by preceeding it with `await io()`.
88

99
```ts filename="app/page.tsx" switcher
10-
import { unstable_io } from 'next/cache'
10+
import { io } from 'next/cache'
1111
import { db } from '@/lib/db'
1212

1313
export default async function Page() {
1414
// Synchronous IO: new Date() would fail during prerender without this
15-
await unstable_io()
15+
await io()
1616
const now = new Date().toISOString()
1717

1818
// Async IO: the query would run and be discarded during prerender;
19-
// unstable_io() above lets Next.js skip it entirely
19+
// io() above lets Next.js skip it entirely
2020
const orders = await db.query('SELECT * FROM orders LIMIT 10')
2121

2222
return (
@@ -33,16 +33,16 @@ export default async function Page() {
3333
```
3434

3535
```js filename="app/page.js" switcher
36-
import { unstable_io } from 'next/cache'
36+
import { io } from 'next/cache'
3737
import { db } from '@/lib/db'
3838

3939
export default async function Page() {
4040
// Synchronous IO: new Date() would fail during prerender without this
41-
await unstable_io()
41+
await io()
4242
const now = new Date().toISOString()
4343

4444
// Async IO: the query would run and be discarded during prerender;
45-
// unstable_io() above lets Next.js skip it entirely
45+
// io() above lets Next.js skip it entirely
4646
const orders = await db.query('SELECT * FROM orders LIMIT 10')
4747

4848
return (
@@ -62,16 +62,16 @@ export default async function Page() {
6262

6363
[`connection()`](/docs/app/api-reference/functions/connection) requires an active HTTP request context and signals that the component needs request-specific data. It is imported from `next/server`.
6464

65-
`unstable_io()` does not require a request context. It can be used inside `"use cache"` scopes, client components, and anywhere you perform IO that should not be included in a static prerender. It is imported from `next/cache`.
65+
`io()` does not require a request context. It can be used inside `"use cache"` scopes, client components, and anywhere you perform IO that should not be included in a static prerender. It is imported from `next/cache`.
6666

67-
Use `connection()` when you need the request itself (cookies, headers, etc.). Use `unstable_io()` when you perform IO that is independent of the request but should still prevent static prerendering.
67+
Use `connection()` when you need the request itself (cookies, headers, etc.). Use `io()` when you perform IO that is independent of the request but should still prevent static prerendering.
6868

6969
## Reference
7070

7171
### Type
7272

7373
```ts
74-
function unstable_io(): Promise<void>
74+
function io(): Promise<void>
7575
```
7676

7777
### Parameters
@@ -84,12 +84,12 @@ function unstable_io(): Promise<void>
8484

8585
## Good to know
8686

87-
- `unstable_io()` is imported from `next/cache`, not `next/server`.
88-
- Inside `"use cache"` scopes, `unstable_io()` resolves immediately. The cache captures the IO result at fill time.
89-
- In client components, `unstable_io()` resolves immediately since there is no prerender context in the browser.
87+
- `io()` is imported from `next/cache`, not `next/server`.
88+
- Inside `"use cache"` scopes, `io()` resolves immediately. The cache captures the IO result at fill time.
89+
- In client components, `io()` resolves immediately since there is no prerender context in the browser.
9090

9191
### Version History
9292

93-
| Version | Changes |
94-
| --------- | -------------------- |
95-
| `v16.x.x` | `unstable_io` added. |
93+
| Version | Changes |
94+
| --------- | ----------- |
95+
| `v16.x.x` | `io` added. |

packages/next/cache.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export {
99

1010
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
1111

12-
export { unstable_io } from 'next/dist/server/request/io'
12+
export { io } from 'next/dist/server/request/io'
1313

1414
import { cacheTag } from 'next/dist/server/use-cache/cache-tag'
1515

packages/next/cache.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ if (process.env.NEXT_RUNTIME === '') {
1717
}
1818
},
1919
unstable_noStore: function unstable_noStore() {},
20-
unstable_io: require('next/dist/client/request/io.browser').unstable_io,
20+
io: require('next/dist/client/request/io.browser').io,
2121

2222
updateTag: notAvailableInClient('updateTag'),
2323
revalidateTag: notAvailableInClient('revalidateTag'),
@@ -46,7 +46,7 @@ if (process.env.NEXT_RUNTIME === '') {
4646
unstable_noStore:
4747
require('next/dist/server/web/spec-extension/unstable-no-store')
4848
.unstable_noStore,
49-
unstable_io: require('next/dist/server/request/io').unstable_io,
49+
io: require('next/dist/server/request/io').io,
5050
cacheLife: require('next/dist/server/use-cache/cache-life').cacheLife,
5151
cacheTag: require('next/dist/server/use-cache/cache-tag').cacheTag,
5252
}
@@ -94,4 +94,4 @@ exports.unstable_cacheLife = cacheExports.unstable_cacheLife
9494
exports.cacheTag = cacheExports.cacheTag
9595
exports.unstable_cacheTag = cacheExports.unstable_cacheTag
9696
exports.refresh = cacheExports.refresh
97-
exports.unstable_io = cacheExports.unstable_io
97+
exports.io = cacheExports.io

packages/next/src/client/request/io.browser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ const resolvedIOPromise: Promise<void> = Promise.resolve(undefined)
55
;(resolvedIOPromise as any).value = undefined
66

77
/**
8-
* Browser implementation of unstable_io(). On the client there is no
8+
* Browser implementation of io(). On the client there is no
99
* prerender context so we always resolve immediately.
1010
*/
11-
export function unstable_io(): Promise<void> {
11+
export function io(): Promise<void> {
1212
return resolvedIOPromise
1313
}

packages/next/src/server/lib/router-utils/cache-life-type-utils.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ describe('cache-life-type-utils', () => {
2929
refresh,
3030
} from 'next/dist/server/web/spec-extension/revalidate'
3131
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
32-
export { unstable_io } from 'next/dist/server/request/io'
32+
export { io } from 'next/dist/server/request/io'
3333
3434
3535
/**
@@ -187,7 +187,7 @@ describe('cache-life-type-utils', () => {
187187
refresh,
188188
} from 'next/dist/server/web/spec-extension/revalidate'
189189
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
190-
export { unstable_io } from 'next/dist/server/request/io'
190+
export { io } from 'next/dist/server/request/io'
191191
192192
193193
/**
@@ -265,7 +265,7 @@ describe('cache-life-type-utils', () => {
265265
refresh,
266266
} from 'next/dist/server/web/spec-extension/revalidate'
267267
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
268-
export { unstable_io } from 'next/dist/server/request/io'
268+
export { io } from 'next/dist/server/request/io'
269269
270270
271271
/**
@@ -342,7 +342,7 @@ describe('cache-life-type-utils', () => {
342342
refresh,
343343
} from 'next/dist/server/web/spec-extension/revalidate'
344344
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
345-
export { unstable_io } from 'next/dist/server/request/io'
345+
export { io } from 'next/dist/server/request/io'
346346
347347
348348
/**
@@ -420,7 +420,7 @@ describe('cache-life-type-utils', () => {
420420
refresh,
421421
} from 'next/dist/server/web/spec-extension/revalidate'
422422
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
423-
export { unstable_io } from 'next/dist/server/request/io'
423+
export { io } from 'next/dist/server/request/io'
424424
425425
426426
/**
@@ -502,7 +502,7 @@ describe('cache-life-type-utils', () => {
502502
refresh,
503503
} from 'next/dist/server/web/spec-extension/revalidate'
504504
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
505-
export { unstable_io } from 'next/dist/server/request/io'
505+
export { io } from 'next/dist/server/request/io'
506506
507507
508508
/**

packages/next/src/server/lib/router-utils/cache-life-type-utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ declare module 'next/cache' {
177177
refresh,
178178
} from 'next/dist/server/web/spec-extension/revalidate'
179179
export { unstable_noStore } from 'next/dist/server/web/spec-extension/unstable-no-store'
180-
export { unstable_io } from 'next/dist/server/request/io'
180+
export { io } from 'next/dist/server/request/io'
181181
182182
${overloads}
183183

packages/next/src/server/request/io.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ const resolvedIOPromise: Promise<void> = Promise.resolve(undefined)
2121
* point, creating a dynamic boundary. Inside `"use cache"` scopes or during
2222
* a real request it resolves immediately.
2323
*
24-
* Unlike `connection()`, `unstable_io()` does not require an actual HTTP
25-
* request and can be used freely inside cache scopes and client components.
24+
* Unlike `connection()`, `io()` does not require an actual HTTP request and
25+
* can be used freely inside cache scopes and client components.
2626
*/
27-
export function unstable_io(): Promise<void> {
27+
export function io(): Promise<void> {
2828
const workStore = workAsyncStorage.getStore()
2929
const workUnitStore = workUnitAsyncStorage.getStore()
3030

@@ -59,7 +59,7 @@ export function unstable_io(): Promise<void> {
5959
return makeHangingPromise(
6060
workUnitStore.renderSignal,
6161
workStore.route,
62-
'`unstable_io()`'
62+
'`io()`'
6363
)
6464
case 'prerender-ppr':
6565
// Dead code to be removed when we eliminate legacy ppr code
@@ -68,7 +68,7 @@ export function unstable_io(): Promise<void> {
6868
case 'cache':
6969
case 'private-cache':
7070
case 'unstable-cache':
71-
// Inside cache scopes, unstable_io() resolves immediately.
71+
// Inside cache scopes, io() resolves immediately.
7272
// Caches can contain IO-dependent code like new Date() — it will
7373
// simply return the value at cache-fill time.
7474
// ...
@@ -79,7 +79,7 @@ export function unstable_io(): Promise<void> {
7979
// ...
8080
// intentional fallthrough
8181
case 'validation-client':
82-
// unstable_io() is usable in client components, resolve immediately.
82+
// io() is usable in client components, resolve immediately.
8383
// The reason we take this position is most io shielding you would do
8484
// in a browser is for sync IO as there aren't many non-fetch based IO
8585
// operations you can do in the browser that have meaningful latency.

test/cache-components-tests-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@
373373
"test/production/app-dir/resume-data-cache/resume-data-cache.test.ts",
374374
"test/production/app-dir/unstable-cache-foreground-revalidate/unstable-cache-foreground-revalidate.test.ts",
375375
"test/e2e/app-dir/parallel-routes-root-param-dynamic-child/parallel-routes-root-param-dynamic-child.test.ts",
376-
"test/e2e/app-dir/unstable-io/unstable-io.test.ts"
376+
"test/e2e/app-dir/io/io.test.ts"
377377
]
378378
}
379379
}

test/e2e/app-dir/unstable-io/fixtures/cache-components/app/getSentinelValue.tsx renamed to test/e2e/app-dir/io/fixtures/cache-components/app/getSentinelValue.tsx

File renamed without changes.

test/e2e/app-dir/unstable-io/fixtures/default/app/io-boundary/page.tsx renamed to test/e2e/app-dir/io/fixtures/cache-components/app/io-boundary/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { Suspense } from 'react'
2-
import { unstable_io } from 'next/cache'
2+
import { io } from 'next/cache'
33
import { getSentinelValue } from '../getSentinelValue'
44

55
export default function Page() {
66
return (
77
<>
88
<p>
9-
This page uses unstable_io() inside a Suspense boundary. Without cache
10-
components unstable_io() is a no-op during prerendering so the entire
11-
page should be fully static.
9+
This page uses io() inside a Suspense boundary. With cache components
10+
the content after io() should be dynamic and rendered at request time,
11+
not during the build prerender.
1212
</p>
1313
<div id="before">{getSentinelValue()}</div>
1414
<Suspense fallback={<div id="fallback">loading...</div>}>
@@ -20,6 +20,6 @@ export default function Page() {
2020
}
2121

2222
async function DynamicComponent() {
23-
await unstable_io()
23+
await io()
2424
return <div id="after-io">{getSentinelValue()}</div>
2525
}

0 commit comments

Comments
 (0)