npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@docoi/jsbridge-sdk

v2.0.2

Published

轻量级、高性能的 JSBridge SDK,用于 Web 与原生 App 之间的通信

Readme

JSBridge SDK

轻量级、高性能的 JSBridge SDK,用于 Web 与原生 App 之间的通信。

特性

  • 🚀 高性能:轻量级设计,无外部依赖,体积小巧
  • 🔄 双向通信:支持 H5 调用原生方法,也支持原生调用 H5 方法
  • 📱 多平台支持:同时支持 iOS (WKWebView) 和 Android (JavaScriptInterface)
  • 🔄 队列管理:内置队列机制,确保顺序调用,避免并发问题
  • 📊 调试友好:内置日志系统,支持不同级别的调试输出
  • 🔌 事件系统:提供订阅/发布模式的事件系统,方便原生向 H5 推送消息
  • 🔄 Promise 支持:支持 Promise 方式调用,代码更简洁
  • 🧩 TypeScript:使用 TypeScript 编写,提供完整类型定义
  • 🛡️ 框架兼容:适用于各种前端框架 (Vue, React, Angular 等)

安装

npm install jsbridge-sdk --save

或者使用 CDN 直接引入:

<script src="https://unpkg.com/jsbridge-sdk/dist/jsbridge.min.js"></script>

基本用法

JSBridge 通信层不内建业务缓存;如需复用接口结果,请在业务层按场景实现缓存策略。

初始化

import JSBridge from 'jsbridge-sdk';

// 初始化 JSBridge
JSBridge.init({
  debug: true,             // 是否开启调试模式
  timeout: false           // 默认不启用超时
});

timeout 默认不启用。只有显式配置全局 timeout 或单次调用的 options.timeout 时,通信层才会在超时后返回 BridgeError。大多数方法默认并发发送;只有单次调用传入 queue: 'serial' 的方法会按同一 method 维度串行执行。

调用原生方法

// 方式 1:回调方式
JSBridge.call('getDeviceInfo', function(result) {
  console.log('设备信息:', result);
});

// 方式 2:带参数
JSBridge.call('getLocation', { type: 'gcj02' }, function(result) {
  console.log('位置信息:', result);
});

// 方式 3:Promise 方式
try {
  const rawResult = await JSBridge.callAsync('getNetworkStatus');
  // 业务 SDK 或业务代码在这里判断 rawResult 的业务语义
  console.log('Native 原始返回:', rawResult);

  // 少数需要互斥执行的 Native 方法,可以在单次调用时指定串行队列
  const mediaResult = await JSBridge.callAsync('chooseMedia', {}, {
    queue: 'serial',
    timeout: 60000
  });
  console.log('选择媒体结果:', mediaResult);
} catch (error) {
  console.error('通信层失败:', error);
}

callAsync 只在通信层失败时 reject,例如 Native bridge 不存在、发送异常、参数无法序列化或显式 timeout。只要 Native 正常回调,通信层都会 resolve 原始数据,不会根据 codesuccesserror 等业务字段判断成功失败。

注册 H5 方法供原生调用

// 注册方法
JSBridge.register('updateUI', function(data) {
  console.log('收到原生传来的数据:', data);
  // 更新界面逻辑
  return {
    success: true,
    message: '界面已更新'
  };
});

// 注销方法
JSBridge.unregister('updateUI');

事件监听

// 监听事件
function networkChangeHandler(data) {
  console.log('网络状态变化:', data);
}
JSBridge.on('networkChange', networkChangeHandler);

// 取消监听
JSBridge.off('networkChange', networkChangeHandler);

一次性事件监听

function loginStateHandler(data) {
  console.log('只处理第一次登录态变化:', data);
}

JSBridge.once('loginStateChanged', loginStateHandler);

// 如果事件触发前不再需要监听,也可以用原始 handler 移除
JSBridge.off('loginStateChanged', loginStateHandler);

once 注册的监听器会在首次触发前先自动移除,再执行 handler,因此可以避免同步重入导致重复触发。

Bridge 诊断

if (JSBridge.isReady()) {
  console.log('Native bridge 可发送');
}

console.log(JSBridge.getBridgeInfo());
// { ready: true, platform: 'ios', bridgeType: 'webkit' }

isReady() 只表示当前 WebView 是否检测到可用 Native bridge 入口,不代表某个业务 method 一定存在。

通信层错误

通信层失败会返回轻量的 BridgeError

{
  type: 'NATIVE_UNAVAILABLE',
  message: '当前环境不支持调用原生方法',
  method: 'getDeviceInfo'
}

通信层错误只表示 JSBridge 通道失败,不表示 Native 业务失败。Native 返回的业务错误会被原样透传,codemsgresult 等业务字段应由上层业务 SDK 处理。

在 Vue 中使用

创建插件

// src/plugins/jsbridge.js
import JSBridge from 'jsbridge-sdk';

export default {
  install(app, options = {}) {
    // 初始化 JSBridge
    JSBridge.init({
      debug: options.debug || false,
      timeout: options.timeout || 15000
    });

    // 添加全局属性 $jsbridge
    app.config.globalProperties.$jsbridge = JSBridge;

    // 提供 JSBridge
    app.provide('jsbridge', JSBridge);
  }
};

// 导出 JSBridge 单例,方便直接使用
export { JSBridge };

在 main.js 中注册插件

import { createApp } from 'vue';
import App from './App.vue';
import JSBridgePlugin from './plugins/jsbridge';

const app = createApp(App);
app.use(JSBridgePlugin, { debug: true });
app.mount('#app');

在组件中使用

// 选项式 API
export default {
  methods: {
    getDeviceInfo() {
      this.$jsbridge.call('getDeviceInfo', result => {
        this.deviceInfo = result;
      });
    }
  }
};

// 组合式 API
import { inject } from 'vue';

export default {
  setup() {
    const jsbridge = inject('jsbridge');

    const getDeviceInfo = async () => {
      try {
        const result = await jsbridge.callAsync('getDeviceInfo');
        // 处理结果
      } catch (err) {
        // 处理错误
      }
    };

    return { getDeviceInfo };
  }
};

原生端实现

本 SDK 提供 JavaScript 端的通信实现,原生端需要实现对应通道才能完成通信。新版通道统一使用 mysJSBridge 命名。

通信边界

jsbridge-sdk 只负责全量传递数据,不组装业务响应结构。业务响应应由上层封装层处理,例如 H5 业务方法需要返回:

{
  code: 0,
  msg: 'ok',
  result: {}
}

则应由 mys-sdk 或业务封装方法返回这个对象,jsbridge-sdk 会原样传给 Native,不再额外包装 successdata 等字段。

Native 回调 H5

H5 调 Native 后,Native 通过 mysJSBridgeCallback 把本次调用结果回传给 H5。

window.mysJSBridgeCallback(callbackId, data)

Native 发事件给 H5

Native 主动广播事件时,通过 mysJSBridgeEvent 通知 H5。事件没有返回值,也不依赖 callbackId

window.mysJSBridgeEvent('networkChange', {
  type: 'wifi'
})

Native 主动调用 H5

Native 通过 mysJSBridgeInvoke 主动调用 H5 已注册的方法。

同步方法会直接返回 H5 handler 的原始返回值序列化字符串:

const result = window.mysJSBridgeInvoke('getPageInfo', {})

异步方法必须传 callbackIdmysJSBridgeInvoke 会立即返回 null,Promise 完成后再由 H5 通过 Native 回调通道把原始数据传回 Native。

window.mysJSBridgeInvoke('selectAddress', { scene: 'order' }, 'native_callback_001')

如果 H5 handler 返回 Promise 但 Native 没有传 callbackId,SDK 会同步返回通信层错误,提示异步 H5 方法必须传 callbackId

iOS 实现(WKWebView)

// 简化示例
extension ViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard let body = message.body as? [String: Any],
              let methodName = body["method"] as? String,
              let callbackId = body["callbackId"] as? String else {
            return
        }

        let params = body["params"] as? [String: Any] ?? [:]
        handleJSBridgeCall(methodName: methodName, params: params, callbackId: callbackId)
    }

    func handleJSBridgeCall(methodName: String, params: [String: Any], callbackId: String) {
        // Native 返回什么,H5 就会收到什么;业务结构由上层 SDK 约定
        let result: [String: Any] = [
            "code": 0,
            "msg": "ok",
            "result": ["platform": "iOS", "version": UIDevice.current.systemVersion]
        ]

        let script = "window.mysJSBridgeCallback('\(callbackId)', \(toJSONString(result)))"
        webView.evaluateJavaScript(script, completionHandler: nil)
    }

    // Native 同步调用 H5 方法
    func callH5Method(name: String, data: [String: Any], completion: ((Any?) -> Void)? = nil) {
        let script = "window.mysJSBridgeInvoke('\(name)', \(toJSONString(data)))"
        webView.evaluateJavaScript(script) { (result, error) in
            completion?(result)
        }
    }

    // Native 异步调用 H5 方法
    func callAsyncH5Method(name: String, data: [String: Any], callbackId: String) {
        let script = "window.mysJSBridgeInvoke('\(name)', \(toJSONString(data)), '\(callbackId)')"
        webView.evaluateJavaScript(script, completionHandler: nil)
    }

    // 触发 H5 事件
    func triggerH5Event(eventName: String, data: [String: Any]) {
        let script = "window.mysJSBridgeEvent('\(eventName)', \(toJSONString(data)))"
        webView.evaluateJavaScript(script, completionHandler: nil)
    }
}

Android 实现(JavaScriptInterface)

// 简化示例
public class MysJSBridgeInterface {
    private WebView webView;
    private Context context;

    public MysJSBridgeInterface(WebView webView, Context context) {
        this.webView = webView;
        this.context = context;
    }

    @JavascriptInterface
    public void call(String message) {
        try {
            JSONObject jsonObject = new JSONObject(message);
            String method = jsonObject.getString("method");
            JSONObject params = jsonObject.optJSONObject("params");
            String callbackId = jsonObject.optString("callbackId");

            JSONObject result = handleMethod(method, params);
            callH5Callback(callbackId, result);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private JSONObject handleMethod(String method, JSONObject params) throws JSONException {
        // Native 返回什么,H5 就会收到什么;业务结构由上层 SDK 约定
        JSONObject result = new JSONObject();
        JSONObject data = new JSONObject();
        data.put("platform", "Android");
        data.put("version", Build.VERSION.RELEASE);
        result.put("code", 0);
        result.put("msg", "ok");
        result.put("result", data);
        return result;
    }

    // 在主线程中回调 H5
    private void callH5Callback(final String callbackId, final JSONObject result) {
        if (callbackId == null || callbackId.length() == 0) {
            return;
        }
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.mysJSBridgeCallback('" + callbackId + "', " + result.toString() + ")",
                null
            );
        });
    }

    // Native 同步调用 H5 方法
    public void callH5Method(String name, JSONObject data, ValueCallback<String> callback) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.mysJSBridgeInvoke('" + name + "', " + data.toString() + ")",
                callback
            );
        });
    }

    // Native 异步调用 H5 方法
    public void callAsyncH5Method(String name, JSONObject data, String callbackId) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.mysJSBridgeInvoke('" + name + "', " + data.toString() + ", '" + callbackId + "')",
                null
            );
        });
    }

    // 在主线程中触发 H5 事件
    public void triggerH5Event(String eventName, JSONObject data) {
        webView.post(() -> {
            webView.evaluateJavascript(
                "window.mysJSBridgeEvent('" + eventName + "', " + data.toString() + ")",
                null
            );
        });
    }

    @JavascriptInterface
    public void onMysJSBridgeReady() {
        // Bridge 已就绪
        Log.d("MysJSBridge", "Bridge is ready");
    }
}

示例

查看 examples 目录中的完整示例:

  • examples/basic.html - 基本用法示例
  • examples/vue-demo/ - Vue 集成示例

API 文档

JSBridge

方法

  • init(options?: JSBridgeOptions): JSBridgeInterface - 初始化 JSBridge
  • call(method: string, params?: any, callback?: CallbackFunction, options?: CallOptions): JSBridgeInterface - 调用原生方法
  • callAsync(method: string, params?: any, options?: CallOptions): Promise<any> - Promise 风格的原生方法调用;仅通信层失败时 reject
  • register(name: string, handler: MethodHandler): JSBridgeInterface - 注册 H5 方法供原生调用
  • unregister(name: string): JSBridgeInterface - 注销 H5 方法
  • on(eventName: string, handler: EventHandler): JSBridgeInterface - 监听原生事件
  • once(eventName: string, handler: EventHandler): JSBridgeInterface - 一次性监听原生事件
  • off(eventName: string, handler?: EventHandler): JSBridgeInterface - 取消监听原生事件
  • isReady(): boolean - 当前是否检测到可用 Native bridge
  • getBridgeInfo(): BridgeInfo - 获取 Bridge 诊断信息
  • setDebug(enabled: boolean, options?: Partial<DebugOptions>): JSBridgeInterface - 设置调试模式

类型定义

interface JSBridgeOptions {
  debug?: boolean;
  timeout?: number | false;
}

type QueueMode = 'parallel' | 'serial';

interface CallOptions {
  queue?: QueueMode;
  timeout?: number | false;
}

type BridgeErrorType =
  | 'NOT_INITIALIZED'
  | 'NATIVE_UNAVAILABLE'
  | 'SEND_FAILED'
  | 'SERIALIZE_FAILED'
  | 'TIMEOUT'
  | 'INVALID_METHOD';

interface BridgeError {
  type: BridgeErrorType;
  message: string;
  method?: string;
  callbackId?: string;
  detail?: unknown;
}

interface BridgeInfo {
  ready: boolean;
  platform: 'ios' | 'android' | 'unknown';
  bridgeType: 'webkit' | 'javascriptInterface' | 'none';
  version?: string;
  capabilities?: string[];
}

type CallbackFunction = (data: any) => void;
type MethodHandler = (data: any) => any | Promise<any>;
type EventHandler = (data: any) => void;

interface DebugOptions {
  enabled: boolean;
  logLevel?: string;
  useConsole?: boolean;
}

构建与开发

# 安装依赖
npm install

# 开发模式
npm run dev

# 构建
npm run build

# 运行示例
npm run example:basic