NPM Dependency Model

· 2 min read

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

  1. 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
  2. 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.

References

Authors
Developer, digital product enthusiast, tinkerer, sharer, open source lover