How to extract package.json files from a sourcemap
Sourcemaps often include `node_modules/<pkg>/package.json` as a source file — especially when the bundler does module resolution at compile time. Each one is a structured, ready-to-parse manifest: name, version, dependencies, engines.
Background
A `package.json` inside a sourcemap is a peculiar artifact. It's the literal manifest of the bundled version of a library — the same file you'd find in `node_modules/<pkg>/package.json` on the author's machine at build time. For popular packages (React, Vue, Next.js) it includes the `version`, `main`, `exports`, `dependencies`, `devDependencies`, `peerDependencies`, `engines` and `sideEffects` fields. That's more information than you could reasonably extract any other way. Extracting them is mechanical: iterate `sources[]`, filter entries matching `package.json`, JSON.parse the matching `sourcesContent[]`. The whole pipeline is 15 lines of Node.js.
Why this matters
`package.json` files tell you not just what version of a library is running, but what it expects of its environment (`engines`), what it depends on (`dependencies`), and often what the author of the site explicitly chose (`sideEffects`, `exports`). Aggregating them across a site's sourcemaps gives you a lockfile-quality view of the bundled ecosystem.
Prerequisites
- Node.js 18+ or `jq`.
- A sourcemap file.
Step-by-step
- 1
Load the sourcemap
`const map = JSON.parse(fs.readFileSync('bundle.js.map'))`. You'll be working with `map.sources[]` and `map.sourcesContent[]`.
- 2
Filter paths ending in package.json
Loop `sources[i]`. Keep those matching `/(?:^|\/)package\.json$/`. Remember the index `i`.
const pkgIndices = []; for (let i = 0; i < map.sources.length; i++) { if (/(^|\/)package\.json$/.test(map.sources[i])) pkgIndices.push(i); } - 3
Parse the matching sourcesContent
For each kept index, `const pkg = JSON.parse(map.sourcesContent[i])`. Pull `pkg.name`, `pkg.version`, and optionally `pkg.dependencies`, `pkg.devDependencies`, `pkg.peerDependencies`, `pkg.engines`, `pkg.sideEffects`.
- 4
Build a name → version map
Aggregate across bundles. If two `package.json`s share a name with different versions (common when pnpm/yarn dedupe differs across chunks), keep both — they're both real.
- 5
Use Sourcemap Explorer
The extension does this step automatically on every bundle it finds, and shows the resulting version alongside the library entry on the Stack tab. For bulk / offline analysis, the script above is what you want.
Real-world example
Troubleshooting
Script finds zero `package.json` entries.
Either the bundler stripped them, or the regex is too strict. Widen to `package.json$` (case-insensitive) and log the first 20 `sources[]` entries to see the actual shape.
Multiple versions of the same package.
Monorepo or hoisting artifact. Both are real; decide whether to report both, the semver-max, or investigate which chunks use which.
Caveats
What to do next
`package.json` data pairs well with the 'reconstruct source' guide — combined, you get a full browsable project tree with a lockfile-shape manifest of its bundled dependencies.
FAQ
Why would a bundler include `package.json` at all?
Bundlers read `package.json` at resolution time (for `main`, `module`, `exports`, `sideEffects` fields). When sourcemap generation captures the full module graph, those reads end up as `sources[]` entries. Whether the map inlines their content is a bundler configuration choice — most modern bundlers default to inlining.
Do CSS sourcemaps have package.json files too?
Occasionally. PostCSS and Sass pipelines sometimes include their bundled package's `package.json`. Less common than in JS maps but not unheard of.
Related
Skip the manual steps.
Sourcemap Explorer automates every workflow in this guide — free, local, no sign-up.