diff --git a/ACCEPTANCE.md b/ACCEPTANCE.md index 66156d1..205d286 100644 --- a/ACCEPTANCE.md +++ b/ACCEPTANCE.md @@ -1179,6 +1179,66 @@ is **updated** to the `?v=` form, **not** removed. --- +## Bugfix: Initial-load module-graph waterfall (slow first data paint) + +The dashboard's first `/api/*` fetch is gated behind the **entire** 89-module +ES-module graph loading, and that graph was discovered one import-tier at a time +(`index.js` → `{config,main,settings}` → main's 33 imports → … ≈ 5 serial round +trips) because nothing told the browser the deeper modules up-front. On a real +connection each tier costs a full RTT, so data did not paint for **2–3 s** +(measured: ~3.7 s to the first `/api/nodes` request at 150 ms RTT / 4× CPU; the +server itself answers every endpoint in <250 ms). The fix emits one +`` per served app ES module in `` — the **same +set the AV3 import map versions** — so the whole graph downloads in parallel +(one round trip over HTTP/2) instead of tier-by-tier. Native browser feature, no +build step or dependency (D7/AV4); read-side only (apex/privacy/parity untouched); +a module absent from the preloads still loads normally (AV3's degradation +property). Built by `PotatoMesh::App::AssetImportMap.preload_html` +(`web/lib/potato_mesh/application/helpers/asset_helpers.rb`), rendered after the +import map in `views/layouts/app.erb`. + +*Run the server in public mode (as in AV-A1) and leave it running for the curl check.* + +### MP-A1 — The head preloads the whole app ES-module graph (busted URLs) +```bash +curl -s http://127.0.0.1:41447/ \ + | grep -oE '' \ + | grep -E 'app/(index|main)\.js' +``` +**Expected:** matches a `` for both the entry point +`index.js` and the transitively-imported `main.js`, each carrying the +`?v=` query — i.e. the preloaded URL equals the import-map **target**, +so the preload and the eventual `import` resolve to the same cache entry. Every +served `/assets/js/app/**` module is preloaded; the classic non-module scripts +(`/assets/js/theme.js`, `/assets/js/background.js`) and `__tests__` files are +**not** preloaded. + +### MP-A2 — Preloads sit after the import map, before the module entry; unit-tested +```bash +( cd web && bundle exec rspec spec/asset_versioning_spec.rb -e "modulepreload" \ + spec/asset_import_map_spec.rb -e "preload" ) +``` +**Expected:** pass. The rendering spec asserts the modulepreload block is emitted +**after** the ` + <%# Preload the whole ES-module graph in parallel so the browser fetches it in + one round trip instead of discovering it import-tier by import-tier; this + removes the waterfall that delayed the first /api data paint. Same set the + import map versions; emitted after it so module URLs resolve to the busted + targets. A module absent here still loads normally on demand. %> + <%= asset_modulepreload_tags %> " />