Sourcemap Explorer
Guide

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.

5 min readNode.js, jq, Sourcemap Explorer extension

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

    Load the sourcemap

    `const map = JSON.parse(fs.readFileSync('bundle.js.map'))`. You'll be working with `map.sources[]` and `map.sourcesContent[]`.

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

Install free on Chrome