metro icon indicating copy to clipboard operation
metro copied to clipboard

Experimental symlink support not working for PNPM Monorepo

Open brownieboy opened this issue 1 year ago • 7 comments

Description

I have PNPM working with the new, experimental symlink support in RN 0.72.3. But it only works for me for a single RN package in a repo. It doesn't work for me in a Monorepo set up.

In my monorepo pnpm ios from the apps/app1 folder throws this error:

 BUNDLE  ./index.js

error: Error: Unable to resolve module react-native from /Users/michaelbrown/Development/test-rn72-pnpm-monorepo/apps/app1/index.js: react-native could not be found within the project or in these directories:
  node_modules
  ../../node_modules
  3 |  */
  4 |
> 5 | import {AppRegistry} from 'react-native';
    |                            ^
  6 | import App from './App';
  7 | import {name as appName} from './app.json';

pnpm android throws this error:

FAILURE: Build failed with an exception.

* Where:
Settings file '/Users/michaelbrown/Development/test-rn72-pnpm-monorepo/apps/app1/android/settings.gradle' line: 2

* What went wrong:
A problem occurred evaluating settings 'app1'.
> Could not read script '/Users/michaelbrown/Development/test-rn72-pnpm-monorepo/apps/app1/node_modules/@react-native-community/cli-platform-android/native_modules.gradle' as it does not exist.

react-native is in the apps/app1/node_modules folder, although it's a symlink (which is how PNPM works). That android/settings.gradle file also is there, and not as a symlink this time.

React Native Version

0.72.3

Output of npx react-native info

npx react-native info info Fetching system and libraries information... System: OS: macOS 13.3.1 CPU: (8) arm64 Apple M1 Memory: 68.48 MB / 16.00 GB Shell: version: "5.9" path: /bin/zsh Binaries: Node: version: 18.9.0 path: ~/Library/Caches/fnm_multishells/87821_1689716195576/bin/node Yarn: version: 1.22.19 path: ~/Library/Caches/fnm_multishells/87821_1689716195576/bin/yarn npm: version: 8.19.1 path: ~/Library/Caches/fnm_multishells/87821_1689716195576/bin/npm Watchman: version: 2023.06.12.00 path: /opt/homebrew/bin/watchman Managers: CocoaPods: version: 1.12.1 path: /Users/michaelbrown/.rvm/gems/ruby-3.0.0/bin/pod SDKs: iOS SDK: Platforms: - DriverKit 22.4 - iOS 16.4 - macOS 13.3 - tvOS 16.4 - watchOS 9.4 Android SDK: API Levels: - "29" - "30" - "31" - "32" - "33" Build Tools: - 29.0.2 - 30.0.2 - 30.0.3 - 31.0.0 - 32.0.0 - 32.1.0 - 33.0.0 System Images: - android-29 | Google APIs Intel x86 Atom_64 - android-31 | Google APIs ARM 64 v8a - android-31 | Google Play ARM 64 v8a - android-32 | Google APIs ARM 64 v8a - android-32 | Google Play ARM 64 v8a Android NDK: Not Found IDEs: Android Studio: 2021.3 AI-213.7172.25.2113.9123335 Xcode: version: 14.3.1/14E300c path: /usr/bin/xcodebuild Languages: Java: version: 11.0.11 path: /usr/bin/javac Ruby: version: 3.0.0 path: /Users/michaelbrown/.rvm/rubies/ruby-3.0.0/bin/ruby npmPackages: "@react-native-community/cli": Not Found react: installed: 18.2.0 wanted: 18.2.0 react-native: installed: 0.72.3 wanted: 0.72.3 react-native-macos: Not Found npmGlobalPackages: "react-native": Not Found Android: hermesEnabled: true newArchEnabled: false iOS: hermesEnabled: true newArchEnabled: false

Steps to reproduce

mkdir test-rn72-pnpm-monorepo
cd test-rn72-pnpm-monorepo
mkdir apps
cd apps
npx react-native@latest init app1
cd app1
rm yarn.lock
rm -rf node_modules
cd ../..
npm init -y

Add new file, pnpm-workspace.yaml at root repo level:

packages:
  # all packages in direct subdirs of packages/
  - 'apps/*'

That file is required for PNPM monorepo support, as PNPM does not use the packages field in the package.json.

Run pnpm i to (re)install the dependencies.

Enable the experimental symlink support in file apps/app1/metro.config.js:

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
  resolver: {
    unstable_enableSymlinks: true,
    unstable_enablePackageExports: true,
  },
};

module.exports = mergeConfig(getDefaultConfig(__dirname), config);

Snack, code example, screenshot, or link to a repository

https://github.com/brownieboy/test-rn72-pnpm-monorepo

brownieboy avatar Jul 19 '23 04:07 brownieboy

Moving to metro

cortinico avatar Jul 19 '23 08:07 cortinico

Managed to get it working by adding watchFolders. Here is my config example:

const config = {
  watchFolders: [path.join(__dirname, '..', '..')],
  resolver: {
    unstable_enableSymlinks: true,
    unstable_enablePackageExports: true,
  },
};

uxigene avatar Jul 25 '23 14:07 uxigene

@uxigene,

  watchFolders: [path.join(__dirname, '..', '..')],

Many thanks! Yes, that worked for me too 😊, although I'm not sure why that works 🤔.

You need to add the path import at the top of the file (metro.config.js) too, of course:

const path = require('path');

brownieboy avatar Jul 25 '23 22:07 brownieboy

This doesn't seem to work for me, same error as the above on android, even after clearing builds, cache etc, @brownieboy @uxigene please can you update the repo with the working builds.

Also, can you please say specifically what node version, pnpm version you are using.

It seems very flaky.

MartinDawson avatar Oct 05 '23 08:10 MartinDawson

For those using Expo SDK 50 + RN 0.73 with pnpm, it seems there are other file resolution issues too:

  • https://github.com/expo/expo/issues/22413#issuecomment-1913169577

karlhorky avatar Jan 27 '24 14:01 karlhorky