ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Expo Go 内置的 react-native-webview:vendored 模块的架构、平台实现与 Expo 定制补丁解析

Expo Go 内置的 react-native-webview:vendored 模块的架构、平台实现与 Expo 定制补丁解析 Expo Go 内置的 react-native-webviewvendored 模块的架构、平台实现与 Expo 定制补丁解析【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo本篇以 Expo 仓库中 Expo Go 应用内嵌的 react-native-webview 模块 为主体解析这个社区维护的 WebView 组件为什么被 Expo Go 以「vendored module」方式内置、它如何同时覆盖 iOS/Android/macOS/Windows 与新旧两套 React Native 架构以及 Expo 团队通过 vendoring 配置 与 作用域补丁 在原生层做了什么定制。读完后你能掌握该模块的目录结构与多平台入口机制、版本升级的操作方式以及 Expo 定制的 WKProcessPool 作用域隔离原理。1. 模块定位为什么 Expo Go 要内置一份 react-native-webview模块自带的 README 说明了它的来历React Native WebView是一个社区维护的 WebView 组件目标取代已从 React Native 核心中移除的内置 WebView它兼容iOS、Android、Windows 和 macOS同时支持旧架构paper与新架构fabric并且明确声明与 Expo 兼容compatible with expo。在 Expo 仓库中apps/expo-go/modules/下的所有模块遵循一个统一规则——modules 目录说明 指出Expo Go 中的 vendored 模块意味着「我们将其内置vendor并应用位于tools/src/vendoring/config的 Expo-Go 专属补丁」。react-native-webview正是这类模块之一。当前 vendored 版本由 package.json 确认为13.16.1该版本号与 Expo Go 应用自身的依赖声明apps/expo-go/package.json中react-native-webview: 13.16.1保持一致。模块自身的依赖极简仅有两个运行时依赖dependencies: { escape-string-regexp: ^4.0.0, invariant: 2.2.4 }peerDependencies要求宿主项目提供任意版本的react与react-native。开发依赖则固定在一个较新的基线上例如react-native: 0.73.5、react-native-macos: 0.73.17、react-native-windows: 0.73.8、callstack/react-native-visionos: 0.73.8——从这些版本组合可以推断该组件是在 RN 0.73 世代完成新架构Codegen/Fabric适配的。README 还给出了官方使用示例这也是本模块对外暴露的最基本 APIimport React, { Component } from react; import { StyleSheet, Text, View } from react-native; import { WebView } from react-native-webview; // ... const MyWebComponent () { return WebView source{{ uri: https://reactnative.dev/ }} style{{ flex: 1 }} /; }组件从react-native-webview导入通过source属性传入uri/HTML其余行为由一组onXxx回调与配置 props 驱动。README 同时保留了上游的常见问题提示出现Invariant Violation: Native component for RNCWebView does not exist通常是原生 link 环节出错Android 在:app:mergeDexRelease阶段构建失败则需要在android/app/build.gradle开启 multidex。项目遵循语义化版本SemVer破坏性变更只出现在主版本号许可证为 MIT。需要注意一个仓库事实README 中链接的docs/Getting-Started.md、docs/Reference.md等上游文档并未包含在本仓库的 vendored 副本中apps/expo-go/modules/react-native-webview/下没有docs目录。vendoring 配置中明确排除了测试文件excludeFiles: [src/__tests__/**/*]API 参考需以上游仓库文档为准本仓库内可查证的是src/与lib/中的完整类型定义。2. 目录结构一套 TypeScript 源码 四套原生实现vendored 副本的顶层结构清晰地体现了「JS 层统一、原生层分平台」的组织方式目录/文件职责src/TypeScript 源码跨平台共享逻辑与四个平台入口apple/iOS 与 macOS 共用的 Objective-C/Swift 原生实现android/Kotlin/Java 实现按事件分类组织 JS 事件类windows/C 实现ReactWebView / ReactWebView2 双后端lib/prepare脚本产出的编译产物JS d.tsreact-native-webview.podspecCocoaPods 集成入口iOS/macOS 共用apple/源码index.js / index.d.ts包入口指向lib/package.json 中三个入口字段解释了「源码模式 vs 发布模式」的双轨制main: index.js—— npm 安装场景加载lib/编译产物react-native: src/index.ts—— 在 MetroExpo/RN 开发链路中解析器优先取该字段直接消费 TypeScript 源码保证 Expo Go 内置副本可以被调试与热更新main-internal: src/index.ts—— Expo 内部构建链路的显式入口。package.json 的codegenConfig声明了 Codegen 规范RNCWebViewSpectype: allAndroid 包名为com.reactnativecommunity.webviewiOS 侧映射组件RNCWebView与模块RNCWebViewModule——这就是新架构下src/RNCWebViewNativeComponent.ts能从 spec 生成原生绑定、并在android/newarch与android/oldarch两个目录中各放一份 Manager 实现的结构来源。2.1 多平台入口与 Web 端的「哑组件」入口文件 只有一行导出import WebView from ./WebView; export { WebView }; export default WebView;而src/目录下并排存在五个 WebView 实现WebView.ios.tsx、WebView.android.tsx、WebView.macos.tsx、WebView.windows.tsx与 WebView.tsx。RN/Metro 的文件扩展名解析约定决定了不同平台会命中对应后缀的文件最后的WebView.tsx是不被任何后缀命中的兜底实现它的源码直白地说明了用途// This dummy WebView is to render something for unsupported platforms, // like for example Expo SDK web platform. const WebView: React.FunctionComponentWebViewProps () ( View style{styles.flexStart} Text style{styles.colorRed} React Native WebView does not support this platform. /Text /View );即在 Expo 的 Web 平台上渲染一段红字提示而非崩溃——这保证了含 WebView 的应用可以直接跑在 Expo Web SDK 里。lib/中同名分布的.js/.d.ts文件WebView.ios.js、WebView.macos.js等印证了babel --extensions .ts,.tsx --out-dir lib src构建脚本的产物布局。3. Expo 的定制vendoring 流程与作用域隔离补丁3.1 升级流程et uvm命令 自动打补丁modules 目录说明 给出了升级命令运行et uvm react-native-webview -c 版本号工具会把模块更新到指定版本并重新应用补丁。其自动化逻辑位于 expoGoConfig.tsreact-native-webview: { source: react-native-webview, sourceType: npm, excludeFiles: [src/__tests__/**/*], async postCopyFilesHookAsync(sourceDirectory, targetDirectory) { // patch for scoped webview const patchFile path.join( EXPOTOOLS_DIR, src/vendoring/config/react-native-webview-scoping.patch ); // ... await applyPatchAsync({ patchContent, cwd: targetDirectory, stripPrefixNum: 0 }); }, },流程是从 npm 拉取指定版本 → 剔除测试文件 → 拷贝进apps/expo-go/modules/→ 以patch -p0方式应用 scoping 补丁。补丁应用失败时工具会打印等价的手动命令patch -p0 -d dir patch文件并抛错保证 CI 中不会静默丢失定制。3.2 补丁原理按 scopeKey 隔离 WKProcessPoolreact-native-webview-scoping.patch 是理解 Expo 定制的核心它改动了apple/下四个文件目的是让不同 Expo 项目scope的 WKWebView 使用相互隔离的进程池与存储上下文避免多项目共享 Expo Go 容器时发生 cookie/存储串扰RNCWKProcessPoolManager.h/.m上游只有单例方法sharedProcessPool补丁为其增加了字典_pools与方法- (WKProcessPool *)sharedProcessPoolForScopeKey:(NSString *)scopeKey;逻辑为scopeKey为空时回退到原共享池否则按 key 懒创建并复用独立WKProcessPool。RNCWebViewImpl.h/.m给视图实现增加property (nonatomic, strong) NSString *scopeKey并在创建WKWebViewConfiguration时改为sharedProcessPoolForScopeKey:self.scopeKey仅在useSharedProcessPool为真时生效。RNCWebViewManager.mmManager 新增接收scopeKey以及easProjectId、kernelServiceDelegate等参数的初始化方法并在view工厂方法中把 scopeKey 注入每个RNCWebViewImpl实例RNCWebViewImpl *webview [[RNCWebViewImpl alloc] init]; webview.scopeKey _scopeKey;从源码结构看scopeKey 最终来源于 Expo Go 内核按项目划分的 stable legacy id / scope 体系同一项目的多个 WebView 共享一个进程池不同项目之间则完全隔离。这也解释了为什么补丁只覆盖 Apple 平台——Android 侧的隔离由 Expo Go 自身的 WebView CookieManager 上下文机制处理而本补丁仅针对 WKWebView 的进程池共享行为。4. 原生事件系统与关键 Props从类型定义到原生回调README 指向的 API 参考虽不在 vendored 副本中但 WebViewTypes.ts 的完整类型定义就是权威参考。核心 Props 包括Prop说明取自类型定义source: WebViewSource加载来源uri/html等约 L314、L1177onMessage接收 Web 端通过 postMessage 桥接的消息L307、L1254onShouldStartLoadWithRequest拦截并控制新请求是否发起可用于路由外链L308、L1323injectedJavaScript/injectedJavaScriptObject页面加载时向 JS 上下文注入脚本或序列化对象L293、L1349injectedJavaScriptBeforeContentLoaded及*ForMainFrameOnly系列在 content 加载前注入ForMainFrameOnly默认trueAndroid 上为强制行为L643-L654、L1280-L1289onLoadSubResourceError子资源发生 SSL 错误时回调L1165-L1170allowsBackForwardNavigationGestures、fileSystemAccessfile://URL 相关L602、L916等平台特定行为开关iOS 侧由 apple/RNCWebViewImpl.m、RNCWebViewManager.mm其中RCT_EXPORT_VIEW_PROPERTY(source, NSDictionary)声明了 source 的桥接类型与RNCWebViewDecisionManager决策链等文件承载Android 侧把每一种事件都建模为独立的事件类见 android 事件目录TopMessageEvent、TopLoadingStartEvent、TopLoadingFinishEvent、TopLoadingErrorEvent、TopHttpErrorEvent、TopNewWindowEvent、TopRenderProcessGoneEvent、TopShouldStartLoadWithRequestEvent、SubResourceErrorEvent等——与 JS 侧onXxx回调一一对应再由RNCWebViewClient/RNCWebChromeClient触发、RNCWebViewManagerImpl.kt组装 View。Windows 侧则由 windows/ReactNativeWebView 下的ReactWebView传统后端与ReactWebView2Edge WebView2 后端双实现提供。5. 小结该模块是上游社区项目v13.16.1 的 vendored 副本README 声明的平台矩阵iOS/Android/Windows/macOS与新旧架构双支持均可由src/、apple/、android/newarch oldarch、windows/的实际代码结构印证。Expo 的价值增量集中在 vendoring 工具链et uvm react-native-webview -c ver可完成「拉取 npm 版本 → 排除测试 → 打 scoping 补丁」的完整升级闭环。scoping 补丁 通过给RNCWKProcessPoolManager引入sharedProcessPoolForScopeKey:按项目隔离 WKProcessPool是 Expo Go 多项目并发场景下 Web 内容隔离的关键定制。若需完整的属性文档与 Getting Started 步骤vendored 副本未携带上游docs/请以本仓库 WebViewTypes.ts 中的类型与注释作为实现级参考。【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表