[GH-ISSUE #701] Add experimental.useOffline — offline detection, retry, and useOffline() hook #150

Closed
opened 2026-05-06 12:37:39 +02:00 by BreizhHardware · 0 comments

Originally created by @github-actions[bot] on GitHub (Mar 28, 2026).
Original GitHub issue: https://github.com/cloudflare/vinext/issues/701

Upstream

Summary

Next.js added a new experimental.useOffline flag that provides two capabilities:

1. Offline retry for navigations, server actions, and prefetches

When a fetch() rejects due to a network error (not abort/timeout), the request blocks until connectivity is restored and then retries automatically, instead of falling back to MPA navigation or surfacing an error.

  • New packages/next/src/client/components/offline.ts module owns all offline state: detection, polling with exponential backoff (500ms → 1s → 2s → 3s cap), and connectivity checks via HEAD requests.
  • fetchServerResponse (navigation) catches network errors, calls checkOfflineError()waitForConnection() → retries.
  • fetchServerAction (server actions) does the same — safe to replay because the rejection means the request never reached the server.
  • Browser offline/online events feed into the polling loop. Successful fetches from any code path short-circuit via notifyOnline().
  • Gated behind process.env.__NEXT_USE_OFFLINE with lazy require() calls.

2. useOffline() hook via next/offline

  • New next/offline export path (offline.js, offline.d.ts).
  • useOffline() hook returns true when offline, powered by OfflineProvider rendered inside the app router.
  • Uses useState + useOptimistic so value updates even during blocked transitions.
  • Module-level dispatchOfflineChange() bridges from the offline detection module into React state via startTransition.

Impact on vinext

  1. New shim needed: next/offline → export useOffline() hook. Needs to be added to the shim map in index.ts.
  2. Config flag: experimental.useOffline needs to be recognized if vinext processes next.config.
  3. Client-side router changes: The offline retry logic lives in the client router reducer layer. If vinext ships its own client-side navigation (vs. delegating to Next.js client code), this needs to be replicated. If vinext re-exports Next.js client components, this may come for free with the flag.
  4. OfflineProvider in app router tree: The provider wraps the router content — relevant if vinext constructs the app router React tree.
  5. Prefetch scheduler integration: notifyOnline() calls pingPrefetchScheduler() to resume prefetches after reconnection.

Suggested approach

Start with the shim for next/offline that exports a no-op useOffline() returning false. The full offline retry behavior is complex client-side router logic that can be deferred until the feature stabilizes (it's behind experimental).

Originally created by @github-actions[bot] on GitHub (Mar 28, 2026). Original GitHub issue: https://github.com/cloudflare/vinext/issues/701 ## Upstream - https://github.com/vercel/next.js/pull/92011 — offline retry behavior (`904501127c9ed2e0a7ffd51bd192537b7c398fb3`) - https://github.com/vercel/next.js/pull/92012 — `useOffline()` hook (`7bce97d6485599cab2964ef58fde8a55d19904d3`) ## Summary Next.js added a new `experimental.useOffline` flag that provides two capabilities: ### 1. Offline retry for navigations, server actions, and prefetches When a `fetch()` rejects due to a network error (not abort/timeout), the request blocks until connectivity is restored and then retries automatically, instead of falling back to MPA navigation or surfacing an error. - New `packages/next/src/client/components/offline.ts` module owns all offline state: detection, polling with exponential backoff (500ms → 1s → 2s → 3s cap), and connectivity checks via HEAD requests. - `fetchServerResponse` (navigation) catches network errors, calls `checkOfflineError()` → `waitForConnection()` → retries. - `fetchServerAction` (server actions) does the same — safe to replay because the rejection means the request never reached the server. - Browser `offline`/`online` events feed into the polling loop. Successful fetches from any code path short-circuit via `notifyOnline()`. - Gated behind `process.env.__NEXT_USE_OFFLINE` with lazy `require()` calls. ### 2. `useOffline()` hook via `next/offline` - New `next/offline` export path (`offline.js`, `offline.d.ts`). - `useOffline()` hook returns `true` when offline, powered by `OfflineProvider` rendered inside the app router. - Uses `useState` + `useOptimistic` so value updates even during blocked transitions. - Module-level `dispatchOfflineChange()` bridges from the offline detection module into React state via `startTransition`. ## Impact on vinext 1. **New shim needed:** `next/offline` → export `useOffline()` hook. Needs to be added to the shim map in `index.ts`. 2. **Config flag:** `experimental.useOffline` needs to be recognized if vinext processes next.config. 3. **Client-side router changes:** The offline retry logic lives in the client router reducer layer. If vinext ships its own client-side navigation (vs. delegating to Next.js client code), this needs to be replicated. If vinext re-exports Next.js client components, this may come for free with the flag. 4. **`OfflineProvider` in app router tree:** The provider wraps the router content — relevant if vinext constructs the app router React tree. 5. **Prefetch scheduler integration:** `notifyOnline()` calls `pingPrefetchScheduler()` to resume prefetches after reconnection. ## Suggested approach Start with the shim for `next/offline` that exports a no-op `useOffline()` returning `false`. The full offline retry behavior is complex client-side router logic that can be deferred until the feature stabilizes (it's behind `experimental`).
BreizhHardware 2026-05-06 12:37:39 +02:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/vinext#150
No description provided.