npm Dependency Tree Analyzer
What does this package really install?
To see everything a package drags into node_modules, type its name (or paste your package.json) and this tool resolves the full transitive dependency tree live from the npm registry — the real list of every package an install pulls in, with exact install weight, tree depth, duplicate versions and the heaviest sub-trees ranked. The semver ranges are resolved in your browser exactly the way npm does it, so nothing is installed and your manifest never leaves your machine — only bare package names are requested from the registry.
Resolution per the npm semver spec · sizes from registry dist.unpackedSize · the security half of this question lives in the vulnerability scanner, the legal half in the license checker
Dependency resolver console
What those numbers actually mean
yet a developer typically lists only 10–20 in package.json. Everything past that line is trust by proxy — code you ship but never chose.
in a 2016 joke that stuck because it was true: a fresh create-react-app once unpacked to over 200 MB across 1,000+ folders before tree-shaking and pnpm changed the math.
and its 2016 un-publish broke React, Babel and thousands of builds worldwide in hours — proof that a tiny transitive dependency can be a single point of failure for the whole ecosystem.
in disk, in install time, and in audit surface. Two copies of the same library at different versions is the most common, most fixable cause of node_modules bloat.
Node server frameworks by dependency footprint
A common decision: which web framework keeps node_modules smallest? Approximate transitive footprints — resolve the live numbers for your exact version above.
| Framework | Installed packages | Install weight | Profile |
|---|---|---|---|
| Hono | 1 (zero deps) | ~1.4 MB | Edge-first minimalist — nothing transitive at all |
| Koa | ~35 | ~0.8 MB | Express's leaner successor — lightest by weight |
| @hapi/hapi | ~30 | ~1.3 MB | Opinionated and config-heavy, yet surprisingly lean today |
| Fastify | ~48 | ~6.9 MB | Performance-first; schema & serialization deps add weight |
| Express | ~69 | ~2.0 MB | Mature, batteries-included — the largest count here |
Dependency footprint of 12 popular packages
| Package | Packages installed | Install weight | Notes |
|---|---|---|---|
| react | 1 | 0.2 MB | v19 went fully zero-dependency; v18 still pulled loose-envify + js-tokens. |
| lodash | 1 | 1.4 MB | Zero dependencies — the weight is its own enormous breadth. |
| chalk | 1 | 0.04 MB | v5 went zero-dep and ESM — a deliberate diet from its old tree. |
| express | 69 | 2.0 MB | The canonical mid-size framework tree, six levels deep. |
| axios | 30 | 2.3 MB | Small core, but follow-redirects and form-data ride along. |
| vue | 23 | 16 MB | Compiler + reactivity packages travel together — heavy by weight. |
| moment | 1 | 4.2 MB | Zero deps but heavy — the reason teams moved to date-fns / Day.js. |
| typescript | 1 | 23 MB | One giant zero-dependency binary — count tiny, weight large. |
| @angular/core | 2 | 6.9 MB | Lean core; the real Angular tree balloons once the CLI joins. |
| eslint | 69 | 9.1 MB | Flat-config era trimmed it sharply; still dev-only weight to patch. |
| webpack | 71 | 19 MB | Build tooling — the long tail of loaders and schema utilities. |
| next | 12 | 152 MB | Tiny package count, huge weight — bundled native SWC binaries. |
Figures resolved live in 2026-06 and rounded; the analyzer above is the source of truth for your exact version. Next: check these trees for CVEs in the vulnerability scanner.
How the footprint is computed
Install weight & bands
weight = Σ unpackedSize(pkg) over unique packagesWorked: a tree of express@4.18.2 sums ~66 packages' unpacked sizes to ~2.1 MB → “Lean”. Bands: <25 MB featherweight · <100 lean · <350 moderate · <800 heavy · ≥800 bloated.
- ≤25 MBFeatherweight
- ≤100 MBLean
- ≤350 MBModerate
- ≤800 MBHeavy
- ≤∞Bloated
How the tree is resolved
- 1. Read each direct dependency's name and semver range from your input.
- 2. Fetch the package's abbreviated packument from the npm registry (the metadata-only feed npm uses to plan installs).
- 3. Pick the highest published version that satisfies the range —
^1.2.3→>=1.2.3 <2.0.0, with the ^0.x and prerelease edge cases handled exactly as npm does. - 4. Recurse into that version's dependencies, deduping by name@version, until the tree is fully walked (capped at 600 packages).
- 5. Sum unpacked sizes, measure depth, and flag any package resolved to more than one version as a duplicate.
How to analyze a dependency tree in 5 steps
Enter a package or paste package.json
Type a single npm package name (optionally with a version or range, e.g. express@^4.18.2), or paste an entire package.json to analyze your whole project's direct dependencies at once.
Choose your depth
Quick resolves production dependencies only. Pro adds the devDependencies toggle, the duplicate-version finder and side-by-side package comparison. Engineer exposes Node engine constraints, the full flat package table and JSON export.
Resolve the tree
Click Analyze. Each package's metadata is pulled live from the npm registry (registry.npmjs.org), the best version for every semver range is computed in your browser, and the full transitive tree is walked — exactly what npm would install, without installing anything.
Read the verdict and the heaviest packages
The summary gives total unique packages, install weight, tree depth and duplicate versions, with a lean/heavy verdict. The heaviest-packages ranking shows precisely which sub-trees account for the bulk of node_modules.
Trim, dedupe, or compare alternatives
Expand the interactive tree to see where weight and duplicates come from, use Pro mode to compare two packages head-to-head, and export the JSON report. Re-run after a dependency change to confirm the footprint shrank.
Why dependency trees got so deep — and why it matters
In 2026, a developer adds one line — "some-helper": "^2.0.0" — to package.json, runs install, and quietly acquires eighty new packages, six maintainers they'll never meet, and twelve megabytes of code that now runs with the same privileges as their own. None of that is visible from the manifest. This tool exists to make it visible before the install, not after: the gap between the dependencies you declare and the ones you actually ship is the entire story of modern dependency management.
That gap is a deliberate design choice with a history. When Isaac Schlueter released npm in 2010, its defining decision was nested dependencies: unlike earlier package managers that forced one global version of each library, npm let every package have its own copy of its own dependencies. This solved "dependency hell" — version conflicts that made large installs impossible — but it traded that problem for a new one: trees that could nest dozens of levels deep and install the same library a dozen times. The npm philosophy of small, single-purpose modules (epitomized by packages like is-odd) multiplied the count further.
The risks of that model went from theoretical to front-page in March 2016, when a developer un-published left-pad, an eleven-line package that pads a string, after a naming dispute. Because React, Babel and thousands of other projects depended on it transitively — most without knowing — builds broke across the world within hours. npm took the unprecedented step of restoring the package. The lesson was permanent: a transitive dependency you have never heard of can be a single point of failure for your entire build, and you cannot manage what you cannot see.
Security followed the same arc. The event-stream incident of 2018 — where an attacker gained publish rights to a popular package and slipped in code to steal cryptocurrency wallets — proved that the threat isn't just availability but integrity: a deep tree is a wide attack surface, because every maintainer of every transitive package is someone who can ship code into your project. Counting and mapping the tree, which is what this analyzer does, is the first step; checking those packages for known vulnerabilities is the second, which is why this tool links directly to the vulnerability scanner and the license checker.
The tooling fought back on weight, too. Semantic versioning (semver) gave ranges like ^1.2.3a precise meaning, so resolvers could safely pick the newest compatible version — the exact algorithm this page runs in your browser. Yarn (2016) and pnpm (2017) attacked duplication directly: pnpm's content-addressable store keeps a single copy of each version on disk and symlinks it everywhere, turning the "heaviest object in the universe" joke into a solved problem for teams who adopt it. But the logical tree — the one that determines your audit surface and your supply-chain risk — is the same regardless of the installer, and that is the tree shown here.
What hasn't changed is the discipline. The leanest projects aren't the ones with the best installer; they're the ones whose authors ask, before every npm install, "what does this actually pull in?" — and choose date-fns over moment, chalk v5's zero-dependency rewrite over the old tree, a few lines of their own code over a package that drags in eighty. This tool is built to make that question a two-second answer instead of a post-install regret.
Trusted by Platform, Frontend & Tooling Teams
“We use this in PR review to answer one question: 'how much does this new dependency actually cost us?' Pasting the proposed package and seeing 140 transitive packages and 18 MB before it merges has killed more bad dependency decisions than any lint rule. The heaviest-packages ranking is exactly the conversation starter we needed.”
“The duplicate-version finder paid for itself in one sitting — found three libraries installed at two versions each across our tree, traced them to two stale dependencies, and cut install time noticeably. That this runs in a browser tab with no npm install and no telemetry is the reason I can recommend it org-wide.”
“Before I add a dependency to a library, I check its tree here. Watching a 'small' helper drag in 80 packages has made me ship far leaner releases. The semver resolution is correct — I checked it against npm ls on a few gnarly ranges and it matched, including the ^0.x edge cases everyone gets wrong.”
“Engineer mode's Node-engine floor caught why our CI broke after a routine bump — a deep transitive dependency had quietly moved to >=20. The JSON export went straight into our dependency review doc. Would love a lockfile import next, but as a zero-install footprint check it's already in our toolbelt.”
Love using our calculator?
Related tools
Related Articles
Dive deeper with our expert guides and tutorials related to npm Dependency Tree Analyzer
Resolution per the npm semver specification · sizes from registry dist.unpackedSize · Last reviewed: 2026-06