All Projects → ronhe → rn-webview-rpc

ronhe / rn-webview-rpc

Licence: MIT license
Add RPC capabilities to a React Native WebView component

Programming Languages

javascript
184084 projects - #8 most used programming language
HTML
75241 projects
shell
77523 projects

Projects that are alternatives of or similar to rn-webview-rpc

FlexHybridApp-Android
WebView bridge interface with Promise pattern
Stars: ✭ 20 (-20%)
Mutual labels:  webview, bridge
Vue Bridge Webview
javascript bridge android/ios webview
Stars: ✭ 52 (+108%)
Mutual labels:  webview, bridge
React Native Webview Invoke
Invoke functions between React Native and WebView
Stars: ✭ 211 (+744%)
Mutual labels:  webview, bridge
Slimsocial For Facebook
Light version of Facebook. Light both in the weight and in the use.
Stars: ✭ 171 (+584%)
Mutual labels:  webview
React Native Turbolinks
React Native adapter for building hybrid apps with Turbolinks 5
Stars: ✭ 177 (+608%)
Mutual labels:  webview
Cargo
🚂🚋🚋 A browser with almost no UI.
Stars: ✭ 221 (+784%)
Mutual labels:  webview
vue-js-bridge
vue-js-bridge for Vue.js
Stars: ✭ 41 (+64%)
Mutual labels:  webview
Hybridfoundation
混合应用基础架构 跨平台热更新方案 Js双向通信 基础WebView
Stars: ✭ 164 (+556%)
Mutual labels:  webview
Google-Docs-for-Mac
Native Google Docs app for Mac
Stars: ✭ 33 (+32%)
Mutual labels:  webview
Recaptcha
[In]visible ReCaptcha v2 for iOS
Stars: ✭ 208 (+732%)
Mutual labels:  webview
Tauri
Build smaller, faster, and more secure desktop applications with a web frontend.
Stars: ✭ 25,383 (+101432%)
Mutual labels:  webview
React Native Linkedin
🔗 React-Native LinkedIn, a simple LinkedIn login library for React-Native or Expo with WebView and Modal
Stars: ✭ 180 (+620%)
Mutual labels:  webview
React Native Webview Messaging
✉️ Send/Receive data between React Native app and WebView
Stars: ✭ 251 (+904%)
Mutual labels:  webview
Android Advancedwebview
Enhanced WebView component for Android that works as intended out of the box
Stars: ✭ 2,186 (+8644%)
Mutual labels:  webview
Android-WebView-in-Kotlin
Native Android WebView Example in Kotlin. Website to android app github open source template.
Stars: ✭ 87 (+248%)
Mutual labels:  webview
Webviewane
WebView Adobe Air Native Extension for macOS 10.10+, Windows Desktop, iOS 9.0+ and Android 19+. This ANE provides access to a more modern webview from AIR.
Stars: ✭ 169 (+576%)
Mutual labels:  webview
FMWebViewJavascriptBridge
FMWebViewJavascriptBridge inspired by WebViewJavascripBridge and react native
Stars: ✭ 29 (+16%)
Mutual labels:  bridge
Android Youtube Player
YouTube Player library for Android and Chromecast, stable and customizable.
Stars: ✭ 2,510 (+9940%)
Mutual labels:  webview
Vscode Kanban
Kanban board for Visual Studio Code.
Stars: ✭ 191 (+664%)
Mutual labels:  webview
WebViewNativeBridge
WebView bridge for android
Stars: ✭ 35 (+40%)
Mutual labels:  webview

React-Native WebView RPC

NPM version Build Status

RN-WebView-RPC's goal is to allow calls to native API from a web application that runs inside a WebView component, and vice versa. It can be used as a bridge between the native and the web parts of hybrid apps, for example, requesting native geo-location permissions from withing a WebView.

RN-WebView-RPC integrates React-Native's WebView component together with Google's Comlink library into an easy-to-use package.

For example, the snippet below allows opening a native alert that lets the user to choose the background color of an html web page.

// App.js

import React from 'react';
import { View, Alert } from 'react-native';
import WebViewRpc from 'rn-webview-rpc/native';
import html from './index.html';

export default class App extends React.Component {
  render() {
    return (
      <View style={{ flex: 1 }}>
        <WebViewRpc
          style={{ marginTop: 0, flex: 1 }}
          source={html}
          exposedObj={{ Alert }}
          injectScriptTag
        />
      </View>
    );
  }
}
// index.html

const proxy = rnRpc.proxy();
await proxy.Alert.alert(
    'What is your favorite color?',
    'We got green and blue',
    [
      {text: 'Ask me later'},
      {text: 'Green', onPress: rnRpc.proxyValue(() => setBgColor('green'))},
      {text: 'Blue', onPress: rnRpc.proxyValue(() => setBgColor('blue'))},
    ],
    { cancelable: false }
);
    
function setBgColor(color) {
  document.body.style.backgroundColor = color;
}

Installation

React-Native End Installation

First, install the react-native-webview peer dependency, by following the instruction here. For most projects, that would be:

$ npm install --save react-native-webview
$ react-native link react-native-webview

Then, install rn-webview-rpc from NPM:

$ npm install --save rn-webview-rpc

Finally, in your code, import the WebViewRpc component:

import WebViewRpc from 'rn-webview-rpc/native';

Note: If you encounter this error:

Objects are not valid as a React child...

error screenshot

then you should try adding the following imports

import 'core-js/es6/map';
import 'core-js/es6/symbol';

at the top of your app's JavaScript entry point. See this thread for more info.

Web End Installation

You can either install from NPM or from a CDN.

Install from NPM

Install rn-webview-rpc from NPM (exactly as for the React-Native project):

$ npm install --save rn-webview-rpc

Then, in your code, import the rnRpc object:

import rnRpc from 'rn-webview-rpc/web';

Install from a CDN

Install from a CDN automatically

Let the React-Native's WebViewRpc inject an HTML script tag to the website, by setting the injectScriptTag prop to true:

<WebViewRpc
  ...
  injectScriptTag
/>
Install from a CDN manually

Add a script tag to your HTML's head:

<script src="https://cdn.jsdelivr.net/npm/[email protected]></script>

Either way (after a manual or automatic installation) the rnRpc object becomes available globally.

Warning: When manually installing rn-webview-rpc on the web end (either from NPM or CDN), it's your responsibility to make sure that both ends (React-Native and web) use compatible versions of rn-webview-rpc. However, when installing automatically from a CDN by using the injectScriptTag, this burden is inherently taken care of for you.

React-Native API - The WebViewRpc component

A React-Native component that renders a WebView component with a bi-directional RPC bridge.

Props

The following props are consumed by the rn-webview-rpc component. Additional props are forwarded to the react-native-webview's WebView component.

exposedObj

The React-Native object to be exposed to the web end.

  • Type: object
  • Default: {}

injectScriptTag

Controls whether to inject a script tag to automatically load the rn-webview-rpc module to the website.

  • Type: bool
  • Default: false

onMessage(listener)

Allows an extra custom listener to message events (except for the one that is already configured in order to take care of the RPC functionality).

  • Type: function
  • Default: undefined

In most cases, this prop should not be used.

target

An interface object for proxy calls. It is required for invoking calls from the React-Native end to the web end (using the rnRpc's proxy attribute).

  • Type: object
  • Default: {}

Methods and Attributes

Hint: A React class component instance is accessible using the ref prop, for example:

<WebViewRpc
    ref={(ref) => {
      this.webViewRpc = ref;
    }}
/>

proxy

An ES6 proxy polyfill that sends all operations performed on it to the web side. It is essentially a proxy object returned by Comlink's proxy function. However, due to limitations of the proxy polyfill (with respect to the ES6 proxy), it is limited to the interface defined beforehand by the target prop. This limitation will be resolved once React-Native updates its JavaScript engine to a modern one, probably in [email protected].

webView

A reference to the native WebView component instance.

Static Class Methods

proxyValue(value)

A wrapper function to let a parameter or a return value be proxied rather than copied. This is just a reference to Comlink's proxyValue function.

Web API - rnRpc

An object at the web end that provides a bi-directional RPC bridge to the native end.

Functions

proxy(target)

Creates an ES6 proxy that sends all operations performed on it to the native side. proxy() returns an ES6 proxy object, exactly like Comlink's proxy function.

In older browsers the proxy polyfill is used instead of the ES6 proxy. In that case, the target argument should define the interface object for proxy calls.

proxyValue

A wrapper function to let a parameter or a return value be proxied rather than copied. This is just a reference to Comlink's proxyValue function.

expose(obj)

Exposes an object to the native end. It just wraps Comlink's expose function.

Limitations

Exposing an object in the native side requires providing a target interface at creation time. This is because the JavaScript engine JavaScriptCore used by React-Native does not support the ES6 proxy object, and its polyfill proxy-polyfill is limited. Same applies for the web end for old browsers.

Example

See the example directory.

example gif

Under the Hood

Reading this section is most definitely optionally :)

The major pain coding this package was helping the delightful Comlink library to work in the native environment (and old browsers). Comlink is designed for web workers environment, and unfortunately the native JavaScript engine is more limited.

  1. WebView's messaging interface supports only string messages. Thankfully, solving this issue was easy, since the Comlink library already includes a MessageChannelAdapter, to support string based message channels, such as WebRTC. What remained to be done is to translate the postMessage/onMessage WebView's message API to a send/addEventListener endpoint.

  2. The ES6 proxy object is unsupported natively. This was solved using the Proxy Polyfill (with some limitations). Moreover, to allow proxy to work in React-Native, a few changes were required in Comlink.

  3. The MessageChannel and MessagePort objects are missing in the native environment. Since no polyfills are available, to address this problem I had to write pretty simple degenerated polyfills.

  4. More polyfills: The Object and ArrayBuffer behave slightly inconsistently in different environments. Hence, I have them overridden by polyfills when necessary.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].