Mobile Development 17 min read

In‑Depth Analysis and Implementation of JSBridge for Mobile Hybrid Development

This article provides a comprehensive overview of JSBridge, covering its origins, use cases, communication mechanisms, and detailed JavaScript‑side implementation with code examples for iOS and Android, helping developers understand and build robust hybrid mobile applications.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
In‑Depth Analysis and Implementation of JSBridge for Mobile Hybrid Development

1 Introduction

Most developers first encounter JSBridge through WeChat's WeiXinJSBridge (now wrapped as JSSDK), which allows web pages to call native functions. JSBridge has existed long before mobile, appearing in desktop software for notifications, product details, and ads that use Web UI but trigger native actions. In the mobile era, hybrid apps and React‑Native rely heavily on JSBridge, as do WeChat Mini‑Programs.

2 Origin of JSBridge

The name "JSBridge" stems from JavaScript's dominance as the easiest, most maintainable, and most deployable UI technology. Web pages can be updated instantly without user intervention, making Web a low‑cost choice for hybrid development. JavaScript therefore naturally became the bridge between Web and native layers. PhoneGap (the predecessor of Cordova) was the first widely recognized JSBridge use case, and WeChat popularized it for sharing content.

JSBridge is applied in two main technical schemes:

Web‑based hybrid solutions such as the WeChat browser and company‑specific hybrid frameworks.

Non‑Web UI solutions whose business logic is JavaScript, e.g., React‑Native.

WeChat Mini‑Programs use a Web UI but isolate JavaScript for performance, placing them between the two categories.

3 Uses of JSBridge

JSBridge provides JavaScript with an interface to invoke native capabilities (location, camera, payment, etc.) and establishes a two‑way communication channel between native and non‑native code.

JavaScript → Native: send messages to call functions or notify native of state.

Native → JavaScript: return results, push messages, or notify JavaScript of native state.

4 Implementation Principles of JSBridge

JavaScript runs in an isolated JS context (e.g., WebKit, JSC). This isolation is analogous to RPC, where each call is a remote procedure invocation. The design therefore follows the typical RPC client‑server model.

4.1 Communication Principles

4.1.1 JavaScript Calls Native

4.1.1.1 Injected API

Injecting an API uses the WebView interface to add objects or methods to the JavaScript window, allowing direct native execution when called.

iOS UIWebView example:

JSContext *context = [uiWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
context[@"postBridgeMessage"] = ^(NSArray<NSArray *> *calls) {
    // Native logic
};

Front‑end call:

window.postBridgeMessage(message);

iOS WKWebView example:

@interface WKWebVIewVC ()
@end
@implementation WKWebVIewVC
- (void)viewDidLoad {
    [super viewDidLoad];
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    configuration.userContentController = [[WKUserContentController alloc] init];
    WKUserContentController *userCC = configuration.userContentController;
    // Inject object, native can capture calls
    [userCC addScriptMessageHandler:self name:@"nativeBridge"];
    WKWebView *wkWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
    // TODO: display WebView
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"nativeBridge"]) {
        NSLog(@"Front‑end data %@: ",message.body);
        // Native logic
    }
}
@end

Front‑end call:

window.webkit.messageHandlers.nativeBridge.postMessage(message);

4.1.1.2 Intercept URL Scheme

URL Scheme is a custom protocol (e.g., qunarhy://hy/url?url=... ) that the native side intercepts. The Web side typically uses an iframe.src request. This method suffers from URL length limits and higher latency, but historically supported iOS 6.

4.1.2 Native Calls JavaScript

Native simply evaluates a JavaScript string. The JavaScript function must be attached to the global window object.

iOS UIWebView:

result = [uiWebview stringByEvaluatingJavaScriptFromString:javaScriptString];

iOS WKWebView:

[wkWebView evaluateJavaScript:javaScriptString completionHandler:completionHandler];

Android pre‑KitKat:

webView.loadUrl("javascript:" + javaScriptString);

Android KitKat and later:

webView.evaluateJavascript(javaScriptString, new ValueCallback
() {
    @Override
    public void onReceiveValue(String value) {
        // handle result
    }
});

4.2 JSBridge Interface Implementation

The bridge provides two core functions: invoke (JavaScript → Native) and receiveMessage (Native → JavaScript). A simple implementation looks like:

window.JSBridge = {
    // Call Native
    invoke: function(msg) {
        nativeBridge.postMessage(msg);
    },
    // Receive from Native
    receiveMessage: function(msg) {
        // handle msg
    }
};

To support callbacks, a unique callbackId is generated and stored on the JavaScript side. Native returns the same callbackId so the original callback can be executed.

(function () {
    var id = 0,
        callbacks = {};
    window.JSBridge = {
        invoke: function (bridgeName, callback, data) {
            var thisId = id++;
            callbacks[thisId] = callback;
            nativeBridge.postMessage({
                bridgeName: bridgeName,
                data: data || {},
                callbackId: thisId
            });
        },
        receiveMessage: function (msg) {
            var bridgeName = msg.bridgeName,
                data = msg.data || {},
                callbackId = msg.callbackId;
            if (callbackId && callbacks[callbackId]) {
                callbacks[callbackId](msg.data);
            } else if (bridgeName) {
                // handle bridgeName logic
            }
        },
        register: function (bridgeName, callback) {
            if (!registerFuncs[bridgeName]) {
                registerFuncs[bridgeName] = [];
            }
            registerFuncs[bridgeName].push(callback);
        }
    };
})();

The full example (omitting some details) combines the above ideas into a more complete bridge that also supports native‑to‑JavaScript callbacks.

5 How to Include JSBridge

5.1 Injection from Native

Native injects the entire bridge script into the WebView. This ensures version consistency but requires retry logic if injection fails.

5.2 Reference from JavaScript

JavaScript loads the bridge script itself, guaranteeing its presence before calls, but the bridge must remain compatible with multiple native versions.

6 Summary

This article dissected the principles of communication between JavaScript and native code, presented a JavaScript‑side implementation of JSBridge, discussed reference strategies, and supplied illustrative code snippets to help developers build reliable hybrid mobile applications.

Mobilejavascripthybrid-developmentNative IntegrationJSBridge
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.