Monorepos and Unimodules - do they all need to be symlinked?

I’m following the advice in the Mods preview docs to setup a monorepo using expo-yarn-workspaces. It says you need to sometimes add packages to "expo-yarn-workspaces.symlinks in package.json in order for things to work. I noticed when I ran pod install, it didn’t install any of my unimodules to my Podfile.lock. So, I added one to the symlinks list, ran yarn and pod install again, and it worked.

Is it indeed the case that I need to add every single unimodule to that symlinks list, or am I doing something wrong? I was trying to crib the setup of the bare workflow test project on Expo, and it has some unimodules listed in symlinks, but not all of the unimodules that are listed in dependencies, so I’m not sure how that works.


So, I tried adding all of my “expo-” modules to the symlinks list, but, oddly, they still didn’t install. So then I went back to the bare-expo test project in the Expo repo, and cribbed their Podfile and package.json, which involved adding the expo-modules-core packaging, and setting my Podfile to this:

install! 'cocoapods',
         generate_multiple_pod_projects: true,
         incremental_installation: true
source ''
platform :ios, '11.0'

# Import the auto-linking packages
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")
require File.join(File.dirname(`node --print "require.resolve('expo-modules-core/package.json')"`), "scripts/autolinking")

target 'nudgev4' do
  config = use_native_modules!

  use_react_native!(:path => config["reactNativePath"])

  # Uncomment to opt-in to using Flipper
  # if !ENV['CI']
  #   use_flipper!('Flipper' => '0.75.1', 'Flipper-Folly' => '2.5.3', 'Flipper-RSocket' => '1.3.1')
  #   post_install do |installer|
  #     flipper_post_install(installer)
  #   end
  # end

(basically the same as the bare-expo project, minus the Flipper stuff, because I removed all that).

Then, all my unimodules installed… without adding them to symlinks. Now my Podfile.lock looks almost the same as it did originally (minus the UMCore stuff). But, I should note that this is very different from the standard Podfile that comes out of expo eject. I don’t see anything in expo-yarn-workspaces docs about changing the Podfile around.

Hey Keith! You are running into an in-between state at the moment. Let me explain the two things separately.

We are actively working on expo-modules-core, which should be a replacement for some core stuff from unimodules. It’s something that we only have partially released for testing purposes, so that might change a bit. But, with this newer system, we are trying to improve the monorepo setup and maintenance requirement.

As you can see, your podfile now contains node --print "require.resolve('...')". This basically lets Node decide where the node_modules folder is. With the older unimodules, we just hardcoded the paths to something like ../../node_modules, which is the relative path from the ios podfile to your app’s node_modules.

Now with the older unimodules, and thus hardcoded paths, you’d actually need to symlink the packages into the app’s folder. Especially when hoisted in the root of your monorepo. That was the job of expo-yarn-workspaces, using the expo-yarn-workspaces postinstall command.

There will be better docs, but for now you can find more info in expo-modules-core and expo-modules-autolinking. For now, I would recommend sticking with unimodules (even though it states that it is deprecated).

Hope this helps!

Thanks, Cedric! So, are you saying I should go back to the stock Expo 42 Podfile and add all the unimodules to the symlinks list? The only mystery there is, the last time I did that, cocoapods still didn’t install most of my unimodules, and it threw an error about UMCore missing. I do have the postinstall command in there.

Ohhh… I think I’m starting to get it- I need to add the node modules for those require statements in the Podfile, as well as any dependencies of my unimodules. So, I added the following to symlinks:


and then started adding my unimodules, and now they’re installing

1 Like

We’re also hitting this and I’m not quite following the workaround here. I’ve tried:


require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
require File.join(File.dirname(`node --print "require.resolve('react-native-unimodules/package.json')"`), "cocoapods.rb")
require File.join(File.dirname(`node --print "require.resolve('expo-modules-core/package.json')"`), "scripts/autolinking")

to the Podfile but it results in a

 Invalid `Podfile` file: cannot load such file -- /Users/benrudolph/projects/peregrine-frontend/node_modules/expo-modules-core/scripts/autolinking.

which makes sense cause that file does not exist (note that I did add expo-modules-core to the postinstall symlink). I’m just seeing that the scripts directory is not in that module, though I do see it on github.

We were able to resolve this and for folks who also ran into this:

  1. Do not modify the auto-generated Podfile in the ios directory, instead rely on expo-workspaces
  2. Ensure that the expo-yarn-workspaces contains all the necessary packages to be symlinked so that the build can find the project.

I got a lot of value at studying the list that was linked to above: eas-monorepo-example/package.json at main · byCedric/eas-monorepo-example · GitHub