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

With symlinked packages: Error: Unable to resolve module @scope/ui from /some/path.js: Module @scope/ui does not exist in the Haste module map #286

Open
mxmzb opened this issue Oct 8, 2018 · 8 comments

Comments

@mxmzb
Copy link

mxmzb commented Oct 8, 2018

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

I have a lerna monorepo where i decided to scope the packages inside. When I run lerna link --force-local (which essentially symlinks my local packages inside of others if they are mentioned in the package.json) my React Native app at some point will have the following directory in it: ./node_modules/@scope/ui and ui is the symlinked directory.

If I now start the metro bundler and run the app, it will throw following error:

error: bundling failed: Error: Unable to resolve module `@scope/ui` from `/Projects/myMainLerna/packages/myRnApp/index.js`: Module `@scope/ui` does not exist in the Haste module map

I have seen all the other issues around this like facebook/react-native#4968 and #241 and many others, but this is something unrelated to the causes in the other issues.

How do I know it's a problem with symlinked packages? I simply threw a real copy of my package into my ./node_modules/@scope/ui and it started working. It might be though that symlinked packages, if not put into a scope directory, work - I don't know because I didn't try that one.

How to reproduce and a minimal repository on GitHub

https://github.com/mxmzb/MetroLinkedHasteExample and follow the README instructions

What is the expected behavior?

App finds and uses the package.

Please provide your exact Metro configuration and mention your Metro, node, yarn/npm version and operating system.

Note: it doesn't seem to matter if I use yarn or npm.

Metro configuration: As it comes with React Native
node: 8.12.0
yarn: 1.10.1
npm: 6.4.1
All on macOS

@nickarora
Copy link

nickarora commented Oct 11, 2018

We are dealing with a similar issue using yarn workspaces. Attempts to work around it using extraNodeModules were unsuccessful. Would appreciate if the maintainers could offer recommendations

@rochapablo
Copy link

rochapablo commented Oct 30, 2018

I believe that I'm getting the same problem. Before upgrade the React Native, it was working, but now I'm getting

Loading dependency graph, done.
error: bundling failed: Error: Unable to resolve module `../../../../src/store` from `C:\...rn-app\src\app.tsx`: The module `../../../../src/store` could not be found from `C:\...rn-app\src\app.tsx`. Indeed, none of these files exist:
  * `C:\src\store(.native||.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)`
  * `C:\src\store\index(.native||.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)`
    at ModuleResolver.resolveDependency (C:\...rn-app\node_modules\metro\src\node-haste\DependencyGraph\ModuleResolution.js:120:15)
    at ResolutionRequest.resolveDependency (C:\...rn-app\node_modules\metro\src\node-haste\DependencyGraph\ResolutionRequest.js:49:18)
    at DependencyGraph.resolveDependency (C:\...rn-app\node_modules\metro\src\node-haste\DependencyGraph.js:219:16)
    at Object.resolve (C:\...rn-app\node_modules\metro\src\lib\transformHelpers.js:141:30)
    at dependencies.map.result (C:\...rn-app\node_modules\metro\src\DeltaBundler\traverseDependencies.js:373:31)
    at Array.map (<anonymous>)
    at resolveDependencies (C:\...rn-app\node_modules\metro\src\DeltaBundler\traverseDependencies.js:369:18)
    at C:\...rn-app\node_modules\metro\src\DeltaBundler\traverseDependencies.js:188:33
    at Generator.next (<anonymous>)
    at step (C:\...rn-app\node_modules\metro\src\DeltaBundler\traverseDependencies.js:298:30)
{
  "presets": [
    "module:metro-react-native-babel-preset"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx-source",
      "module-resolver",
      {
        "cwd": "babelrc",
        "root": ["./src"],
        "alias": {
          "src": "./src"
        }
      }
    ]
  ]
}
"react-native": "^0.57.4",
"babel-plugin-module-resolver": "^3.1.1",

tleunen/babel-plugin-module-resolver#310
#275

@Pradeet
Copy link

Pradeet commented Dec 18, 2018

Hi,
I am facing the same problem, before upgrading react-native every thing is working fine...
But now i am getting
error: bundling failed: Error: Unable to resolve module `@babel/runtime/helpers/interopRequireDefault` from `/Users/pradeetswamy/Work/javascriptWorkspace/sprinklr/sprinklr-native-client/packages/spr-native-passcode/src/index.js`: Module `@babel/runtime/helpers/interopRequireDefault` does not exist in the Haste module map

versions:
react-native: '0.57.8'
metro: '0.48.5'

Here is my rn-cli.config.js

const blacklist = require('metro-config/src/defaults/blacklist');
const fs = require('fs');

const getDependencyPath = dependency => fs.realpathSync(`node_modules/${dependency}`);

const getSymlinkedDependencies = () => {
  const packageJson = require(`${process.cwd()}/package.json`);
  const dependencies = [
    ...Object.keys(packageJson.dependencies),
    ...Object.keys(packageJson.devDependencies),
  ];
  return dependencies.filter(dependency => fs.lstatSync(`node_modules/${dependency}`).isSymbolicLink());
};

const symLinkedDependencies = getSymlinkedDependencies();

const projectRoots = new Set();
const extraNodeModules = {};
const dependenciesToBlacklist = [];

symLinkedDependencies.forEach((symLinkedDependency) => {
  projectRoots.add(symLinkedDependency);

  const symLinkedDependencyPath = getDependencyPath(symLinkedDependency);
  const peerDependenciesMapOfSymLinkedDependency = Object.keys(require(`${symLinkedDependencyPath}/package.json`).peerDependencies);
  console.log('peerDependency ==> ', [symLinkedDependency], 'symLinkedDependencies ==>', peerDependenciesMapOfSymLinkedDependency);

  peerDependenciesMapOfSymLinkedDependency.forEach((peerDependency) => {
    extraNodeModules[peerDependency] = path.resolve(__dirname, 'node_modules', peerDependency);

    dependenciesToBlacklist.push(new RegExp(`^${escape(path.resolve(__dirname, '..', symLinkedDependency, 'node_modules', peerDependency))}\\/.*$`));
  });
});

console.log('extraNodeModules: ---> ', extraNodeModules);

module.exports = {
  watchFolders: [__dirname, ...Array.from(projectRoots).map(project => path.join(__dirname, '..', project))],
  extraNodeModules,
  getBlacklistRE() {
    const modulesToBlacklist = [/react-native\/local-cli\/core\/__fixtures__.*/, ...dependenciesToBlacklist];
    return blacklist(modulesToBlacklist);
  },
};

@aleclarson
Copy link
Contributor

Symlinks are not currently supported by Metro. See this comment.

@SachinB-Droisys
Copy link

@aleclarson at the moment I see that many people have found different workaround solutions to this issue and the other; among plethora of suggestions and comments I am kind of lost in what to do and what not. Can you please honestly suggest a best solution which works for all the issues?
My specs:
OS: Windows 10
Android Studio: 3.3.2
React-native: 0.59.4
Native Platforms: android and ios
Project structure:

  1. An android project with a simple MainActivity and a MainApplication (looking for a react package to be included into getPackages call)
  2. An android project created using create-react-native-module which is supposed targeted by the other project as a library
    Both the projects are sitting in their individual workspaces (not nested anyway and not expecting to do so either).
    Suggestions will be highly appreciated!

@aleclarson
Copy link
Contributor

@SachinB-Droisys The best solution is to fork Jest and Metro, and then use jestjs/jest#7549 and #257 in your local clones. But unfortunately, it's probably not the easiest solution. Instead, you could try what this comment suggests. Otherwise, you're on your own, sorry!

@MehdiDonk
Copy link

Hi,
You can try WML.
https://www.npmjs.com/package/wml

What it does:

replaces npm link with something that actually works!

It worked for me !
Cheers

@numandev1
Copy link

@MehdiDonk wml package have many issue right now and not maintained
if you get any issue with wml then you can use https://www.npmjs.com/package/mtsl
it is alternative of wml

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

8 participants