facebook / metro

🚇 The JavaScript bundler for React Native
https://metrobundler.dev
MIT License
5.25k stars 627 forks source link

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 6 years ago

mxmzb commented 6 years ago

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 https://github.com/facebook/react-native/issues/4968 and https://github.com/facebook/metro/issues/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 commented 6 years ago

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 commented 6 years ago

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",

https://github.com/tleunen/babel-plugin-module-resolver/issues/310 https://github.com/facebook/metro/issues/275

Pradeet commented 5 years ago

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 commented 5 years ago

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

SachinB-Droisys commented 5 years ago

@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 commented 5 years ago

@SachinB-Droisys The best solution is to fork Jest and Metro, and then use https://github.com/facebook/jest/pull/7549 and https://github.com/facebook/metro/pull/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 commented 5 years ago

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 commented 4 years ago

@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