Summary
On Edge (and other third-party browsers) on iPhone, a fresh cold load shows a blank white screen ~50% of the time. The page is fully loaded and the JavaScript runs — the browser just never paints the content to the screen. Only a full reload clears it (scrolling, tapping, and rotating do not). Safari on the same device is unaffected.
This issue documents an extensive investigation (8 releases, v0.34.2-beta → v0.34.8-beta) that ruled out every web-reachable cause. The conclusion is that this is a render-process / compositing freeze in iOS-26 WKWebView (the engine all third-party iOS browsers are required to use), almost certainly a WebKit regression on a brand-new OS. It is paused pending a future iOS update; Safari is the workaround.
Environment
- Device: iPhone, iOS 26.5
- Browser: Microsoft Edge for iOS (
EdgiOS/148.0.3967.97), which runs on WKWebView (AppleWebKit/605.1.15, Version/26.0)
- Reproduced by: clearing all browsing data, then cold-loading the site repeatedly (~3–5 blanks per 7–9 loads).
- Safari on the same iOS 26 device does NOT reproduce it.
Decisive on-device diagnostic
A temporary on-screen probe (since removed) captured the page state on a blank/parked load:
bundleRan=true ← the JS bundle loaded and executed
readyState=complete ← document fully loaded
mapChildren=0
loadedTiles=0
hasConsent=false ← parked at the consent gate (expected — see note)
consentOverlay=393x661 ← on loads that DO paint, the overlay is in the DOM at full size
swController=no ← service worker NOT controlling the page
ua=…EdgiOS/148… iPhone OS 26_5 … AppleWebKit/605.1.15
Key facts established:
- The app is healthy.
bundleRan=true, readyState=complete, DOM present and correctly sized. Nothing is throwing.
- It's a whole-page paint failure, not any single element. On a blank load, neither the consent overlay nor the separate inline diagnostic overlay paints — two unrelated elements injected into
document.body, both invisible. Even appending a fresh full-screen element several seconds later does not paint.
- The service worker is not involved.
swController=no.
- It is undetectable from JavaScript. The Paint Timing API records a
first-contentful-paint entry even on frozen loads (the paint is computed but never composited to screen), so the page cannot detect its own freeze to auto-recover.
- Only a fresh navigation (reload) clears it — scroll / tap / rotate (which force relayout+repaint) do not, indicating the freeze is below the layout/paint-trigger level (render/GPU process).
- Safari works; only WKWebView freezes — same WebKit engine, so the differentiator is WKWebView's render/GPU-process behavior, which is more fragile under first-load conditions on iOS 26.
Note on hasConsent=false: the soak workflow clears data each run and refreshes past blanks without accepting the consent modal, so nearly every test load sits at the consent gate. The freeze is independent of the consent modal (proven by the diagnostic overlay also failing to paint).
What was tried and ruled out
| Release |
PR |
Theory |
Result |
| (pre) |
#210 |
nginx served /sw.js with 1-year immutable cache → stale SW |
Real bug, fixed — but not the blank cause |
| v0.34.3-beta |
#213 |
Cache-first navigateFallback served empty navigations in WKWebView |
No effect |
| v0.34.4-beta |
#215 |
NetworkFirst networkTimeoutSeconds: 3 fell back to flaky cache |
No effect |
| v0.34.5-beta |
#217 |
Migrate generateSW→injectManifest: bulletproof nav (network→precache fallback) + SW-side error capture + purgeOnQuotaError |
No effect; SW-diag confirmed handler not even involved |
| v0.34.6-beta |
#219 |
Consent overlay injected during first paint; mount in requestAnimationFrame |
No effect (slightly worse: 5/9); reverted |
| v0.34.7-beta |
#221 |
Auto-reload via Paint Timing when no first-contentful-paint recorded |
Detector never fires — FCP is recorded despite the freeze |
| v0.34.8-beta |
#223 |
Strip first-paint compositing layers: remove #map { isolation: isolate } (full-screen composited layer) + lazy-inject #offline-banner (fixed+transform) |
No effect (~50% unchanged) |
Conclusion: the cause is not the service worker, not the consent modal, and not first-paint compositing pressure from app CSS. It is not auto-recoverable (JS cannot detect a compositing freeze) and not preventable by the levers available to web code.
Recommendation / next steps
- Treat as an upstream iOS-26 WKWebView (WebKit) regression. iOS 26 was released days before this investigation; render-process regressions on new OS releases are common and typically fixed in point updates.
- Workaround for users: use Safari (unaffected), or install the site to the Home Screen (runs in a system WebKit context with Safari-like behavior).
- Revisit when: a new iOS 26.x point release ships — re-test on the updated OS before spending more effort.
If revisiting and the freeze persists on a newer iOS, ideas not yet tried (all low-confidence):
- Test whether it reproduces in Chrome for iOS and a minimal/blank test page hosted on the same origin — to determine whether it's app-specific at all or any WKWebView page on this OS.
- A minimal reproduction (static HTML, no Vite/Leaflet) to file an Apple Feedback / WebKit bug with.
- Inline a non-white
<body> background so a freeze degrades to a branded screen rather than stark white (cosmetic only, not a fix).
- Check whether
display: standalone / the web app manifest or theme-color interacts with the freeze.
Related
Diagnostics that enabled this investigation: #206 (boot-watchdog), #207/#208 (on-screen blank-state reporter). The temporary diagnostics and the (exonerated) service-worker complexity are being removed in a separate clean-up PR; this issue preserves the full record.
Summary
On Edge (and other third-party browsers) on iPhone, a fresh cold load shows a blank white screen ~50% of the time. The page is fully loaded and the JavaScript runs — the browser just never paints the content to the screen. Only a full reload clears it (scrolling, tapping, and rotating do not). Safari on the same device is unaffected.
This issue documents an extensive investigation (8 releases, v0.34.2-beta → v0.34.8-beta) that ruled out every web-reachable cause. The conclusion is that this is a render-process / compositing freeze in iOS-26 WKWebView (the engine all third-party iOS browsers are required to use), almost certainly a WebKit regression on a brand-new OS. It is paused pending a future iOS update; Safari is the workaround.
Environment
EdgiOS/148.0.3967.97), which runs on WKWebView (AppleWebKit/605.1.15,Version/26.0)Decisive on-device diagnostic
A temporary on-screen probe (since removed) captured the page state on a blank/parked load:
Key facts established:
bundleRan=true,readyState=complete, DOM present and correctly sized. Nothing is throwing.document.body, both invisible. Even appending a fresh full-screen element several seconds later does not paint.swController=no.first-contentful-paintentry even on frozen loads (the paint is computed but never composited to screen), so the page cannot detect its own freeze to auto-recover.What was tried and ruled out
/sw.jswith 1-year immutable cache → stale SWnavigateFallbackserved empty navigations in WKWebViewnetworkTimeoutSeconds: 3fell back to flaky cachepurgeOnQuotaErrorrequestAnimationFramefirst-contentful-paintrecorded#map { isolation: isolate }(full-screen composited layer) + lazy-inject#offline-banner(fixed+transform)Conclusion: the cause is not the service worker, not the consent modal, and not first-paint compositing pressure from app CSS. It is not auto-recoverable (JS cannot detect a compositing freeze) and not preventable by the levers available to web code.
Recommendation / next steps
If revisiting and the freeze persists on a newer iOS, ideas not yet tried (all low-confidence):
<body>background so a freeze degrades to a branded screen rather than stark white (cosmetic only, not a fix).display: standalone/ the web app manifest ortheme-colorinteracts with the freeze.Related
Diagnostics that enabled this investigation: #206 (boot-watchdog), #207/#208 (on-screen blank-state reporter). The temporary diagnostics and the (exonerated) service-worker complexity are being removed in a separate clean-up PR; this issue preserves the full record.