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)
1
  • 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 Commented Nov 15, 2019 at 6:41

2 Answers 2

97

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

25
  • 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 <projectdir>/node_modules/<module>/dist/
    – thurt
    Commented Jan 31, 2017 at 19:55
  • 4
    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
    Commented Mar 2, 2017 at 23:41
  • 3
    As of (at least) RN 0.52, the import needs to be: const blacklist = require('metro').createBlacklist;
    – mtkopone
    Commented Mar 20, 2018 at 17:45
  • 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
    Commented Nov 8, 2020 at 17:08
  • 2
    Thanks for adding the 0.64 update. I have tested and it works.
    – iJeep
    Commented May 18, 2021 at 21:00
1

For Expo:

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

const config = getDefaultConfig(__dirname);

module.exports = {
  ...config,
  resolver: {
    ...config.resolver,
    blockList: [config.resolver.blockList, /(\/amplify\/.*)$/],
  },
};

Not the answer you're looking for? Browse other questions tagged or ask your own question.