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 🙏

© 2024 – Pkg Stats / Ryan Hefner

rn-webview-rpc

v2.1.0

Published

Adding RPC capabilities to the React Native WebView component

Downloads

126

Readme

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...

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.

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.