XuqmGroup-RNSDK/packages/xwebview
2026-07-27 16:48:52 +08:00
..
src fix(xwebview): bypass page cache in debug 2026-07-27 16:48:52 +08:00
tests feat(xwebview): refine web navigation lifecycle 2026-07-27 15:11:08 +08:00
package.json feat(xwebview): refine web navigation lifecycle 2026-07-27 15:11:08 +08:00
README.md feat(xwebview): refine web navigation lifecycle 2026-07-27 15:11:08 +08:00
tsconfig.json feat: rebuild RN sdk runtime and plugin updates 2026-07-17 13:50:30 +08:00

@xuqm/rn-xwebview

通用 React Native WebView 容器。1.1.0 只有三项正式入口:

  • <XWebViewHost />:应用根部挂载一次的全屏页面 Host。
  • openWebView(config):从任意业务服务打开页面,返回该页面自己的 Handle。
  • <XWebViewView config={...} />:不需要全屏导航栏时使用的内嵌浏览器内核。

SDK 不包含任何医网信、厂商、用户、平台、域名或业务 Bridge 定义。

安装

pnpm add @xuqm/rn-common @xuqm/rn-xwebview \
  react-native-webview react-native-svg \
  @react-native-clipboard/clipboard react-native-safe-area-context

react-native-svg 含原生 ViewManager,必须由宿主直接声明并完成 React Native autolink;它不能只作为 @xuqm/rn-xwebview 的传递依赖。缺少该直接依赖时,使用 SDK 内置导航图标的页面会在运行期报告找不到 RNSVGSvgViewAndroid

@react-native-camera-roll/camera-roll 是可选 peer;只有需要把下载图片登记到系统相册 时才安装。

最小集成

import { XWebViewHost, openWebView } from '@xuqm/rn-xwebview'

export function App() {
  return (
    <>
      <RootNavigation />
      <XWebViewHost />
    </>
  )
}

const page = openWebView({
  source: { uri: 'https://example.com' },
  navigationBar: {
    title: { text: '页面标题', mode: 'web' },
  },
  statusBar: {
    translucent: true,
  },
})

page.reload()
page.postMessage('hello')
page.suspend() // 临时展示宿主原生页面,WebView 实例和历史仍保留
page.resume()
page.close()
const result = await page.closed

Host 尚未挂载时请求最多等待 3 秒,超时以 host_unavailable 关闭。全局只能挂载一个 Host;Host 卸载会以 host_unmounted 关闭其全部页面。

分组配置

openWebViewXWebViewView 使用同一个 XWebViewConfig

  • source{uri, headers?}{html, baseUrl?} 二选一。
  • navigationBar:标题、返回、关闭、菜单、纯色/渐变/图片背景或完整自定义渲染。
  • statusBar:显隐、透明沉浸、背景和前景模式。
  • behaviorCookie、混合内容、外链决策、JS 注入、消息与生命周期回调。
  • permissions:摄像头/麦克风白名单与可选宿主决策。
  • downloads:自动/人工决策、目标目录、鉴权头、进度、完成和失败回调。
  • bridge由具体业务协议包提供;XWebView 只负责转发与页面上下文。

禁止恢复扁平的 url/title/showTopBar 双轨配置。

页面栈与系统返回

每次 openWebView 都生成独立页面和 Handle。页面栈只显示顶层页面,关闭后恢复下一层 页面及其导航状态。默认导航栏的左返回按钮只在存在网页历史时显示,且只执行网页后退; 右侧关闭按钮用于明确关闭当前页。

Android 系统返回先执行网页历史返回,没有历史时默认关闭当前页。需要防止误退出的宿主 可以启用双击关闭,并自行决定首次按键的提示样式:

const page = openWebView({
  behavior: {
    hardwareBack: {
      closeMode: 'doublePress',
      doublePressIntervalMs: 1_000,
      onFirstClosePress: () => showToast('再按一次退出当前页面'),
    },
  },
  source: { uri: 'https://example.com' },
})

宿主需要短暂展示原生页面时调用 page.suspend(),原生页面结束后调用 page.resume();暂停不等于关闭,不触发 closed,也不创建第二份 WebView。

导航标题和显隐修改属于当前页面,不能污染下层页面。H5 隐藏原生导航栏但保留状态栏 时,Bridge 可以从页面上下文取得真实安全区高度。

权限

SDK 不向 Manifest/Info.plist 注入敏感权限。宿主按启用能力声明,例如 Android

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

H5 调用 getUserMedia 时,XWebView 先检查页面配置和宿主决策,再在 Android 请求系统 权限,最后才继续 WebView 媒体请求。未识别资源和 3 秒内未完成的自定义决策均拒绝。

下载与安全默认值

  • 默认保存到 App 沙盒;publicDownloads 在 Android 使用沙盒落盘后登记到下载列表。
  • URI 首屏 headers 自动复用于 HEAD 与文件下载,也可由 downloads.headers 补充。
  • Cookie 默认共享,第三方 Cookie 默认关闭。
  • 混合内容默认 never;生产页面不得改为 always
  • http/https/about:blank 在容器内打开;tel/sms/mailto 交给系统;file/javascript/intent 和未知 scheme 默认拒绝。
  • Bridge 异常不会形成未处理 Promise;宿主可通过 behavior.onBridgeError 接收不含原始 payload 的错误信息。

迁移到 1.0.0

旧的 XWebViewScreenXWebViewControlopenXWebView(navigate, flatConfig) 和 common 内的 WebView Bridge 已删除,不提供兼容壳。

迁移原则:

  1. 根部挂载一次 <XWebViewHost />
  2. 扁平参数转换为上述分组配置。
  3. 全局 Control 改为保存本次 openWebView 返回的页面 Handle。
  4. 业务 Bridge 单独作为 config.bridge 注入,不进入 common 或 XWebView。
  5. 内嵌页面直接使用 <XWebViewView />,不再直接包装 react-native-webview

验证

pnpm --dir packages/xwebview typecheck
pnpm --dir packages/xwebview test