I built an app with Expo and Webview

TLDR: I wanted to have a native app and it's specific features (push notifs, contacts API, etc.) with the deployment flexibility of a web app.

In general, I go for a web app.

For those wondering if they should go for a native app or a web app, I would say that if you can,

always go for the web app.

  • Web is free, native is proprietary. Meaning Apple and Google can review and reject whenever they want. The web won't.
  • Web is universal, you need one codebase to run on any platform: HTML/CSS/JS works everywhere. Not the case for Native, even if you use React Native.
  • Web is easier to deploy: just
    git push
    and you're done. Whereas you need to submit manually to the App Store and Google Play Store on every release.

But sometimes, I need specific features from native apps.

Actually, I think the only reason (appart from marketing) I would voluntarily go for a native app is for the traditionnaly missing features in web apps:

  • Push notifications
  • Contacts API

I say traditionnaly because now in 2023, you can have those features also on iOS, which wasn't the case in 2022.

That's right: PWA's now offers Push API and Contact Picker API, both Android and iOS!

But it's still a pain in the ass to enable them on iOS.

Check out how to enable Push notifications: how would you convince a noob to do that?

And what about the Contact Picker API ? Check that out, what kind of a UX is that...

I think Apple is doing that on purpose, because it's not in their interest that Contact Picker API or Push Notifications are available easily on the Web as they could lose a lot of trafic to their store. And we know they make a lot of money out there.

Too bad I've built a PWA for nothing. What if...

What if I could use the web app I've built, and wrap it in a native app, and have access to all the native features I want? Would Apple and Google accept it?

Well, I had done most of the work already, building the web app, so I did it.

I used Expo and Webview.

Expo is a framework that allows you to build native apps with React Native. It's a great tool, so simple to access all the native API's I needed, and sooo helpful to deploy on each store. I used to do a lot of bare React Native apps because earlier Expo wasn't allowing a few libraries I needed, but now it's all good, I'll go for Expo each time I can.

That being said, the how-to of getting the advantages of iOS/Android features within a Webview in a native app is the following

  1. Tell the webapp that it's running in a native app
  2. The webapp send a message to the native app to request a native feature
  3. The native app executes the native feature: permission and whatever else is needed
  4. The native app sends back the result to the webapp

An example is available below, to show the process. But if you want the whole code, you can find it here.


function App() {
  const onLoadEnd = () => {
    ref.current.injectJavaScript(`window.ENV.PLATFORM_OS = "${Platform.OS}";`);
    setTimeout(() => {
      SplashScreen.hideAsync();
    }, 2000);
  };

  const onPushNotification = (event) => {
    registerForPushNotificationsAsync().then((token) => {
      if (!token) {
        return;
      }
      ref.current.injectJavaScript(`window.onNativePushToken('${JSON.stringify(token)}');`);
    });
  };

  const onMessage = (event) => {
    switch (event.nativeEvent.data) {
      case "request-native-expo-push-permission":
        onPushNotification(event);
        break;
      default:
        break;
    }
  };

  return (
    
  );
}
      

Now, every fix I push is deployed in seconds, and still I got every native features I need.

Awesome 😎