Expo-webでwebviewを使う


Expoはreact-nativeでの開発を楽にするためのラッパーというか開発ツールです。
SDKのバージョンのいくつかから、react-native-webを使ってWebアプリ開発も同時にできるようになりました。
iOS/Androidと同時に、Webも作れてしまうというものです。
ざっと使ってみた感じ、凝ったUIでなければ、重たいけど割とそのまま動いている印象です。

Expo-webはWebViewに非対応

自分の作っているExpoのアプリで、WebViewを使っている部分がありました。下のとおりExpo-webは現時点(SDK41)で、WebViewには非対応です。

そこで、WebViewのほうは変えないまま対応する方法を探したところ react-native-web-webview というのを発見しました。

react-native-web-webview を使う方法について書きます。

react-native-web-webview のための設定

このパッケージ自体は適当にググった結果見つけていたのですが、設定のドキュメント読んでも、よくわかりませんでした。

しばらく放置してましたがこのZennの本を参考にようやく実装方法を理解しました。その他全般の理解に役立ったので、ExpoでのWeb対応を考えている方は読むといいかもしれません。

webpack.config.js の生成

まず、やるべきことは、Web向けに独自の設定を入れるために webpack.config.js ファイルを生成します。以下のコマンドを叩きます。

$expo customize:web

webpack.config.jsの設定

生成された webpack.config.js に、react-native-web-webviewの設定を追記します。

const createExpoWebpackConfigAsync = require("@expo/webpack-config");

module.exports = async function (env, argv) {
  const config = await createExpoWebpackConfigAsync(env, argv);
  // Customize the config before returning it.
  config.module.rules.push({
    test: /postMock.html$/,
    use: {
      loader: "file-loader",
      options: {
        name: "[name].[ext]",
      },
    },
  });
  config.resolve.alias = {
    "react-native": "react-native-web",
    "react-native-webview": "react-native-web-webview",
  };
  return config;
};

これで、yarn web でwebアプリを起動したときに、ネイティブ部分でWebviewだったところが、iFrameで呼ばれるようになります。

postMessage部分の修正

react-native-webviewでは、アプリ本体とデータをやり取りする際に以下のようにpostMessageで送ります。しかし、Webになると window.ReactNativeWebView がいません。

window.ReactNativeWebView.postMessage(postObject);

Expo-webでiFrameとして読み込んだ場合は window.parent にメッセージを送ります。
同じドメインで読み込んでいる場合はサンプルコードの通り、 window.parent.origin を指定すればいいでしょう。自分の場合は違うドメインのものを読み込んでいたので、別のものを指定しています。

window.parent.postMessage(postObject, 'https://yourdomain.com');

自分の実装では、この2つのパターンはWebViewで呼ばれる側のウェブサーバーで出し分けています。

以上のようなやり方で、Expo-webでWebViewが使えるようになりました。おしまい。