Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

yarn workspaces + metro 0.30 #171

Closed
Ashoat opened this issue May 15, 2018 · 8 comments
Closed

yarn workspaces + metro 0.30 #171

Ashoat opened this issue May 15, 2018 · 8 comments

Comments

@Ashoat
Copy link

Ashoat commented May 15, 2018

Problem

I am trying to upgrade from [email protected] and [email protected] to [email protected] and [email protected]. I'm on macOS and using [email protected] with its "workspaces" feature. I did not initially have a rn-cli.config.js.

After upgrading, whenever I try to get Metro to generate a bundle, I get the following error:

error: bundling failed: Error: Unable to resolve module `./../node_modules/react-transform-hmr/lib/index.js` from `/Users/ashoat/Dropbox/src/Sites/squadcal/native/app.react.js`: The module `./../node_modules/react-transform-hmr/lib/index.js` could not be found from `/Users/ashoat/Dropbox/src/Sites/squadcal/native/app.react.js`. Indeed, none of these files exist:
  * `/Users/ashoat/Dropbox/src/Sites/squadcal/node_modules/react-transform-hmr/lib/index.js(.native||.ios.js|.native.js|.js|.ios.json|.native.json|.json)`
  * `/Users/ashoat/Dropbox/src/Sites/squadcal/node_modules/react-transform-hmr/lib/index.js/index(.native||.ios.js|.native.js|.js|.ios.json|.native.json|.json)`

Analysis

In fact, /Users/ashoat/Dropbox/src/Sites/squadcal/node_modules/react-transform-hmr/lib/index.js does exist. However, it is outside the list of watched directories printed when Metro is started. react-transform-hmr is the third module/file that Metro tries to resolve when bundling my application, after my app entry point, and react-native.

Before upgrading, this was the list of watched directories. The list included all four of my workspaces, as well as the root folder of the monorepo. The root folder of the monorepo is the one that contains react-transform-hmr, as it is a "secondary" dependency (ie. dependency of a dependency), and yarn workspaces put those in the root folder. I presume that since the root folder was in the list of watched directories, the previous version of metro was able to resolve things correctly.

After upgrading, this is the list of watched directories. Note that it is much shorter, does not include all the workspaces, and notably does not include the root folder of the monorepo.

Attempted solutions

My initial read of the situation was that I should create a rn-cli.config.js with a getProjectRoots that includes the root folder of the monorepo. That would presumably enable Metro to resolve it.

However, when I tried that, I got an error regarding ambiguous resolution of react-native: https://gist.github.com/Ashoat/7c4b41c063391cd1c3c59d38bc23d71a

I get the ambiguous resolution error even when I set up my getProjectRoots to return only two folders, the project folder (native) and the root folder.

I've also tried using the metro-bundler-config-yarn-workspaces NPM package, which provides a custom rn-cli.config.js that attempts to (a) include the right folders in getProjectRoots, (b) blacklist the duplicate react-native package. However, the custom blacklist doesn't seem to prevent the ambiguous resolution error. I've also tried to write my own custom blacklist to no avail.

Here is my current rn-cli.config.js:

const blacklist = require('metro/src/blacklist');
module.exports = {
  getBlacklistRE() {
    return blacklist([
      /native\/node_modules\/react-native\//,
    ]);
  },
  getProjectRoots() {
    return [
      "/Users/ashoat/Dropbox/src/Sites/squadcal/native",
      "/Users/ashoat/Dropbox/src/Sites/squadcal",
    ];
  },
}

Plead

I've been banging on my head on this problem for two days now. Would appreciate any help I can get, even if it's just an explanation of what may have changed from [email protected] to [email protected] that could've caused this.

Thanks for reading.

@Ashoat
Copy link
Author

Ashoat commented May 15, 2018

I was finally able to resolve this issue by following the instructions here: https://github.com/viewstools/yarn-workspaces-cra-crna#native

For anybody who stumbles on this issue, and is using a vanilla React Native config without Expo, the steps you need to follow start with yarn add --dev metro-bundler-config-yarn-workspaces crna-make-symlinks-for-yarn-workspaces and end with "prestart": "node link-workspaces.js".

My only remaining questions are:

  1. What changes were made that necessitate the use of these two packages? Everything used to be fine without the extra config.
  2. I assume the changes we necessary to enable/fix something else. Wondering - is there a world where those issues are fixed, but out-of-the-box compatibility with yarn workspaces is preserved?

Anyways, thanks team for all your hard work helping to support the open source community. Feel free to close this issue. (I'm leaving it open in hopes of getting answers to the above questions.)

@Ashoat Ashoat closed this as completed Jul 16, 2018
@pronebird
Copy link

@Ashoat could you please reopen this issue because it's not solved :)

There is something cheesy going on in React-Native or/and Metro and worth to be investigated and fixed. I have electron-based app that works just fine with workspaces with zero tweaks, I wonder why react-native and/or metro are so buggy.

@aleclarson
Copy link
Contributor

Yarn workspaces use symlinks, which are not currently supported. See this comment.

@Ashoat
Copy link
Author

Ashoat commented Jan 30, 2019

It's very much still doable with a custom metro.config.js, though #257 would certainly be an improvement.

@jonathanconway
Copy link

I'm thinking of patching this issue by writing an NPM script that watches for changes and automatically copies my intra-workspace builds to the node_modules folder, overwriting if they already exist.

@flybayer
Copy link

For anyone who lands here like I did, here's how to get workspaces working with importing code from another workspace:

// package.json
  "devDependencies": {
    ...
    "expo-yarn-workspaces": "1.2.1"
  },
  "workspaces": {
    "nohoist": [
      "react-native",
      "react-native-*",
      "react-native/**",
      "expo-yarn-workspaces"
    ]
  }
// metro.config.js
const { createMetroConfiguration } = require("expo-yarn-workspaces")

const config = createMetroConfiguration(__dirname)

// Make react-native import from files in other workspace resolve to node_modules in this dir
config.resolver.extraNodeModules["react-native"] = `${__dirname}/node_modules/react-native`

// Default metro config
config.transformer.getTransformOptions = async () => ({
  transform: {
    experimentalImportSupport: false,
    inlineRequires: false,
  },
})

module.exports = config

@Maushundb
Copy link

Hey @flybayer was that package.json the one at your workspace root or in your RN package? Did you do any of the other steps at https://github.com/expo/expo/tree/master/packages/expo-yarn-workspaces in addition to your metro config?

@flybayer
Copy link

@Maushundb in the RN package.

However, I ran into blocking issues with that approach and am now hoisting everything.

// <root>/native/metro.config.js
const path = require("path")

module.exports = {
  projectRoot: path.resolve(__dirname, "../"),
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
}

and change your Podfile to be like this

// <root>/native/ios/Podfile
...
  pod 'React', :path => '../../node_modules/react-native/'
  pod 'React-Core', :path => '../../node_modules/react-native/'
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants