Transitive Dependencies

A direct dependency is a package your project explicitly asks for. A transitive dependency is a package that one of your dependencies asks for, and so on recursively down the tree. You did not name it, and you may not even know it is there, but your code will not run without it.

This is why a project that declares only a handful of packages can end up installing hundreds. Each direct dependency drags in its own dependencies, which drag in theirs. The official npm documentation describes how npm resolves this graph into a folder layout, walking up directories looking for node_modules and reusing a package already installed in an ancestor folder rather than installing it again. Since npm version 3 it also hoists dependencies to the highest level it can, flattening much of the tree.

The catch is fragility. Your project’s behavior depends on code you never chose, maintained by people you do not know. If any package deep in the tree breaks, disappears, or is compromised, the effects propagate upward to everything that depends on it.

The clearest illustration is the left-pad incident of March 2016. When the tiny left-pad package was unpublished, the official npm blog recorded “hundreds of failures per minute, as dependent projects — and their dependents, and their dependents… — all failed when requesting the now-unpublished package.” A package almost nobody had directly installed was a transitive dependency of thousands of projects, and removing one node broke the chain for all of them.