Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native in yarn workspaces not resolving external packages

I am using yarn workspaces to create monorepo for react and react-native. I tried to add redux to @app/common and it works fine with react, but it is not resolving in native. You can see the source at https://github.com/Faisal-Manzer/react-and-react-native-monorepo/tree/08-redux.

When loading bundle it is giving the following error.

error: Error: Unable to resolve module `redux` from `../common/reducers/index.js`: redux could not be found within the project or in these directories:
  ../../node_modules

If you are sure the module exists, try these steps:
 1. Clear watchman watches: watchman watch-del-all
 2. Delete node_modules: rm -rf node_modules and run yarn install
 3. Reset Metro's cache: yarn start --reset-cache
 4. Remove the cache: rm -rf /tmp/metro-*
    at ModuleResolver.resolveDependency (/Users/user/monorepo/packages/native/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:186:15)
    at ResolutionRequest.resolveDependency (/Users/user/monorepo/packages/native/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:52:18)
    at DependencyGraph.resolveDependency (/Users/user/monorepo/packages/native/node_modules/metro/src/node-haste/DependencyGraph.js:287:16)
    at Object.resolve (/Users/user/monorepo/packages/native/node_modules/metro/src/lib/transformHelpers.js:267:42)
    at /Users/user/monorepo/packages/native/node_modules/metro/src/DeltaBundler/traverseDependencies.js:434:31
    at Array.map (<anonymous>)
    at resolveDependencies (/Users/user/monorepo/packages/native/node_modules/metro/src/DeltaBundler/traverseDependencies.js:431:18)
    at /Users/user/monorepo/packages/native/node_modules/metro/src/DeltaBundler/traverseDependencies.js:275:33
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/Users/user/monorepo/packages/native/node_modules/metro/src/DeltaBundler/traverseDependencies.js:87:24)

packages
   |-- common
   |    |-- reducers
   |    |    |-- index.js
   |    |    |-- demo.js
   |    |-- package.json
   |-- web
   |    |-- package.json
   |-- native
   |    |-- metro.conf.js
   |    |-- App.js
   |    |-- package.json
package.json

package.json

{
  "private": true,
  "workspaces": [
    "packages/*"
  ],
  ...
}

packages/common/package.json

{
  "name": "@app/common",
  "version": "0.0.1",
  "private": true,
  "dependencies": {
    "hoist-non-react-statics": "^3.3.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-native": "^0.62.2",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2"
  }
}

packages/native/package.json

{
  "name": "@app/native",
  "version": "0.0.1",
  "private": true,
  "workspaces": {
    "nohoist": [
      "**"
    ]
  },
  "dependencies": {
    "@app/common": "0.0.1",
    "get-yarn-workspaces": "^1.0.2",
    "hoist-non-react-statics": "^3.3.2",
    "react": "^16.13.1",
    "react-native": "0.62.2",
    "react-redux": "^7.2.0",
    "redux": "^4.0.5",
    ...
  },
  "devDependencies": {
    "@babel/core": "^7.6.2",
    "@babel/runtime": "^7.6.2",
    ...
  },
  ...
}
// packages/native/App.js

import React, {useEffect} from 'react';

import {Provider} from 'react-redux';
import {store} from '@app/common/reducers';

const App = () => {
    return (
        <Provider store={store}>
            ....
        </>
    );
};

export default App;

// packages/common/reducers/index.js
import {combineReducers, createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';

import {demo} from './demo';

const reducers = combineReducers({
    demo
});

export const store = createStore(reducers, applyMiddleware(thunk));
like image 626
Faisal Manzer Avatar asked Mar 02 '23 10:03

Faisal Manzer


1 Answers

Actually metro is not looking into root node_modules where all of @app/common dependencies are installing. You need to add the root node_modules to metro's watchFolders.

// metro.conf.js

function getConfig(appDir, options = {}) {
    return {
        watchFolders: [
        ...,
        path.resolve(appDir, '../../node_modules')
        ]
    }
}

module.export = getConfig(__dirname);

You can see full metro.conf.js at https://github.com/Faisal-Manzer/react-and-react-native-monorepo/blob/08-redux/packages/native/metro.config.js#L19

like image 115
Faisal Manzer Avatar answered Mar 05 '23 14:03

Faisal Manzer