question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ignoring packages during dependency resolution

See original GitHub issue

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

What is the current behavior?

We have a dependency which is built as a C library. In order to use and test this with our RN app, we have one package with our node bindings (node-dep) and another with our RN bindings (rn-dep). So our code looks like:

let dep = null
if (typeof navigator === 'undefined' || navigator.product !== 'ReactNative') {
    dep = require("node-dep")
} else {
    dep = require("rn-dep")
}

We blacklistRE this dependency because if it is discovered, you see this package itself specifies a main module field that could not be resolved, presumably because it is not a valid RN package.

The node version of the package is not needed when packaging for RN, but metro discovers the conditional code requiring it and complains that it can’t be found: error: bundling failed: Error: Unable to resolve module `node-dep` from `/home/omit/node_modules/other_dependency/file.js`: Module `node-dep` does not exist in the Haste module map or in these directories: /home/omit/node_modules

So either we blacklistRE the node package to exclude it, and it fails to be found (though not needed), or we do not blacklistRE and it fails to package because it’s not an RN package.

What is the expected behavior?

Is there a way to tell metro to simply ignore any require("node-dep") and just have the app crash at runtime if it were encountered? I’d like to be able to blacklist the package directory and just have metro skip it over. dynamicDepsInPackages does not seem helpful here.

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

metro.config.js:

const blacklist = require('metro-config/src/defaults/blacklist')
const blacklistRE = blacklist([/.*node-dep.*/])

module.exports = {
  resolver: {
    blacklistRE,
  },
  transformer: {
    getTransformOptions: async () => ({
      transform: {
        experimentalImportSupport: false,
        inlineRequires: false,
      },
    }),
  },
};

metro - 0.51.1 (determined by RN version)

yarn - 1.22.0

node - 10.17.0

OS - Linux

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:4
  • Comments:9

github_iconTop GitHub Comments

6reactions
nacho-carnicerocommented, Jan 28, 2021

I ended up finding a solution that works great for my use case and that would work for this one without having to do that funky obfuscation. This solution uses the resolveRequest option of the metro config in order to point to a dumb file for the dependencies that are problematic, and uses the normal resolver for the others. Make sure to add the packages you want to ignore to the blacklistedModules array.

To make it work add this to your metro.config.js file:

/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

const OriginalResolver = require("metro-resolver");
const path = require("path");

const blacklistedModules = ["https", "http", "zlib"];

module.exports = {
  resolver: {
    resolveRequest: (context, realModuleName, platform, moduleName) => {
      if (blacklistedModules.includes(moduleName)) {
        return {
          filePath: path.resolve(__dirname + "/src/shim-module.js"),
          type: "sourceFile"
        };
      } else {
        return OriginalResolver.resolve(
          { ...context, resolveRequest: undefined },
          moduleName,
          platform
        );
      }
    }
  }
};

In my case /src/shim-module.js is a file with this content:

/**
 * File that shims a module. See the file metro.config.js at the root
 */
module.exports = {};

Hope this helps!

2reactions
higleyccommented, Apr 27, 2020

@Slapbox sure, like this:

let dep
if (typeof navigator === 'undefined' || navigator.product !== 'ReactNative') {
    let pname = ""
    let x = ["n", "o", "d", "e", "-", "d", "e", "p"]
    for (let i = 0; i < x.length; ++i) {
        pname += x[i];
    }
    dep = require(pname)
} else {
    dep = require('rn-dep')
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Package.resolved should go in the .gitignore - Swift Forums
Package.resolved file records the result of dependency resolution whenever SwiftPM performs it. If the file is already present, SwiftPM will try ...
Read more >
Understanding dependency resolution - Gradle User Manual
This chapter covers the way dependency resolution works inside Gradle. ... to explain how these declarations come together during dependency resolution.
Read more >
NuGet Package Dependency Resolution - Microsoft Learn
Direct dependency wins ... When the package graph for an application contains different versions of a package in the same subgraph, and one...
Read more >
NuGet ignoring newer version of dependency - Stack Overflow
To resolve this issue, you can use below command in the Package Manager Console: Install-Package PackageTwo -DependencyVersion Highest.
Read more >
Dependency Resolution - pip documentation v22.3.1
It is part of how dependency resolution for Python packages works. Example. The user requests pip install tea . The package tea declares...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found