Skip to content

offline navigations: generate fallback document artifacts (2/10)#93737

Draft
feedthejim wants to merge 1 commit intofeedthejim/offline-navigations-flag-canaryfrom
feedthejim/offline-navigations-manifest
Draft

offline navigations: generate fallback document artifacts (2/10)#93737
feedthejim wants to merge 1 commit intofeedthejim/offline-navigations-flag-canaryfrom
feedthejim/offline-navigations-manifest

Conversation

@feedthejim
Copy link
Copy Markdown
Contributor

@feedthejim feedthejim commented May 10, 2026

Stack Position

This is PR 2 of 10. It is the build-output slice for the fallback HTML document.

Review guide:
https://gist.github.com/feedthejim/a10f757cf07c5550f731adf2fcf1077b

Full Stack

  1. offline navigations: add gated build primitives (1/10) #93736 offline navigations: add gated build primitives (1/10)
  2. This PR: offline navigations: generate fallback document artifacts (2/10) #93737 offline navigations: generate fallback document artifacts (2/10)
  3. offline navigations: register pass-through worker (3/10) #93625 offline navigations: register pass-through worker (3/10)
  4. offline navigations: cache fallback and current-build assets (4/10) #93626 offline navigations: cache fallback and current-build assets (4/10)
  5. offline navigations: serve fallback document offline (5/10) #93627 offline navigations: serve fallback document offline (5/10)
  6. offline navigations: add router-cache persistence primitives (6/10) #93630 offline navigations: add router-cache persistence primitives (6/10)
  7. offline navigations: persist cached router records (7/10) #93640 offline navigations: persist cached router records (7/10)
  8. offline navigations: bootstrap fallback from router records (8/10) #93644 offline navigations: bootstrap fallback from router records (8/10)
  9. offline navigations: support dynamic route patterns (9/10) #93647 offline navigations: support dynamic route patterns (9/10)
  10. offline navigations: add docs and examples (10/10) #93738 offline navigations: add docs and examples (10/10)

What This Changes

This makes the build emit the fallback HTML document at the framework-managed offline navigation path. The document is intentionally small: it is a bootstrap entrypoint that later PRs can cache and serve when document requests fail.

The fallback document source is split into small render helpers for metadata scripts, bootstrap scripts, and final document assembly. The emitted HTML still stays minified. The empty document also shares the inline Flight bootstrap helper with the existing app-render inline Flight path, so the fallback shell does not hand-write a separate self.__next_f bootstrap string.

The slice also tightens the disabled-flag behavior so reviewers can see the build output contract before any client routing code lands.

What Works After This PR

With the flag enabled, the production build emits the fallback document. With the flag disabled, the build does not emit offline navigation artifacts.

What Does Not Work Yet

No service worker is registered yet, so the document is not cached or served at runtime. Soft and hard navigations to prefetched routes still behave normally online and still miss offline.

Reviewer Focus

Please focus on the fallback document path, the shared inline Flight bootstrap helper, disabled-build absence checks, and whether this is the minimum build output needed before the service worker and client router enter the stack.

Proof in This PR

The production suite asserts the emitted fallback document path, exact inline Flight bootstrap, disabled artifact absence, no route HTML in the fallback document, newline-free output, and the fallback HTML size budget:

  • HEADLESS=true pnpm test-start-turbo test/production/app-dir/offline-navigations/offline-navigations.test.ts
  • HEADLESS=true pnpm test-start-webpack test/production/app-dir/offline-navigations/offline-navigations.test.ts

Deferred Coverage

Service worker registration and caching are deferred to PRs 3 and 4. Offline document fallback serving is deferred to PR 5. Router-cache replay is deferred to PR 8.

Docs Status

The user-facing guide and config reference land in PR 10, after the runtime behavior exists.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 10, 2026

Tests Passed

Commit: 41d2265

@feedthejim feedthejim changed the title offline navigations: emit fallback manifest data (2/10) offline navigations: emit fallback manifest data (2/11) May 10, 2026
@feedthejim feedthejim force-pushed the feedthejim/offline-navigations-manifest branch from cef4b74 to 6345adc Compare May 10, 2026 20:21
@feedthejim feedthejim force-pushed the feedthejim/offline-navigations-flag-canary branch from d9404d4 to 2d875f9 Compare May 10, 2026 20:21
@github-actions
Copy link
Copy Markdown
Contributor

Stats from current PR

🔴 1 regression

Metric Canary PR Change Trend
node_modules Size 505 MB 505 MB 🔴 +84.2 kB (+0%) ▁▇▇▇█
📊 All Metrics
📖 Metrics Glossary

Dev Server Metrics:

  • Listen = TCP port starts accepting connections
  • First Request = HTTP server returns successful response
  • Cold = Fresh build (no cache)
  • Warm = With cached build artifacts

Build Metrics:

  • Fresh = Clean build (no .next directory)
  • Cached = With existing .next directory

Change Thresholds:

  • Time: Changes < 50ms AND < 10%, OR < 2% are insignificant
  • Size: Changes < 1KB AND < 1% are insignificant
  • All other changes are flagged to catch regressions

⚡ Dev Server

Metric Canary PR Change Trend
Cold (Listen) 811ms 810ms ███▁█
Cold (Ready in log) 785ms 785ms ▇▇▇▁█
Cold (First Request) 1.218s 1.224s ▅▆▃▂▅
Warm (Listen) 811ms 809ms ▃█▁█▅
Warm (Ready in log) 783ms 784ms ▃▂▃█▇
Warm (First Request) 599ms 602ms ▄▃▃██
📦 Dev Server (Webpack) (Legacy)

📦 Dev Server (Webpack)

Metric Canary PR Change Trend
Cold (Listen) 812ms 811ms █████
Cold (Ready in log) 775ms 776ms █▇▇▆▇
Cold (First Request) 3.210s 3.237s █▆▄▄▅
Warm (Listen) 812ms 810ms █████
Warm (Ready in log) 778ms 776ms █▇▆▆▆
Warm (First Request) 3.236s 3.237s █▄▄▃▃

⚡ Production Builds

Metric Canary PR Change Trend
Fresh Build 4.664s 4.709s ▅█▄▅▄
Cached Build 4.671s 4.709s ▄█▅▃▆
📦 Production Builds (Webpack) (Legacy)

📦 Production Builds (Webpack)

Metric Canary PR Change Trend
Fresh Build 24.128s 24.114s ██▅▂▆
Cached Build 24.136s 24.260s █▆▄▁▆
node_modules Size 505 MB 505 MB 🔴 +84.2 kB (+0%) ▁▇▇▇█
📦 Bundle Sizes

Bundle Sizes

⚡ Turbopack

Client

Main Bundles
Canary PR Change
0-uf63qh441ym.js gzip 65.5 kB N/A -
02_eu35th8xp1.js gzip 161 B N/A -
04hm05ar7kldw.js gzip 5.73 kB N/A -
0cz1d0mv5g_q7.js gzip 39.4 kB 39.4 kB
0dvitrl5zg37g.js gzip 8.82 kB N/A -
0jnyo43x8vdm1.js gzip 167 B N/A -
0nqh1n0j6mmm9.js gzip 49.5 kB N/A -
0sf7ysou-72zd.js gzip 8.71 kB N/A -
0yh-uay5ufmjc.js gzip 70.8 kB N/A -
157abun3hwc_s.js gzip 10.3 kB N/A -
17rz06bb4qf0q.js gzip 156 B N/A -
1elt1qium-r2m.css gzip 115 B 115 B
1gegnjx8b94t8.js gzip 156 B N/A -
1jj68jv9537mc.js gzip 13.8 kB N/A -
1jpaub6y8xlfr.js gzip 2.3 kB N/A -
1k4uph64t2cnr.js gzip 154 B N/A -
1mqf_oa8flo6h.js gzip 155 B N/A -
1ot0mvscrc_uf.js gzip 233 B N/A -
1ua4pgvcras7v.js gzip 157 B N/A -
1uxu6kee53sh_.js gzip 160 B N/A -
1yrhtrozledc8.js gzip 157 B N/A -
2_m3xv2uq3sjc.js gzip 1.46 kB N/A -
2-25idef4_4k4.js gzip 154 B N/A -
24y34mwgrkqp4.js gzip 8.78 kB N/A -
2c-fd4y1zozz8.js gzip 8.79 kB N/A -
2d7416h_xd36x.js gzip 8.71 kB N/A -
2extn3odmmem_.js gzip 12.9 kB N/A -
2fyhyy7niw9r6.js gzip 7.61 kB N/A -
2jp7mexj-ffhj.js gzip 155 B N/A -
2kjre_jvvxym-.js gzip 155 B N/A -
2lyuhit6rn8fy.js gzip 9.44 kB N/A -
2q0gr8wfr3jwl.js gzip 8.77 kB N/A -
2t9e75oz6r0zp.js gzip 8.76 kB N/A -
2uku_olcn15b7.js gzip 8.79 kB N/A -
30r8mm-46bdqy.js gzip 220 B 220 B
3cgkrmk_s_wpq.js gzip 156 B N/A -
3inab2jybr4k9.js gzip 450 B N/A -
3jkm5tdjvaf_q.js gzip 13.1 kB N/A -
3mt67agm5wp40.js gzip 10.6 kB N/A -
3saabek4kohwi.js gzip 10 kB N/A -
4189xmby9yu1p.js gzip 13.6 kB N/A -
turbopack-0e..eglm.js gzip 4.2 kB N/A -
turbopack-0g..c3gx.js gzip 4.2 kB N/A -
turbopack-0t..khtt.js gzip 4.2 kB N/A -
turbopack-12..ub3i.js gzip 4.21 kB N/A -
turbopack-13..n0-u.js gzip 4.2 kB N/A -
turbopack-1c..yqmk.js gzip 4.2 kB N/A -
turbopack-1k..3xbn.js gzip 4.2 kB N/A -
turbopack-1k..kwc3.js gzip 4.2 kB N/A -
turbopack-1o..ge4m.js gzip 4.18 kB N/A -
turbopack-1x..r-ki.js gzip 4.2 kB N/A -
turbopack-3_..svfh.js gzip 4.2 kB N/A -
turbopack-39..jio1.js gzip 4.2 kB N/A -
turbopack-3v..vys8.js gzip 4.2 kB N/A -
turbopack-3v..vyke.js gzip 4.2 kB N/A -
0_i7nqgx23st7.js gzip N/A 10 kB -
05e40c15cx1dd.js gzip N/A 7.61 kB -
06puhytyxk31p.js gzip N/A 8.82 kB -
0fca20ykv8h6s.js gzip N/A 155 B -
0m34gln_kt4fg.js gzip N/A 5.73 kB -
1_ekw0s2no-u6.js gzip N/A 153 B -
1b3r4o2n_avk6.js gzip N/A 155 B -
1bxqv8k7jvem-.js gzip N/A 159 B -
1g3q1ww01thnl.js gzip N/A 2.3 kB -
1hraqxuiymq6v.js gzip N/A 8.79 kB -
1ijznya56sya4.js gzip N/A 153 B -
1l9un1sl77287.js gzip N/A 1.46 kB -
1n-atmavce2tf.js gzip N/A 158 B -
1n4b65wcm1qu2.js gzip N/A 157 B -
1v4dom7n1w8nm.js gzip N/A 156 B -
21-eavqb1k_36.js gzip N/A 13.9 kB -
2147zgtf14z-q.js gzip N/A 234 B -
23bz3xsg-5-1s.js gzip N/A 8.71 kB -
27441mytv7pbm.js gzip N/A 9.43 kB -
2cjkwjgm1zcfs.js gzip N/A 8.71 kB -
2d58c6s3nmhua.js gzip N/A 156 B -
2scd8zaoyb8md.js gzip N/A 8.79 kB -
2st_qs6p_9us0.js gzip N/A 13.1 kB -
2zo2exm1d8qj1.js gzip N/A 13.6 kB -
3-sxo0xac1vlg.js gzip N/A 149 B -
31d304nyh0qnr.js gzip N/A 49.5 kB -
32fzho7lv-v6e.js gzip N/A 153 B -
352tr8j0win8e.js gzip N/A 168 B -
3hn75zuxly9az.js gzip N/A 10.3 kB -
3hqh7m128tvsn.js gzip N/A 8.77 kB -
3hqti_t-zy1x4.js gzip N/A 449 B -
3jz6mmnclh250.js gzip N/A 70.8 kB -
3mnawenie1flm.js gzip N/A 8.76 kB -
3r2a97foojskq.js gzip N/A 155 B -
3ubsozlu6zs38.js gzip N/A 10.6 kB -
41mf-x3mmsxae.js gzip N/A 12.9 kB -
42thqoo1bcm89.js gzip N/A 65.6 kB -
43iwfqjnx1cy_.js gzip N/A 8.78 kB -
turbopack-01..3l6a.js gzip N/A 4.2 kB -
turbopack-0d..yy8u.js gzip N/A 4.2 kB -
turbopack-0g..0hjy.js gzip N/A 4.2 kB -
turbopack-0v..4p4w.js gzip N/A 4.2 kB -
turbopack-0w..ixcj.js gzip N/A 4.2 kB -
turbopack-1g..6nwq.js gzip N/A 4.2 kB -
turbopack-1s..6f82.js gzip N/A 4.2 kB -
turbopack-1x..l758.js gzip N/A 4.18 kB -
turbopack-26..jr44.js gzip N/A 4.2 kB -
turbopack-2f..a86d.js gzip N/A 4.2 kB -
turbopack-2v..9fvd.js gzip N/A 4.2 kB -
turbopack-2x.._yqu.js gzip N/A 4.2 kB -
turbopack-31..b94z.js gzip N/A 4.21 kB -
turbopack-3k..lomm.js gzip N/A 4.2 kB -
Total 468 kB 468 kB ⚠️ +8 B

Server

Middleware
Canary PR Change
middleware-b..fest.js gzip 717 B 716 B
Total 717 B 716 B ✅ -1 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 433 B 432 B
Total 433 B 432 B ✅ -1 B

📦 Webpack

Client

Main Bundles
Canary PR Change
2258-HASH.js gzip 61.1 kB N/A -
2266-HASH.js gzip 4.69 kB N/A -
3317.HASH.js gzip 169 B N/A -
4866-HASH.js gzip 5.64 kB N/A -
9e302639-HASH.js gzip 62.7 kB N/A -
framework-HASH.js gzip 59.5 kB 59.5 kB
main-app-HASH.js gzip 255 B 255 B
main-HASH.js gzip 39.9 kB 39.9 kB
webpack-HASH.js gzip 1.68 kB 1.68 kB
175fd0fd-HASH.js gzip N/A 62.7 kB -
2596-HASH.js gzip N/A 5.63 kB -
34-HASH.js gzip N/A 61 kB -
5691.HASH.js gzip N/A 169 B -
9156-HASH.js gzip N/A 4.68 kB -
Total 236 kB 236 kB ✅ -81 B
Polyfills
Canary PR Change
polyfills-HASH.js gzip 39.4 kB 39.4 kB
Total 39.4 kB 39.4 kB
Pages
Canary PR Change
_app-HASH.js gzip 193 B 193 B
_error-HASH.js gzip 181 B 182 B
css-HASH.js gzip 334 B 332 B
dynamic-HASH.js gzip 1.79 kB 1.81 kB
edge-ssr-HASH.js gzip 255 B 255 B
head-HASH.js gzip 351 B 348 B
hooks-HASH.js gzip 385 B 384 B
image-HASH.js gzip 580 B 580 B
index-HASH.js gzip 257 B 259 B
link-HASH.js gzip 2.51 kB 2.52 kB
routerDirect..HASH.js gzip 318 B 319 B
script-HASH.js gzip 387 B 386 B
withRouter-HASH.js gzip 316 B 316 B
1afbb74e6ecf..834.css gzip 106 B 106 B
Total 7.97 kB 7.99 kB ⚠️ +19 B

Server

Edge SSR
Canary PR Change
edge-ssr.js gzip 126 kB 126 kB
page.js gzip 275 kB 270 kB 🟢 5.25 kB (-2%)
Total 401 kB 396 kB ✅ -5.47 kB
Middleware
Canary PR Change
middleware-b..fest.js gzip 616 B 615 B
middleware-r..fest.js gzip 155 B 155 B
middleware.js gzip 44.7 kB 44.5 kB
edge-runtime..pack.js gzip 842 B 842 B
Total 46.3 kB 46.1 kB ✅ -196 B
Build Details
Build Manifests
Canary PR Change
_buildManifest.js gzip 719 B 717 B
Total 719 B 717 B ✅ -2 B
Build Cache
Canary PR Change
0.pack gzip 4.46 MB 4.45 MB 🟢 5.74 kB (0%)
index.pack gzip 114 kB 114 kB
index.pack.old gzip 114 kB 114 kB
Total 4.68 MB 4.68 MB ✅ -6.17 kB

🔄 Shared (bundler-independent)

Runtimes
Canary PR Change
app-page-exp...dev.js gzip 350 kB 350 kB
app-page-exp..prod.js gzip 194 kB 194 kB
app-page-tur...dev.js gzip 349 kB 349 kB
app-page-tur..prod.js gzip 194 kB 194 kB
app-page-tur...dev.js gzip 346 kB 346 kB
app-page-tur..prod.js gzip 192 kB 192 kB
app-page.run...dev.js gzip 346 kB 346 kB
app-page.run..prod.js gzip 192 kB 192 kB
app-route-ex...dev.js gzip 77.5 kB 77.5 kB
app-route-ex..prod.js gzip 52.9 kB 52.9 kB
app-route-tu...dev.js gzip 77.6 kB 77.6 kB
app-route-tu..prod.js gzip 52.9 kB 52.9 kB
app-route-tu...dev.js gzip 77.2 kB 77.2 kB
app-route-tu..prod.js gzip 52.7 kB 52.7 kB
app-route.ru...dev.js gzip 77.1 kB 77.1 kB
app-route.ru..prod.js gzip 52.7 kB 52.7 kB
dist_client_...dev.js gzip 324 B 324 B
dist_client_...dev.js gzip 326 B 326 B
dist_client_...dev.js gzip 318 B 318 B
dist_client_...dev.js gzip 317 B 317 B
pages-api-tu...dev.js gzip 44.3 kB 44.3 kB
pages-api-tu..prod.js gzip 33.8 kB 33.8 kB
pages-api.ru...dev.js gzip 44.3 kB 44.3 kB
pages-api.ru..prod.js gzip 33.7 kB 33.7 kB
pages-turbo....dev.js gzip 53.7 kB 53.7 kB
pages-turbo...prod.js gzip 39.4 kB 39.4 kB
pages.runtim...dev.js gzip 53.6 kB 53.6 kB
pages.runtim..prod.js gzip 39.3 kB 39.3 kB
server.runti..prod.js gzip 63.2 kB 63.2 kB
use-cache-pr...dev.js gzip 69.7 kB 69.7 kB
use-cache-pr...dev.js gzip 69.7 kB 69.7 kB
use-cache-pr...dev.js gzip 68 kB 68 kB
use-cache-pr...dev.js gzip 68 kB 68 kB
Total 3.36 MB 3.36 MB ⚠️ +5 B
📝 Changed Files (3 files)

Files with changes:

  • pages-api.ru..time.prod.js
  • pages.runtime.prod.js
  • server.runtime.prod.js
View diffs
pages-api.ru..time.prod.js

Diff too large to display

pages.runtime.prod.js

Diff too large to display

server.runtime.prod.js

Diff too large to display

📎 Tarball URL
https://vercel-packages.vercel.app/next/commits/6345adc1dd08a0b9050117976073871a35117dad/next

Commit: 6345adc

@feedthejim feedthejim force-pushed the feedthejim/offline-navigations-flag-canary branch from 2d875f9 to a30807a Compare May 10, 2026 23:28
@feedthejim feedthejim force-pushed the feedthejim/offline-navigations-manifest branch from 6345adc to 865d623 Compare May 10, 2026 23:28
@feedthejim feedthejim changed the title offline navigations: emit fallback manifest data (2/11) offline navigations: generate fallback document artifacts (2/10) May 10, 2026
@feedthejim feedthejim force-pushed the feedthejim/offline-navigations-manifest branch from 865d623 to 41d2265 Compare May 11, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant