NPM Dependency Model
I’ve always stayed at the simple usage level for dependencies, without understanding the dependency model. So I decided to eliminate this blind spot.
Let’s understand through the following scenarios.
Direct and Indirect Dependencies on the Same Package
Note: Versions are different
foo
├── hello 0.1.2
└── bar
├── hello 0.2.8
└── goodbye 3.4.0
Physical Disk
node_modules/
├── hello 0.1.2
└── bar
└── node_modules/
├── hello 0.2.8
└── goodbye 3.4.0
In this situation, both versions will coexist on the physical disk.
Indirect Dependencies on the Same Package
Note: Versions are different
foo
├── hello 0.1.2
└── world 1.0.7
bar
├── hello 0.2.8
└── goodbye 3.4.0
In this situation, both versions will coexist on the physical disk.
Physical Disk
node_modules/
├── foo/
│ └── node_modules/
│ ├── hello/ 0.1.2
│ └── world/ 1.0.7
└── bar/
└── node_modules/
├── hello/ 0.2.8
└── goodbye/ 3.4.0
Dependency Model During Install Phase
During the install phase, npm installs packages based on Semver, which is package name + version number. As long as they’re inconsistent, both versions will be installed.
Build Phase
As shown above, multiple versions of packages exist in node_modules. So the question arises: which version will be in the vendor file after packaging? Both will be there
, because the two instances are indeed different.
Summary
- Under npm’s dependency model, physically, different versions of the same package are allowed to exist. A package’s uniqueness is determined by
package name + version number
- Try to ensure consistent dependency package versions as much as possible, as this affects the overall bundled size
Final Thoughts
Understanding this point helps us better use and manage dependencies, giving us a clear understanding of the final dependency versions.