35

Problem:

My project has a @providesModule naming collision when trying to run react-native run-ios from the command line. It is conflicting with autogenerated dir dist/ which is created by another npm package, esdoc. I would like to be able to keep this autogenerated dir and just make the react native packager ignore the dist/ dir.

Error Message:

[01/23/2017, 13:17:07] <START> Building Haste Map
    Failed to build DependencyGraph: @providesModule naming collision:
      Duplicate module name: ann
      Paths: /Users/thurt/projects/example/package.json collides with /Users/thurt/projects/example/dist/esdoc/package.json

This error is caused by a @providesModule declaration with the same name across two different files.
Error: @providesModule naming collision:
  Duplicate module name: ann
  Paths: /Users/thurt/projects/example/package.json collides with /Users/thurt/projects/example/dist/esdoc/package.json

This error is caused by a @providesModule declaration with the same name across two different files.
    at HasteMap._updateHasteMap (/Users/thurt/projects/example/node_modules/react-native/packager/react-packager/src/node-haste/DependencyGraph/HasteMap.js:158:13)
    at p.getName.then.name (/Users/thurt/projects/example/node_modules/react-native/packager/react-packager/src/node-haste/DependencyGraph/HasteMap.js:133:31)
Rob Hogan
  • 2,442
  • 19
  • 23
thurt
  • 882
  • 1
  • 10
  • 25
  • hello just came across this post for my issue, i am using 0.59.8 react-native version, i have two metro.config.js files one under node-module/metro and another under node-module/react-native which to change? plz help struggling with issue past 3 days – user2813740 Nov 15 '19 at 06:41

2 Answers2

94

The configuration for this has a habit of changing between RN versions. See below for version-specific instructions on creating a config file, loading the config file and clearing the cache.

For React Native >= 0.64 to 0.71(+?)

A rename of the helper function from blacklist to exclusionList was made in Metro 0.60, and the config entry blacklistRE -> blockList in Metro 0.61. These both landed in RN in 0.64.0.

In your project root create metro.config.js with the contents:

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

// exclusionList is a function that takes an array of regexes and combines
// them with the default exclusions to return a single regex.

module.exports = {
  resolver: {
    blockList: exclusionList([/dist\/.*/])
  }
};

For React Native >= 0.59, < 0.64

In your project root create metro.config.js with the contents:

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

// blacklist is a function that takes an array of regexes and combines
// them with the default blacklist to return a single regex.

module.exports = {
  resolver: {
    blacklistRE: blacklist([/dist\/.*/])
  }
};

For React Native >= 0.57, < 0.59

In your project root create rn-cli.config.js with the contents:

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

// blacklist is a function that takes an array of regexes and combines
// them with the default blacklist to return a single regex.

module.exports = {
  resolver: {
    blacklistRE: blacklist([/dist\/.*/])
  }
};

For React Native >= 0.52, < 0.57

In your project root create rn-cli.config.js with the contents:

const blacklist = require('metro').createBlacklist;

module.exports = {
  getBlacklistRE: function() {
    return blacklist([/dist\/.*/]);
  }
};

For React Native >= 0.46, < 0.52.

In your project root create rn-cli.config.js with the contents:

const blacklist = require('metro-bundler').createBlacklist;

module.exports = {
  getBlacklistRE: function() {
    return blacklist([/dist\/.*/]);
  }
};

For React Native < 0.46.

In your project root create rn-cli.config.js with the contents:

const blacklist = require('react-native/packager/blacklist');

module.exports = {
  getBlacklistRE: function() {
    return blacklist([/dist\/.*/]);
  }
};

All versions < 0.59

Have your CLI command use this config by passing the --config option:

react-native run-ios --config=rn-cli.config.js

(The config file should be automatically picked up by RN >= 0.59, ever since it was renamed metro.config.js)

All versions: Note on caching

Be aware that your blacklisted items may have already been included in the cache by the packager in which case the first time you run the packager with the blacklist you may need to reset the cache with --reset-cache

Rob Hogan
  • 2,442
  • 19
  • 23
  • 1
    Thanks rob ! For my situation, all I needed to do was include the `--reset-cache` flag. now it appears that my `rn-cli.config.js` file is automatically used, so i did not need the `--config=rn-cli.config.js`. After successfully getting past the packager step, I was still getting "module not found" error when app first tries to load up. I added the project folder name to the beginning of the blacklist regex which appears to fix that problem. I think I needed that to ensure the packager does not ignore folders like /node_modules//dist/ – thurt Jan 31 '17 at 19:55
  • which rn version do you use? – Guy Segal Feb 04 '17 at 18:29
  • @GuySegal rn 0.40.0 – thurt Feb 06 '17 at 15:06
  • 3
    What is NOT said here is that the matching is anchored to the end of input (the regular expressions in the array are built into one final regular expression that is terminated by $)... so make sure to put a .* at the end of the regular expression you would like to match against. Also, another helpful hint is that all '/' forward slashes are automatically replaced with the current OS path separator. – th317erd Mar 02 '17 at 23:41
  • 3
    As of (at least) RN 0.52, the import needs to be: `const blacklist = require('metro').createBlacklist;` – mtkopone Mar 20 '18 at 17:45
  • @mtkopone good spot. `metro-bundler` was renamed `metro` in RN 0.52.0 exactly. Will update the answer. – Rob Hogan Mar 22 '18 at 00:09
  • This is not working for me, seems like getBlacklistRE ignoring my regex. – sunny Jul 17 '18 at 12:07
  • @sunny have you reset the pacakager cache? If you want to post your RN version and code as a new question I’ll try to help. – Rob Hogan Jul 20 '18 at 12:28
  • @RobHogan I have already posted as a new question- https://stackoverflow.com/questions/51383954/blacklisting-react-native-module-doesnt-works – sunny Jul 20 '18 at 12:48
  • does this work for you in mac as well ? I am using ReactNative version 0.56 and I have tried the same solution suggested here. But no luck. I am doing iOS app with RN. – Yugandhar Pathi Sep 19 '18 at 00:59
  • @YugandharPathi I've updated my answer for RN 0.57 - maybe you could try that version with 0.56? – Rob Hogan Sep 19 '18 at 09:14
  • did not work with rn-cli.config.js but perfectly works with the same changes made in metro.config.js ("react-native": "0.59.4", windows) – KEMBL May 27 '19 at 23:40
  • `metro.config.js` is a new name of this config file, `rn-cli.config.js` is a legacy name. And there is no need to pass it to `--config` option. – zubko Jul 10 '19 at 20:39
  • @KEMBL @zubko - thanks, I've updated for RN 0.59+ and `metro.config.js` – Rob Hogan Jul 11 '19 at 10:02
  • hello just came across this post for my issue, i am using 0.59.8 react-native version, i have two metro.config.js files one under node-module/metro and another under node-module/react-native which to change? plz help struggling with issue past 3 days – user2813740 Nov 15 '19 at 06:36
  • @user2813740 don’t modify anything under `node_modules`. As the answer says, you need to create a *new* `metro.config.js` in your project root (that’s the top level directory which also contains your `package.json` etc) – Rob Hogan Nov 16 '19 at 11:18
  • @Rob Hogan hello, i tried earlier, now also i tried but getting same issue. i am totally new for react native without prior java-script experience ....... how does i have to tell project refer to created metro.config.js? mine i have created Expo CLI project and added backend. please help...totally lost – user2813740 Nov 17 '19 at 12:42
  • @Rob Hogan, as my project shows already two metro.config.js so dont know if new added filed picked up or not i am using all latest versions only – user2813740 Nov 17 '19 at 15:14
  • Ignoring directories with the packager (this question and answer) is a fairly unusual use case that shouldn't be necessary with Expo out of the box. My guess is this probably isn't the right solution to whatever problem you're having. If you want to create a new question with the original problem that led you to try this, post a link here and I'll take a look. – Rob Hogan Nov 17 '19 at 17:05
  • https://stackoverflow.com/questions/58838038/haste-module-naming-collision-react-native-app-with-aws-service-amplify-projec i had added question but i did not got any answer...plz have a look – user2813740 Nov 18 '19 at 05:23
  • In recent versions of Metro, this is called `blocklist`. See https://github.com/facebook/metro/pull/591 – Ehtesh Choudhury Sep 30 '20 at 17:56
  • 1
    @EhteshChoudhury - thanks, but `inlineRequires` isn't the option covered by this answer. However, the exported function in `defaults` has actually renamed from `blacklist` to `exclusionList` in metro 0.60. I've added a section on RN 0.64+ covering this. – Rob Hogan Nov 08 '20 at 17:08
  • 2
    Thanks for adding the 0.64 update. I have tested and it works. – iJeep May 18 '21 at 21:00
  • 1
    At least with 0.70.3, it seems wrong to use "exclusionList" with blacklistRE. All that does is replace directory separators, changing / to \ in Windows, but the code that uses this pattern (anymatch) always expects forward slashes. Just using a regex directly works for me. Maybe they're meant to be used together and this is a bug (don't have time to investigate further). – Glenn Maynard Jan 13 '23 at 01:20
  • @GlennMaynard - I think you might be right - I suspect the default exclusion list (which covers things like `.git`) may actually be ineffective on Windows, which is a bug. That may be harmless, but probably means Metro is watching more files than it needs to. (PSA: Since my last comment here, I joined FB/Meta and I'm now maintaining Metro :) ) – Rob Hogan Jan 16 '23 at 18:04
1

For Expo:

const { getDefaultConfig } = require('expo/metro-config');

const config = getDefaultConfig(__dirname);

module.exports = {
  ...config,
  resolver: {
    ...config.resolver,
    blockList: [config.resolver.blockList, /(\/amplify\/.*)$/],
  },
};
webjay
  • 5,358
  • 9
  • 45
  • 62