Field notes

reference ·

What your lockfile actually proves

Read dependency records without confusing declared intent, resolved versions, licenses, vulnerabilities, and shipped code.

On this page

A package manifest says what a project asks for. A lockfile records much more about the dependency tree used to satisfy that request. Neither file is a certificate that everything inside is safe, maintained, licensed for every purpose, or somehow necessary.

That last question may require a difficult conversation with the date picker.

Read the right layer

In npm projects, package.json typically contains dependency declarations and ranges. package-lock.json describes the resolved dependency tree in a format whose details depend on the lockfile version. npm documents fields for resolved versions, sources, integrity information, and package records. A reader should inspect the format version before assuming a particular structure. npm

Distinguish direct dependencies from packages pulled in by them. Distinguish declared ranges from resolved versions. Count package instances separately from unique package names when multiple versions occur. Label the counting method so a large number does not become an unexplained scare tactic.

Follow a concrete inspection

Imagine a manifest requesting a library with a caret range and a lockfile resolving an exact version. A dependency receipt should show both values, indicate whether it is a production or development declaration, and show the relevant lockfile record.

If the record has no license field, show “not recorded.” Do not infer a license from a similarly named package or its parent. If current registry metadata is fetched, display it as a separate dated observation; current metadata is not automatically the metadata for the locked release.

Never execute package scripts just to inspect a file. Parsing JSON is enough for the initial task. Apply a file-size limit, reject unsupported lockfile formats, and report malformed JSON without making the visitor paste the whole project into a third-party service.

Inspect a real project without running it

Use an existing npm project with a version 2 or 3 lockfile. These read-only Node commands inspect the file; they do not install packages or run package scripts:

node -e "const fs=require('node:fs'); const l=JSON.parse(fs.readFileSync('package-lock.json','utf8')); console.log('lockfileVersion',l.lockfileVersion); console.log('root declarations',l.packages?.['']?.dependencies);"
node -e "const fs=require('node:fs'); const l=JSON.parse(fs.readFileSync('package-lock.json','utf8')); if(!l.packages) throw Error('Use a v2/v3 lockfile'); console.table(Object.entries(l.packages).filter(([p])=>p).map(([path,p])=>({path,version:p.version,dev:p.dev??false,license:p.license??'not recorded'})));"

Pick one declared dependency and locate its package record. Record the requested range, resolved version and installation path separately. If another version appears at a nested path, retain both instances. Save the original lockfile with this inspection; a later install may change the tree.

Integrity answers a narrower question

An integrity value helps identify expected package content. It does not mean the content is benevolent. A perfectly intact package can still contain a bug, an unsuitable license, or code you never wanted to ship.

Likewise, an npm audit result is a report about known vulnerabilities available to that mechanism, not a complete security assessment. npm documents the audit command separately from lockfile semantics for a reason. Keep an optional advisory lookup distinct from the basic dependency inventory. npm

If no advisory check has been performed, say that plainly. “No findings” and “not checked” must not share the same reassuring badge.

Installed size is not browser cost

Registry unpacked size describes the package archive after unpacking. It is not the compressed JavaScript delivered by your production route. Bundling, imports, tree shaking, assets, and transitive dependencies affect what a visitor receives.

Treat a package inventory as a lead for measurement. Build the relevant route and inspect its actual output before claiming that removing a dependency will save a particular number of kilobytes. A small wrapper package can pull in a large runtime; a larger package can contain files that never reach the browser.

Export a receipt, not a verdict

A useful result contains the input filename and hash, lockfile version, counting method, package identifiers, resolved versions, dependency paths, and the provenance of any registry enrichment. Keep missing fields explicit and make the raw inventory downloadable.

Then ask practical questions: which dependency owns this code path, which versions are duplicated, and which capabilities are actually used? Those questions lead to changes you can test.

The goal is to make the dependency tree understandable enough to maintain. The tree does not need another dashboard awarding it a score of 87 for reasons nobody can explain.

Next: A web app you can take home puts dependency boundaries to work.

Sources

Put this to work

More field notes