Reputation: 10057
I know that npm libraries, when installed, can install multiple versions of the same library in a hierarchical tree, like this:
[email protected]
-> [email protected]
-> [email protected]
-> [email protected]
In the above, package a
at version 0.1.0
is pulled in, and its dependencies [email protected]
and [email protected]
. Similarly, [email protected]
's dependency is
pulled in, which is [email protected]
.
I have heard from someone that, even though package b
is installed at two different versions, only one of them is actually loaded into memory and used. I have also heard that this may or may not be the case for node deployments of javascript versus browser deployments.
So my question is: Is it true that only one package of b
is loaded into memory? If it is, is this true for both node and browser, or are there differences?
Upvotes: 4
Views: 256
Reputation: 74670
Multiple versions of a Node module/library can be loaded, depending on where they are loaded from. The module loader is covered in depth in the Node.js documentation.
The require()
call caches modules based on the resolved file path.
require('b')
from module a
will resolve to .../a/node_modules/b
require('b')
from module c
will resolve to .../a/node_modules/c/node_modules/b
So seperate modules will be loaded for the same call. This can be demonstrated with a small example.
Module B - node_modules/b/index.js
module.exports = {
VERSION = 'b-0.5.0'
}
Module C - node_modules/c/index.js
module.exports = {
VERSION: 'c-1.0.0',
BVERSION: require('b').VERSION,
}
Module C's copy of B - node_modules/c/node_modules/b/index.js
module.exports = {
VERSION: 'b-9.8.7',
}
Create a program to output the versions.
console.log('b', require('b').VERSION)
console.log('c', require('c').VERSION)
console.log('cb', require('c').BVERSION)
Then output the versions
→node index.js
b b-0.5.0
c c-1.0.0
cb b-9.8.7
So two modules with different paths using require('b').VERSION
get a different value.
It's worth noting that if a Node.js require('b')
fails to find a locally installed ./node_modules/b
then it will traverse up the directory tree to look for b
in parent node_modules
directories.
Using the above example case again, but removing a/node_modules/c/node_modules/b
.
Module c
does a require('b')
but can't find ...a/node_modules/c/node_modules/b
then it will go into the parent node_modules/
and look for b
, In this case it would load the cached copy of ...a/node_modules/b
→node index.js
b b-0.5.0
c c-1.0.0
cb b-0.5.0
Browsers have no concept of an npm module. You need a loader that supports CommonJS module's like Browserify or Webpack. If the loader doesn't respect CommonJS/Node.js rules then it's unlikely to work with npm packages.
You should be able to package up the above example with your loader and see how it behaves.
Upvotes: 5