Repository navigation
Windows (New Architecture): production feedback on the WebView2 implementation + offer of hardening PRs #3980
Description
We ship a production react-native-windows 0.83.2 New-Architecture app (Win32 composition, WinAppSDK 1.8, ARM64) with an independently-built WebView2 Fabric component that converged on exactly the architecture #3973 landed: WinUI 3 WebView2 → Microsoft.UI.Xaml.XamlIsland → ContentIsland → RNW ContentIslandComponentView.Connect(). It renders real web content in the field today, so first: the XamlIsland/ContentIsland approach in #3973 is solid — we can confirm first pixel, load events, postMessage round-trips, and teardown behavior (including the "orphaned island breaks window-wide input" trap your comment in RCTWebView2ComponentView.cpp also documents) on independent code.
Reading windows/ReactNativeWebView/RCTWebView2ComponentView.cpp against our production component, we found a handful of places where our implementation had to harden the same code paths, and we'd like to upstream them as a small PR series.
- No
onErrorwhen the WebView2 Runtime is missing.EnsureCoreWebView2Async()is called without an environment and without failure handling (InitializeContentIsland). On machines without the Evergreen Runtime (stripped/managed images, Server SKUs) the view stays blank with no JS-visible signal. We create the environment explicitly (CoreWebView2Environment::CreateWithOptionsAsync) with a writable, packaged-safe user-data folder, catch failures, and emitonLoadingErrorwith the HRESULT — both when environment creation itself throws (Runtime entirely missing) and viaCoreWebView2InitializedEventArgs.Exception()(failure after an environment was created). - Failed navigations emit
onLoadingFinish.OnNavigationCompleteddoesn't consultargs.IsSuccess()/WebErrorStatus(), so DNS failures, TLS errors, and offline states look like successful loads to JS. We branch and emitonLoadingErrorwith theCoreWebView2WebErrorStatusinstead. While in there:title(DocumentTitle()) already exists as a field on every nav-event struct in the codegen (RCTWebView2.g.h) but is never populated on Windows — we fill it in ononLoadingStart/onLoadingFinish/onLoadingError/onSourceChanged. - Bridge timing:
window.ReactNativeWebViewis injected post-load inNavigationCompleted; page scripts that run during load (a synchronous inline<script>in<head>, for example) can't see it, and theWebMessageReceivedhandler is re-registered on everyNavigationStarting. Registering the bridge once viaAddScriptToExecuteOnDocumentCreatedAsyncwhenCoreWebView2becomes available makes it exist before any page script runs on every subsequent navigation — and the same mechanism wires upinjectedJavaScriptBeforeContentLoaded, which already exists in the codegen'd prop spec but isn't read on Windows yet. javaScriptEnabledset before core-init is lost (applied inUpdatePropsonly whenCoreWebView2()already exists;OnCoreWebView2Initializedre-applies onlyuserAgentand pending HTML, neverjavaScriptEnabled).UpdatePropsre-navigates on unrelated prop changes. It receives the full current prop set on every call (not a diff), and unconditionally re-setsm_webView.Source(uri)/ callsNavigateToString(html)whenever a source is present — so toggling an unrelated prop likejavaScriptEnabledcan re-navigate/reload the page as a side effect. We diff againstoldProps(already a parameter, currently unused) before navigating.
We've opened a 4-PR series against master, each independently revertible, in roughly ascending order of size:
- WV-1 — item 1 (environment + init-error
onError) - WV-2 — item 2 (
IsSuccess()honored +titlein nav events) - WV-3 — item 3 (document-start bridge +
injectedJavaScriptBeforeContentLoaded) - WV-4 — item 4 + 5 (
javaScriptEnabledlifecycle + source-diffing)
All four are marked draft: we have not compiled them against this repo (no Windows build was run this pass — the changes are hand-verified by side-by-side reading against your RCTWebView2ComponentView.cpp, not by bun run windows), and each PR description says so explicitly. Every fix mirrors a code path already running in production in a parallel Windows new-arch WebView2 Fabric component — see FacilitronWorks/react-native-webview-windows — but that component uses renamed symbols and isn't a drop-in diff, so the PRs are hand-ported to your codegen/class shape, not copy-pasted.
Two questions before we go further:
- Any in-flight work post-feat(windows)!: New Architecture support + update all platforms to latest React Native #3973 that would collide (especially around environment creation or the
codegen_manualheaders)? - Preference on user-data-folder policy: fixed
ApplicationData.LocalFoldersubfolder (what we did), or a new prop/static setter so apps can share a profile with their own WebView2 environments?
Context for anyone landing here from search: for apps pinned to react-native-webview versions before Windows New Architecture support landed, we also maintain a small companion package with these fixes (FacilitronWorks/react-native-webview-windows) — the plan is to upstream everything above and retire it.
Activity
FaithfulAudio commentedon Jul 11, 2026
Opened the series:
onError): fix(windows): explicit CoreWebView2 environment + surface init failure to JS #3981IsSuccess()honored +titlein nav events): fix(windows): honor navigation success/failure + include title in nav events #3982injectedJavaScriptBeforeContentLoaded): fix(windows): register message bridge at document-start; support injectedJavaScriptBeforeContentLoaded #3983javaScriptEnabledlifecycle + source-diffing): fix(windows): fix javaScriptEnabled lost before core-init; stop re-navigating on unrelated prop changes #3984All four are draft — none compiled against this repo yet, each PR body says so explicitly. Each is based directly on
masterand independently revertible; happy to rebase/squash however you'd prefer if more than one lands.flawrist commentedon Jul 11, 2026
I don't know where to post this, since modern developers have changed the web beyond recognition, so I'm hoping someone can point me in the right direction.
This week (July 2026), I can no longer leave comments on Github which uses React. Some React module requires .toSorted method. It is not supported by Chrome/Edge 109, the browser I use on Windows 7 x64. The solution is extremely simple — just add a polyfill to your codebase like this:
Guys, with your endless quest to optimize and make everything glow, you're ruining the way to communicate with others that has worked for decades.
Titozzz commentedon Jul 14, 2026
Since I'm not using webview on Windows myselfn let me ping folks at microsoft @Nitin-100 @anupriya13
FaithfulAudio commentedon Jul 15, 2026
Thanks @Titozzz, appreciate the ping. Quick orientation: the four PRs (#3981 environment + init-error onError, #3982 IsSuccess()/title in nav events, #3983 document-start bridge + injectedJavaScriptBeforeContentLoaded, #3984 javaScriptEnabled lifecycle) are each based on master, independently revertible, and touch only the Windows/WebView2 path — nothing in shared, iOS, or Android. They're still draft because I haven't compiled them against this repo's build yet; the fixes were validated in our production RNW 0.83 new-arch app. Happy to walk through any root cause or rebase if more than one lands.
tido64 commentedon Aug 4, 2026
@acoates-ms, @vmoroz: Is this something you can take a look at?