Share code between React Native and React Web

This article explains a coexisting of react native and react web apps with similar to monorepo workspaces behavior, but without sharing node_modules dependencies.

All web workspaces remain workspaces, mobile just acts like workspace.

I’ve had an exi…


This content originally appeared on DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» and was authored by Rita

This article explains a coexisting of react native and react web apps with similar to monorepo workspaces behavior, but without sharing node_modules dependencies.

All web workspaces remain workspaces, mobile just acts like workspace.

I've had an existing huge web monorepo. Yarn's nohoist setup, or editing metro configuration wasn't working for me because this monorepo contains a lot of dependencies incompatible with react native. But it might work for you and might be a better solution.

TL;DR

  1. You need to update metro config to handle sources outside of react native project.
  2. Setup mobile project's babel config with aliases to shared folders.
  3. Enjoy the magic ✨

Minimal working example [repo]

This article expects that you know how to create yarn workspaces monorepo. If not, please, read docs here.

Also, I have example repo with mobile and web sharing some code.

1. Create folder which needs to be shared

Let's say, we have our workspaces in the folder projects, like this:

β”œβ”€β”€ projects
β”‚   β”œβ”€β”€ web
β”‚   └── ...  (means here can be lots of files)
β”œβ”€β”€ package.json
...

Add a new workspace, which will contain shared files for both mobile and web.

  β”œβ”€β”€ projects
+ |   β”œβ”€β”€ shared
+ |   |   β”œβ”€β”€ src
+ |   |   β”œβ”€β”€ index.js
+ |   |   └── package.json
  β”‚   β”œβ”€β”€ web
  β”‚   └── ...
  β”œβ”€β”€ package.json
...
// package.json
{
  "name": "shared",
  "scripts": {
    ...
  },
  "dependencies": {
    ...
  }
}

// index.js
export { sayHello } from './src/sayHello'

// src/sayHello.js
export function sayHello() {
  return 'Hello world!';
}

2. Add shared to other workspaces

Now we need to add our shared folder into package.json files of other workspaces.

// web/package.json
{
  "name": "web",
  "scripts": {
    ...
  },
  "dependencies": {
+   "shared": "*" 
    ...
  }
}

and same of all other workspaces, where we want to use shared.
Then, to let yarn know what we did, run yarn install or just yarn.

Now we can do something like this:

// projects/web/src/somefile.ts

import { sayHello } from "shared";

sayHello();

3. Create react native application

React Native setup guide does a better job at explaining how to set up a new mobile app, or maybe you have your existing one. I'll skip this part, if you're not sure how to do this, docs are here.

You need to create a mobile app inside projects folder like this:

  └── projects
      β”œβ”€β”€ shared
      |   β”œβ”€β”€ src
      |   β”œβ”€β”€ index.ts
      |   └── package.json
      β”œβ”€β”€ web
+     └── mobile
+         |   β”œβ”€β”€ src
+         |   ...
+         β”œβ”€β”€ metro.config.js
+         β”œβ”€β”€ babel.config.js
+         └── package.json
...

And now the most important part.
We need to tell the metro where to find source files. If we don't do that, it'll only look inside the mobile folder.

const path = require("path");

const projectRoot = __dirname;

// store path to workspace root, in our case, one level above /projects
const workspaceRoot = path.resolve(projectRoot, "../../");

module.exports = {
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: true,
      },
    }),
  },

  // watch not only our mobile folder, but also root's folders
  // this will include @common
  watchFolders: [path.resolve(__dirname, workspaceRoot)],
  resolver: {
    nodeModulesPaths: [
      // Tell metro to resolve modules in /mobile folder
      // and if not found, then try to find modules in workspace
      path.resolve(projectRoot, "node_modules"),
      path.resolve(workspaceRoot, "node_modules"),
    ],
    // And to make thing above work:
    disableHierarchicalLookup: true,
  },
};

So what happens above:

  1. we tell metro to look for files everywhere (meaning in root dir)
  2. resolve node_modules from workspace root as well.

Second part is needed, because at some point shared code will use some packages, and they will be in root's node_modules

Okay, now metro sees codes from the shared folder, how to import them into a mobile project?

4. Import files from shared into mobile

Remember how we imported it on the web?

import { sayHello } from "shared";

It is possible, because shared is a workspace. It's like having yet another node module.

But mobile doesn't treat it as a workspace, we will import files directly. And to have similar experience as in web, we can use babel aliases:

yarn add -D babel-plugin-module-resolver

then

// mobile/babel.config.js
module.exports = {
  presets: ["module:metro-react-native-babel-preset"],
  plugins: [
    [
      "module-resolver",
      {
        root: ["./"],
        alias: {
          "shared": "../shared", // needed alias
        },
      },
    ],
  ],
};

And now we can do imports like this in mobile as well:

import { sayHello } from "shared";

At this point you'll be able to run mobile and web, and see how changes in shared code reflect on both.

I also recommend to add this line to root package.json, to have mobile packages installed from yarn command:

{
  "scripts": {
+   "postinstall": "cd ./projects/mobile && yarn"
  }
}

Minimal working example [repo]

Do you see any downsides to this approach? Please, let me know in the comments.


This content originally appeared on DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» and was authored by Rita


Print Share Comment Cite Upload Translate Updates
APA

Rita | Sciencx (2022-12-14T22:55:16+00:00) Share code between React Native and React Web. Retrieved from https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/

MLA
" » Share code between React Native and React Web." Rita | Sciencx - Wednesday December 14, 2022, https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/
HARVARD
Rita | Sciencx Wednesday December 14, 2022 » Share code between React Native and React Web., viewed ,<https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/>
VANCOUVER
Rita | Sciencx - » Share code between React Native and React Web. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/
CHICAGO
" » Share code between React Native and React Web." Rita | Sciencx - Accessed . https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/
IEEE
" » Share code between React Native and React Web." Rita | Sciencx [Online]. Available: https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/. [Accessed: ]
rf:citation
» Share code between React Native and React Web | Rita | Sciencx | https://www.scien.cx/2022/12/14/share-code-between-react-native-and-react-web/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.