{"id":26910920,"url":"https://github.com/ronhe/rn-webview-rpc","last_synced_at":"2025-04-01T14:25:56.498Z","repository":{"id":48554605,"uuid":"126470297","full_name":"ronhe/rn-webview-rpc","owner":"ronhe","description":"Add RPC capabilities to a React Native WebView component","archived":false,"fork":false,"pushed_at":"2023-01-03T15:17:34.000Z","size":8932,"stargazers_count":25,"open_issues_count":15,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-12-26T17:17:56.511Z","etag":null,"topics":["bridge","comlink","react","react-native","rpc","webview"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ronhe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-23T10:32:12.000Z","updated_at":"2022-11-07T12:18:35.000Z","dependencies_parsed_at":"2023-02-01T07:01:44.405Z","dependency_job_id":null,"html_url":"https://github.com/ronhe/rn-webview-rpc","commit_stats":null,"previous_names":[],"tags_count":3,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronhe%2Frn-webview-rpc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronhe%2Frn-webview-rpc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronhe%2Frn-webview-rpc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ronhe%2Frn-webview-rpc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ronhe","download_url":"https://codeload.github.com/ronhe/rn-webview-rpc/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246653118,"owners_count":20812250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bridge","comlink","react","react-native","rpc","webview"],"created_at":"2025-04-01T14:25:55.780Z","updated_at":"2025-04-01T14:25:56.492Z","avatar_url":"https://github.com/ronhe.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React-Native WebView RPC\n[![NPM version](https://img.shields.io/npm/v/rn-webview-rpc.svg)](https://www.npmjs.com/package/rn-webview-rpc)\n[![](https://data.jsdelivr.com/v1/package/npm/rn-webview-rpc/badge)](https://www.jsdelivr.com/package/npm/rn-webview-rpc)\n[![Build Status](https://travis-ci.org/ronhe/rn-webview-rpc.svg?branch=master)](https://travis-ci.org/ronhe/rn-webview-rpc)\n\nRN-WebView-RPC's goal is to allow calls to native API from a web\napplication that runs inside a `WebView` component, and vice versa.\nIt can be used as a bridge between the native and the web\nparts of hybrid apps, for example,\nrequesting native geo-location permissions from withing a `WebView`.\n\nRN-WebView-RPC integrates React-Native's\n[WebView](https://github.com/react-native-community/react-native-webview)\ncomponent together with Google's\n[Comlink](https://github.com/GoogleChromeLabs/comlink)\nlibrary into an easy-to-use package.\n\nFor example, the snippet below allows opening a native alert that lets \nthe user to choose the background color of an html web page.\n\n```javascript\n// App.js\n\nimport React from 'react';\nimport { View, Alert } from 'react-native';\nimport WebViewRpc from 'rn-webview-rpc/native';\nimport html from './index.html';\n\nexport default class App extends React.Component {\n  render() {\n    return (\n      \u003cView style={{ flex: 1 }}\u003e\n        \u003cWebViewRpc\n          style={{ marginTop: 0, flex: 1 }}\n          source={html}\n          exposedObj={{ Alert }}\n          injectScriptTag\n        /\u003e\n      \u003c/View\u003e\n    );\n  }\n}\n```\n\n```javascript\n// index.html\n\nconst proxy = rnRpc.proxy();\nawait proxy.Alert.alert(\n    'What is your favorite color?',\n    'We got green and blue',\n    [\n      {text: 'Ask me later'},\n      {text: 'Green', onPress: rnRpc.proxyValue(() =\u003e setBgColor('green'))},\n      {text: 'Blue', onPress: rnRpc.proxyValue(() =\u003e setBgColor('blue'))},\n    ],\n    { cancelable: false }\n);\n    \nfunction setBgColor(color) {\n  document.body.style.backgroundColor = color;\n}\n```\n\n## Installation\n### React-Native End Installation\nFirst, install the `react-native-webview` peer dependency, by following the\ninstruction [here](https://github.com/react-native-community/react-native-webview/blob/master/docs/Getting-Started.md#react-native-webview-getting-started-guide).\nFor most projects, that would be:\n```bash\n$ npm install --save react-native-webview\n$ react-native link react-native-webview\n```\n\nThen, install `rn-webview-rpc` from NPM:\n\n```bash\n$ npm install --save rn-webview-rpc\n```\n\nFinally, in your code, import the `WebViewRpc` component:\n```javascript\nimport WebViewRpc from 'rn-webview-rpc/native';\n```\n\n**Note**: If you encounter this error:\n\u003e Objects are not valid as a React child... \n\n\u003cimg alt=\"error screenshot\" src=\"docs/symbol-error.png\" width=\"320\"\u003e\n\nthen you should try adding the following imports\n```javascript\nimport 'core-js/es6/map';\nimport 'core-js/es6/symbol';\n```\nat the top of your app's JavaScript entry point.\nSee [this thread](https://github.com/facebook/react-native/issues/18542)\nfor more info. \n\n### Web End Installation\nYou can either install from NPM or from a CDN.\n\n#### Install from NPM\nInstall `rn-webview-rpc` from NPM (exactly as for the React-Native project):\n```bash\n$ npm install --save rn-webview-rpc\n```\nThen, in your code, import the `rnRpc` object:\n```javascript\nimport rnRpc from 'rn-webview-rpc/web';\n```\n#### Install from a CDN\n##### Install from a CDN automatically\nLet the React-Native's `WebViewRpc` inject an HTML script tag to the website,\nby setting the `injectScriptTag` prop to `true`:\n```javascript\n\u003cWebViewRpc\n  ...\n  injectScriptTag\n/\u003e\n```\n\n##### Install from a CDN manually\nAdd a `script` tag to your HTML's `head`:\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/rn-webview-rpc@2.0.0\u003e\u003c/script\u003e\n```\n\nEither way (after a manual or automatic installation) the `rnRpc` object\nbecomes available globally.\n\n**Warning**:\nWhen manually installing `rn-webview-rpc` on the web end\n(either from NPM or CDN), it's your responsibility to make sure that\nboth ends (React-Native and web) use compatible versions\nof `rn-webview-rpc`.\nHowever, when installing automatically from a CDN by using the `injectScriptTag`,\nthis burden is inherently taken care of for you.\n\n\n## React-Native API - The `WebViewRpc` component \nA React-Native component that renders a\n[`WebView`](https://github.com/react-native-community/react-native-webview)\ncomponent with a bi-directional RPC bridge.\n### Props\nThe following props are consumed by the `rn-webview-rpc` component.\nAdditional props are forwarded to the `react-native-webview`'s\n`WebView` component.\n#### `exposedObj`\nThe React-Native object to be exposed to the web end.\n* Type: object\n* Default: `{}`\n#### `injectScriptTag`\nControls whether to inject a `script` tag to automatically\nload the `rn-webview-rpc` module to the website.\n* Type: bool\n* Default: `false`\n#### `onMessage(listener)`\nAllows an extra custom listener to `message` events\n(except for the one that is already configured in order to take care of the\nRPC functionality).\n* Type: function\n* Default: `undefined`\n\nIn most cases, this prop should not be used.\n\n#### `target`\nAn interface object for proxy calls.\nIt is required for invoking calls from the React-Native end to the web end\n(using the `rnRpc`'s `proxy` attribute). \n* Type: object\n* Default: `{}`\n\n### Methods and Attributes\n*Hint*: A React class component instance is accessible using the `ref` prop,\nfor example:\n```javascript\n\u003cWebViewRpc\n    ref={(ref) =\u003e {\n      this.webViewRpc = ref;\n    }}\n/\u003e\n```\n#### `proxy`\nAn ES6 `proxy` polyfill that sends all operations performed on it\nto the web side. It is essentially a proxy object returned by\n[Comlink's `proxy` function](https://github.com/ronhe/comlink#comlinkproxyendpoint).\nHowever, due to limitations of the `proxy` polyfill\n(with respect to the ES6 `proxy`), it is limited to the interface defined \nbeforehand by the `target` prop. This limitation will be resolved once\nReact-Native updates its JavaScript engine to a modern one,\nprobably in React-Native@0.60.\n\n#### `webView`\nA reference to the native `WebView` component instance.\n\n### Static Class Methods\n#### `proxyValue(value)`\nA wrapper function to let a parameter or a return value\nbe proxied rather than copied.\nThis is just a reference to\n[Comlink's `proxyValue` function](https://github.com/ronhe/comlink#comlinkproxyvaluevalue).\n\n## Web API - `rnRpc`\nAn object at the web end that provides a bi-directional RPC bridge\nto the native end.\n### `Functions`\n#### `proxy(target)`\nCreates an ES6 `proxy` that sends all operations performed on it\nto the native side.\n`proxy()` returns an ES6 `proxy` object, exactly like\n[Comlink's `proxy` function](https://github.com/ronhe/comlink#comlinkproxyendpoint).\n\nIn older browsers the `proxy` polyfill is used instead of the ES6 `proxy`.\nIn that case, the `target` argument should define the interface object\nfor proxy calls.\n\n#### `proxyValue`\nA wrapper function to let a parameter or a return value\nbe proxied rather than copied.\nThis is just a reference to\n[Comlink's `proxyValue` function](https://github.com/ronhe/comlink#comlinkproxyvaluevalue).\n\n#### `expose(obj)`\nExposes an object to the native end.\nIt just wraps\n[Comlink's `expose` function](https://github.com/ronhe/comlink#comlinkexposeobj-endpoint).\n \n\n## Limitations\nExposing an object in the native side requires providing a\n`target` interface at creation time.\nThis is because the JavaScript engine \n[JavaScriptCore](https://trac.webkit.org/wiki/JavaScriptCore)\nused by React-Native does not support the ES6 `proxy` object,\nand its polyfill\n[proxy-polyfill](https://github.com/GoogleChrome/proxy-polyfill)\nis limited.\nSame applies for the web end for old browsers.\n\n## Example\nSee the [example directory](https://github.com/ronhe/rn-webview-rpc/tree/master/example).\n\n\u003cimg alt=\"example gif\" src=\"docs/example.gif\" width=\"320\"\u003e\n\n\n## Under the Hood\n\u003e Reading this section is most definitely optionally :)\n\nThe major pain coding this package was helping the\ndelightful Comlink library to work in the native environment (and old browsers).\nComlink is designed for web workers environment, and\nunfortunately the native JavaScript engine is more limited.\n1. `WebView`'s messaging interface supports only string messages.\nThankfully, solving this issue was easy,\nsince the Comlink library already includes a\n[`MessageChannelAdapter`](https://github.com/ronhe/comlink/blob/master/messagechanneladapter.ts),\nto support string based message channels, such as WebRTC.\nWhat remained to be done is to translate the\n`postMessage`/`onMessage` WebView's message API to a\n`send`/`addEventListener` endpoint.\n2. The ES6 `proxy` object is unsupported natively. This was solved using the\n[Proxy Polyfill](https://github.com/GoogleChrome/proxy-polyfill)\n(with some \n[limitations](https://github.com/ronhe/rn-webview-rpc#limitations)).\nMoreover, to allow `proxy` to work in React-Native, [a few changes\nwere required in\nComlink](https://github.com/GoogleChromeLabs/comlink/commits?author=ronhe). \n\n3. The `MessageChannel` and `MessagePort` objects are missing\nin the native environment. Since no polyfills are available, \nto address this problem I had to write pretty\nsimple degenerated polyfills.\n\n4. More polyfills: The `Object` and `ArrayBuffer` behave slightly\ninconsistently in different environments. Hence, I have them\noverridden by polyfills when necessary.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fronhe%2Frn-webview-rpc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fronhe%2Frn-webview-rpc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fronhe%2Frn-webview-rpc/lists"}