A cross platform app with React in a monorepo

locropulenton
hello JS
Published in
4 min readMay 22, 2017

--

joining the pieces of code…

tldr; a cross platform mobile and web app should be developed in a monorepo, and you should plug the app into the base code and not on the other way around.

In this blog post I am focussing on the interoperability of alls apps built by React, and how the state, some basic behaviors, actions, user interfaces and some experiences can be arranged in order for it to be more modular.

While a backend project is usually divided into more than one NPM package, a cross platform app is suggested to be a monorepo.

The closer the code, the faster to write the code; they say, instead of having a git repository for each module which is considered a best practice when thinking in micro-services, it scales better to maintain your frontend code in a single repository.

To join all dependencies for all platforms within a single React app tends to make things faster in small projects but harder to maintain in big ones.

but … IT CAN WORK

When looking into the existing boilerplates for react-native-web, all of them are focused on the idea of sharing the package.json for android iOS and web, but mixing web and mobile platform is not good on the long term.

I found it is tempting to fall into that idea because of the following:

  • package.json is easier to maintain
  • babel-preset-react-native is recommended by react-native-web and by react-native.
  • react-native-web plays well with react-native
  • webpack well configured and the RN packager removes unnecessary out of the platform code.
  • jest can run in either platforms
  • you will have a monolithic bundle one way or another

The bad parts of not splitting the platform when it comes to the degree of modularity, the scalability and the maintainability of each platform:

  • your code is not portable
  • you might want a version of a given shared dependency in the web another one in the mobile
  • jest and flow can run in either platform but not in all ones
  • your favorite editor is not aware of the platform.

The platform should be a plugin

In an ideal world, the platform should be plugged into the code, not the code plugged into the platform.

From that statement some questions may arise such as of how should I orchestrate my app if I want it to run it in expo, a new version of react-native on iOS and on an stable one in Android?

Or what if I want to have an stable version of any given package like maps, in production environment, and an alpha version of the same package using expo?

Or what if I want to evaluate the performance when running it using haul vs using the metro bundler?

As of today when we talk about platform we mean ios, android, windows and web, but sketch, VR and videogames can be thought as a platform as well as in the future it could be the Web GL or an autonomous car.

Lerna to the rescue

Having a web-mobile project in a lerna-style monorepo could be a great choice when you aim to share JS logic in your app.

In addition to improving it architecturally, allow semantic releases, and symlinking your components, your app will scale much better on the long term.

For doing that you should have a module per platform, and consume shared modules using native iOS android and web file extensions as needed.

You can have peerDependencies on those ones so that each platform can define their specific version, but that should be handled carefully to avoid incompatibilities.

… and your code without being 100% platform agnostic, will be a step further from being platform specific.

react-native-web-workspace

I created this minimum boilerplate that has configured a react-native app packaged with haul sharing somes libraries with the web environment using react-native-web to have it as a usefull working example.

create-react-workspace

This great new project aims to solve out by the cli the way the code is shared between React web apps, React Native apps, and standalone libraries.
It’s in alpha stage but it looks promising on the long term.

--

--