All Projects → jsamr → yarnberry-expo-quickstarter

jsamr / yarnberry-expo-quickstarter

Licence: other
Yarn 2 (berry) + React Native / Expo has never been so easy

Programming Languages

javascript
184084 projects - #8 most used programming language

⚠️ This repository uses expo for illustration purposes, but it works equally well with “vanilla” React Native

Use Expo / React Native with Yarn 2 and Workspaces

Latest tested Expo SDK: 44
Latest tested yarn version: 3.2.0
PRs welcome to upgrade Expo SDK and yarn versions.

Goal

The goal of this project is to have the workspace expo-client depend on workspace common.

yarn install
yarn workspace expo-client start

Steps

Install yarn 2.3+

You need yarn version 2.3+

yarn set version berry

Use node-modules linker

Add this line to your .yarnrc.yml, see explanation here.

nodeLinker: node-modules

Setting up hoistingLimits

In the workspace using React Native or Expo, add this to package.json file:

{
  //...
  "installConfig": {
    "hoistingLimits": "workspaces"
  }
}

This is a central piece: it prevents react-native and other packages to be hoisted to the root node_modules folder. It replaces the outdated nohoist config from yarn 1.

Customize metro.config.js

This latest step will help metro identify how to resolve workspace dependencies (those specified with the workspace protocol). To address the issue of workspaces being symlinked by yarn, we use the Proxy trick:

const path = require("path");
const fs = require("fs");
const { getDefaultConfig } = require("expo/metro-config");

const workspaces = fs.readdirSync(path.resolve(__dirname, "../"));
const currentWorkspace = path.basename(__dirname);

module.exports = (async () => {
  const expoMetroConfig = await getDefaultConfig(__dirname);
  return {
    ...expoMetroConfig,
    projectRoot: __dirname,
    watchFolders: workspaces
      .filter((f) => f !== currentWorkspace)
      .map((f) => path.join(__dirname, "../", f)),
    resolver: {
      extraNodeModules: new Proxy(
        {},
        {
          get: (target, name) => path.join(__dirname, `node_modules/${name}`),
        }
      ),
    },
    transformer: {
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: true,
        },
      }),
    },
  };
})();

You will need to replace commonModulePath with any workspace path you'd like to import. If your project follows a pattern where all workspaces are under the same folder, you can automate the process easily. See how it is implemented in this project.

Remark: Extending expo/metro-config is required since Expo SDK 41 but must not be used in a vanilla React Native projects or Expo SDK 40 and lower versions.

Support for EAS builds (Optional)

EAS builds will almost work out of the box with one hurdle: the pre-build step. Because EAS will tamper with the package.json file to add required dependencies for the build step, and engage with a yarn install. The latest will fail since yarn berry sets the immutable flag when the CI environment is present.

Fortunately, you can force the immutable flag off by setting the YARN_ENABLE_IMMUTABLE_INSTALLS env to false. Just patch your eas.json file:

diff --git a/packages/expo-client/eas.json b/packages/expo-client/eas.json
index 15b318c..d142455 100644
--- a/packages/expo-client/eas.json
+++ b/packages/expo-client/eas.json
@@ -7,7 +7,11 @@
     "preview": {
       "distribution": "internal"
     },
-    "production": {}
+    "production": {
+      "env": {
+        "YARN_ENABLE_IMMUTABLE_INSTALLS": "false"
+      }
+    }
   },
   "submit": {
     "production": {}

Fixing duplicated React versions

If you have mismatched React versions between your expo-client package and workspace dependencies, you will run into failures. Make sure all React versions match. You can audit this with the below command:

yarn why react

If only one react version is resolved, you will be fine. You can also force the resolution to a specific version via the resolutions field of your root package.json. This can be done via the following command:

yarn set resolution -s react@npm 17.0.1
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].