I love the web, but I spent a large portion of the last few years woking on native apps. I had a dream of consolidating two applications onto a single tech stack. We did it, but I learned a lot of lessons and maybe would do it again differently.
We started as a small team needed to support two different codebases that did essentially the same thing. A mobile app that let customers perform self service actions, and a website that did the same thing. Even a lot of the designs between all of the products looked very similar. I had an idea after listening to a talk on react-native-web. Why can't we do the same thing?
Imagine a world where you took react-native primatives and had them just render to web primatives. A react-native application is in fact mostly just JavaScript. If one is using a state management solution such as Redux, MobX, or Apollo, you can even just write all that logic once. It allows you to treat your entire front end as a monolithic application with a single source of truth for business logic and state.
All React really adds outside of javascript is the additional JSX elements,
which are in the end just transpiled down to js anyway. Could these be
abstracted? Easy to think about with View
Text
A new showdown really happening in the application development space is a battle between the web and native apps. Interesting schisms have formed in that a PWA can look like an app, but actually be written like a website. Browsers even allow for system calls to access things like sensors and cameras that apps have historically had a leg up on.
Often, apps have an advantage with performace as they can things a little bit closer to the metal. There's less overhead. With more direct access to the operating system, there is more things apps can do to make them performant. That's not to say websites can't be through new static site generation techniques, prerendering, bundle splitting, etc. There's just a level of overhead that a browser and js engine will always have.
Native apps also have access to specific things such as a customer's MAC address, device id, and contacts. Things often not important to a the performace of an application, but very important to collecting data for advertisment purposes.
If I were to architect another application like I did in the past, I'd take an extreme focus on creating universal components. Universal components are often as easy to think of as maybe just a button. These buttons could all be a certain color, have a certain roundness, and be sized consistently. Universal component may also be as complex as something like layout where things get arranged on the screen consistently as the viewport changes sizes. They may also include business logic. In fact, commonalities between business logic are probably the most important part as that's where the majority of bugs get introduced into things.
I liked to think of things in 3 parts: Data, Layout, Visual.
Any code between that should be a page's actual implamentation. Say you have a data layer to get a customer name and then do some action.
import React from "react";import { useCustomerName, useAction } from "./my-actions";import { Layout } from "./my-layout";import { Title, Button } from "./my-lib";export const UniversalComponent = () => {const { name } = useCustomerName();const { action } = useAction();return (<Layout><Title>{name}</Title><ButtontestID="my-button"accessibilityLabel="Perform the action"onPress={action}>Do this</Title></Layout>);};
In a way, this actually isn't different that good construction of regular react components. But where do things get specific?
The abstractions for some things such as routing aren't great. There's also platform specific elements that will occasionally catch you.
You can make your own kind of music in the form of abstractions as well. For
example for analytics, it may make sense to just make a react hook called
useTrackEvent
I think I would still do it all over again. I would probably be a lot more careful about crafting these components. A suggested way of putting the project togeather would be to use a monorepo similar to this template and to keep your components in between the platforms that you're developing.
There's also lots of tools that really make the process go a lot smoother today too. Expo is modular and can run on native platforms and the web. Component libraries are a lot more built out and meant to work on both. I wrote and open sourced a few utilities too that abstracted away a lot of the common problems that I ran into:
In a way, I wish I could just write PWAs. Safari unfortunately does not furfill the entire PWA spec. There's also often a somewhat dark side to app development in that your data is being harvested to create things like device graphs and relations between you and your contacts. Like it or not, this is nearly the entire point of sites like Facebook, Twitter, and Google and why they all have native apps. Many would rather give this data than write a check to use an app or social network, and that's ok.