Search code examples
javascriptnpmpeer-dependencies

Why can't a peerDependency be imported or required, even when it's present in the parent module?


I'm trying to use npm peerDependencies but nothing seems to work as advertised. What am I missing?

The setup is, I have two modules, mod and plugin, both of which depend on an external module from npm. mod declares a hard dependency on both plugin and the external module, and the plugin declares a peer dependency, in order to get access to the version being used by the parent module.

The files look like this:

~/plugin/package.json:

    {
      "name": "plugin",
      "version": "1.0.0",
      "main": "index.js",
      "peerDependencies": {
        "pad-right": "^0.2.2"
      }
    }

~/plugin/index.js

    var peerDependency = require('pad-right')
    module.exports = 'this is a plugin'

~/mod/package.json:

    {
      "name": "mod",
      "version": "1.0.0",
      "main": "index.js",
      "dependencies": {
        "pad-right": "^0.2.2",
        "plugin": "../plugin"
      }
    }

~/mod/index.js:

    var hardDependency = require('pad-right')
    var plugin = require('plugin')

As I understand it from docs and examples, I think this should be a standard way to use peer dependencies, and running npm install in either directory doesn't give any errors or warnings.

However when I run webpack in the mod folder, I get errors like:

ERROR in ../plugin/index.js
Module not found: Error: Can't resolve 'pad-right' in '~/plugin'
 @ ../plugin/index.js 1:21-41
 @ ./index.js

What's going wrong here, shouldn't webpack resolve the require statement inside plugin with the peer dependency from the parent mod module?


Solution

  • Gah, it looks like this is an edge case that only affects modules that are referencing each other locally via the file system.

    The solution is apparently to add something like:

        resolve: {
            alias: {
                'pad-right': path.resolve('node_modules', 'pad-right'),
            },
        },
    

    to your webpack config. (Or else to try resolve.symlinks: false, which solves the problem in the minimal repro code I posted, but doesn't solve things in my actual project).

    Article about the issue