How to set up a Monorepo with React Native You.I and Yarn Workspaces

BY ANDREI CALAZANS

/ 06/02/2020

In order to simplify dependency management, code reuse, and collaboration across teams, many projects have sought out to use the Monorepo structure.

In order to simplify dependency management, code reuse, and collaboration across teams, many projects have sought out to use the Monorepo structure. This post will outline how to achieve a Monorepo folder structure using React Native You.I alongside Yarn Workspaces.
Things this post covers:
How Yarn Workspaces work.
The errors Metro will throw.
Jest Testing.
A Possible Alternative.
Goal
Our goal is to have two apps in the same repository, and allow these two apps to use the same modules inside a directory named shared . We also want to be able to run tests separately for each app.
- apps - app_one - app_two - shared - module_one - module_two
Plain Text
You can go ahead and try to do this yourself, we will generate the apps using youi-tv cli , however, if you are not using React Native You.I, you can use the react-native-cli instead.
To achieve this goal we will:
Create The Repository
In the location you want to create the project, run the following commands in your terminal line to create the folders, initialize git, initialize yarn, and generate the apps.
Create Folders
mkdir monorepo
cd monorepo && git init
yarn init
mkdir apps
mkdir shared
Generate Apps
cd apps && youi-tv init app_one
cd apps && youi-tv init app_two
Create Shared Modules
cd shared && mkdir module_one && cd module_one && yarn init
Paste the following in your terminal to create the index.jsfile:
echo "import React from ‘react’; import { Text } from ‘react-native’; import { FormFactor } from ‘[@youi/react-native-youi](<http://twitter.com/youi/react-native-youi>)’; export function moduleOne() { return <Text>{FormFactor.isTV ? “Module one for TV” : “Module one for others”}</Text>; } " >> shared/module_one/index.js
Plain Text
cd shared && mkdir module_two && cd module_two && yarn init
Paste the following in your terminal to create the index.jsfile:
echo " export function moduleTwo() { return "Module Two"; } " >> shared/module_two/index.js
Plain Text
If you are following along, you should have the following structure by now:
Folder Hierarchy
Set Up Yarn Workspaces
According to the documentation we have to add the following configuration in our package.json file:
“workspaces”: { “packages”: [ “shared/*”, “apps/app_one”, “apps/app_two” ] },
Plain Text
This will allow our apps to access the shared packages.
Fixing Yarn Workspaces
Once you have added the configuration, you will have to delete all of your node_modules and install them again.
Run the following command in your terminal line to find all nested **node_modules, **delete them, and run yarn again:
find . -type dir -name node_modules | xargs rm -rf && yarn
Plain Text
Now that this is done, technically we should be able to build and start our app.
If you remember the youi-tv cli output:
Run `youi-tv docs` to see next steps. Or run the following (on platform OSX for example): cd app_two youi-tv build -p osx ./youi/build/osx/Debug/app_two
Plain Text
We should be able to do that and run the app. Let's try?
In app_one build an osx app by running: youi-tv build -p osx inside apps/app_one
Then, in that same directory, run yarn start
You will see the following error:
~/youi/monorepo/apps/app_one   master  yarn start yarn run v1.19.1 $ node node_modules/react-native/local-cli/cli.js start internal/modules/cjs/loader.js:895 throw err; ^ Error: Cannot find module ‘/Users/andrei/youi/monorepo/apps/app_one/node_modules/react-native/local-cli/cli.js’ at Function.Module._resolveFilename (internal/modules/cjs/loader.js:892:15) at Function.Module._load (internal/modules/cjs/loader.js:785:27) at Function.Module.runMain (internal/modules/cjs/loader.js:1143:12) at internal/main/run_main_module.js:16:11 { code: ‘MODULE_NOT_FOUND’, requireStack: [] } error Command failed with exit code 1. info Visit [<https://yarnpkg.com/en/docs/cli/run>](<https://yarnpkg.com/en/docs/cli/run>) for documentation about this command.
Plain Text
What is happening? If you look inside <root>/apps/app_one/package.json the start script tries to call cli.js with a relative path. And since we are using workspaces, all of our dependencies were lifted up to the root of the project, therefore, they are no longer inside <root>/apps/app_one/node_modules , they are instead in <root>/node_modules.
We can fix this by using the symlink of React Native provided by yarn
Replace both start and react-native scripts with the following:
“start”: “react-native start”, “react-native”: “react-native”,
Plain Text
*Note, the react-native script here is required because when we bundle the JavaScript code, our Cmake config runs yarn react-native bundle to achieve this. If you are using just **React Native *omit that script.
Does yarn start work now?
Yes, it should. You can run yarn start to test it. Now since you generated the osx app, you can run it directly from the terminal line with the following command inside the app_one directory:

Content Management with Gatsby, Contentful & Netlify

Babs Craig /

02/18/2019

Gatsby, Contentful, Netlify — The Triple Threat For Content Management Success

Focus Management with React Native on TV Plaforms

Guillermo Velásquez /

03/06/2019

Helping frontend / React engineers prepare for interviews with mock interviews

How to set up a Monorepo with React Native You.I and Yarn Workspaces

Andrei Calazans /

02/06/2020

In order to simplify dependency management, code reuse, and collaboration across teams, many projects have sought out to use the Monorepo structure.