一、什么是 JSBridge?
JSBridge,顾名思义,是连接 JavaScript 和 Native(原生客户端) 的桥梁。它是一种机制,允许运行在 WebView 中的 JavaScript 代码调用原生系统(如 Android 的 Java/Kotlin, iOS 的 Objective-C/Swift)的功能,同时也允许原生代码调用 JavaScript 函数。
核心目的:让 Hybrid App(混合模式移动应用) 中的 H5 页面能够使用原生能力,如相机、地理位置、文件系统、蓝牙等,从而突破纯网页技术的限制,获得接近原生应用的体验。
二、为什么需要 JSBridge?
- 动态化与灵活性:H5 页面可以随时上线和更新,无需经过应用商店的审核,非常适合业务快速迭代和 A/B 测试。
- 跨平台:一套 H5 代码,可以在 Android 和 iOS 两个平台上运行,节省开发成本。
- 功能互补:H5 无法实现或实现效果不佳的功能(如复杂的图形处理、高性能游戏、深度设备集成),可以由原生端提供,然后通过 JSBridge 供 H5 调用。
- 体验平衡:在保证大部分业务动态化的前提下,通过调用原生组件(如导航栏、弹窗),可以提升局部的用户体验。
三、JSBridge 的核心原理与实现方式
JSBridge 的本质是 双向通信。其实现主要依赖于 WebView 提供的交互能力。
1. JavaScript 调用 Native
这是最常用的方向。主要有三种主流方案:
a) 拦截 URL Scheme(最常用、最经典)
这是最普遍的实现方式。
原理:
-
JavaScript 通过创建一个
iframe或直接修改window.location,发起一个特殊的伪协议 URL 请求。- 例如:
jsbridge://showToast?title=hello&duration=2000
- 例如:
-
Native 端会监听 WebView 的所有请求。当它发现这个请求的 Scheme(这里是
jsbridge://)是事先约定好的协议时,就不会进行真正的网络请求,而是拦截这个请求。 -
Native 端解析这个 URL,获取到方法名(
showToast)和参数({title: ‘hello’, duration: 2000})。 -
Native 端执行对应的原生方法。
-
(可选)执行完毕后,Native 通过其他方式将结果回调给 JavaScript。
优点:兼容性好,几乎所有版本的 WebView 都支持。
缺点:URL 长度有限制,传递大量数据时可能有问题;调用是单向的,获取返回值需要额外的回调机制。
b) 向 JavaScript 注入 API(Android 4.2+ 推荐)
原理:
-
Native 端在 WebView 加载页面时,通过 WebView 的接口(Android 的
addJavascriptInterface,iOS 的JavaScriptCore或WKScriptMessageHandler)向 JavaScript 上下文(window)中注入一个全局对象。 -
JavaScript 可以直接调用这个全局对象上的方法。
- 例如:
window.NativeBridge.showToast(‘hello’, 2000)
- 例如:
优点:调用方式更直观、自然,就像调用本地函数一样;性能较好。
缺点:
- Android:在 4.2 以下有严重安全漏洞(漏洞详情与
addJavascriptInterface有关)。虽然 4.2+ 已修复,但兼容低版本需要额外处理。 - iOS:
UIWebView(已废弃)和WKWebView的注入方式不同,需要分别处理。
c) 弹窗拦截(已过时,了解即可)
早期通过 JavaScript 的 alert, confirm, prompt 方法触发,Native 端拦截这些弹窗并解析其中的信息。因其会阻塞线程且功能有限,现已很少使用。
2. Native 调用 JavaScript
这个方向相对简单。
原理:
Native 端通过 WebView 的 loadUrl 方法或 evaluateJavascript 方法,直接执行一段 JavaScript 字符串代码。
-
Android:
java
// 4.4 之前 webView.loadUrl("javascript:handleFromNative('" + message + "')"); // 4.4+ 推荐 webView.evaluateJavascript("javascript:handleFromNative('" + message + "')", new ValueCallback<String>() { @Override public void onReceiveValue(String value) { // 这里可以拿到 JavaScript 函数的返回值 } }); -
iOS (WKWebView) :
objc
[webView evaluateJavaScript: "javascript:handleFromNative('message')" completionHandler:^(id _Nullable response, NSError * _Nullable error) { // 处理返回结果或错误 }];
四、一个完整的 JSBridge 设计流程
一个成熟的 JSBridge 不仅仅是通信,还包括回调管理、消息队列等。
-
初始化:H5 页面加载后,检查 Native 注入的全局对象是否存在。如果不存在,则降级为使用 URL Scheme 方式。
-
JavaScript 调用 Native:
- H5 生成一个唯一的
callbackId。 - 将
callbackId、方法名、参数组装成一个消息。 - 在 H5 端创建一个以
callbackId为 key 的回调函数,存入一个回调字典中。 - 通过 URL Scheme 或注入的 API 将消息发送给 Native。
- H5 生成一个唯一的
-
Native 处理:
- Native 解析消息,执行对应的原生功能。
- 执行完毕后,携带结果数据和接收到的
callbackId,调用 H5 的一个统一接收函数。
-
Native 回调 JavaScript:
- H5 的统一接收函数被调用,根据
callbackId从回调字典中找到对应的回调函数。 - 执行该回调函数,并将 Native 返回的数据传入。
- 从字典中移除已执行的回调。
- H5 的统一接收函数被调用,根据
-
消息队列:在 Bridge 尚未准备就绪时(例如,H5 的 Bridge JS 文件已加载,但 Native 尚未注入对象),可以将调用请求先存入一个队列,待 Bridge 准备好后再依次执行。
五、实际应用与现有库
在实际开发中,我们很少从零开始实现一整套 JSBridge。通常会使用成熟稳定的库或框架。
- DSBridge:一个非常优秀的开源库,同时支持 Android 和 iOS,API 设计简洁,同时支持上述的两种调用方式,并且提供了同步调用能力。
- WebViewJavascriptBridge (iOS):一个经典的、在 iOS 端广泛使用的库。
- 官方推荐:现在更推荐使用
WKWebView的postMessage机制,或者 Google 推出的 PWA + Trusted Web Activity 方案来构建混合应用,它们提供了更现代、更安全的通信方式。
总结
| 特性 | 描述 |
|---|---|
| 本质 | JavaScript 与 Native 代码之间的双向通信通道。 |
| 核心目的 | 让 H5 能够调用原生能力,实现 Hybrid App 的动态化和功能互补。 |
| 主要实现方式 | JS 调 Native:拦截 URL Scheme、注入 API。Native 调 JS:evaluateJavascript / loadUrl。 |
| 关键设计 | 消息格式、回调管理、桥接器就绪机制。 |
JSBridge 是混合开发技术的基石,理解它对于开发高性能、高体验的 Hybrid App 至关重要。