You open a pull request to review a dependency update and the diff is a wall of text — 80 lines of package names and version numbers. Your teammate says "just bumped a few deps", but buried in there is a downgraded React version and two new packages nobody discussed.
Manually spotting that by eye is error-prone. A proper side-by-side diff would have caught it in seconds.
Here are four methods for comparing package.json files, when to use each, and a workflow that fits into real code reviews.
Why package.json Comparisons Go Wrong
The obvious ones are easy — a new package name sticks out. The dangerous ones are subtle:
- A minor version bump (
^18.2.0 → ^18.3.0) that pulls in a breaking change via a transitive dependency - A
peerDependencyconflict where two packages need different versions of the same library — causing silent runtime bugs that your test suite won't catch - A package silently downgraded during a lockfile resolution
- A
devDependencyaccidentally moved todependencies, inflating your production bundle
None of these are obvious from a quick glance at a git diff. They need a proper side-by-side comparison.
Method 1: Git Diff (Fastest)
The go-to for a quick local check before pushing:
git diff main..feature-branch -- package.json
To include more context lines around each change:
git diff -U10 main..feature-branch -- package.json
Always diff the lockfile at the same time — version constraints in package.json can hide transitive changes that only show up in package-lock.json or yarn.lock:
git diff main..feature-branch -- package.json package-lock.json
Best for: Quick checks before pushing. Not great for large files or sharing with teammates — the raw terminal output is hard to read.
Method 2: GitHub Pull Request Diff
If the PR is already open on GitHub:
- Go to the Files changed tab
- Scroll to
package.json - Click the split view icon (two columns) for side-by-side mode
GitHub highlights added lines in green and removed lines in red. For large files, use the File filter dropdown at the top to jump straight to package.json.
Best for: Reviewing a PR before merging. Doesn't help when you want to compare arbitrary branches or files not in an open PR.
Method 3: Online Diff Tools (Most Visual)
For a detailed, shareable comparison — especially useful for large dependency updates or monorepo audits — paste both package.json files into an online diff tool like Online Diff.
Here's what a typical comparison looks like:
// package.json on main branch
"dependencies": {
"react": "^18.2.0",
"axios": "^1.4.0",
"lodash": "^4.17.21"
}
// package.json on feature branch
"dependencies": {
"react": "^18.3.0", // ← version bumped
"axios": "^1.4.0",
"lodash": "^4.17.21",
"zod": "^3.22.4", // ← new package added
"date-fns": "^3.0.0" // ← new package added
}
With syntax highlighting and character-level diffs, version bumps and new packages are immediately obvious. You can share the diff URL with your team — useful when the reviewer can't run git locally.
Best for: Detailed dependency audits, sharing with colleagues, comparing files across different repos.
Method 4: npm diff (npm 8+)
npm 8 introduced a built-in diff command:
npm diff -- package.json
You can also compare specific versions of a package:
npm diff --diff=lodash@4.17.20 --diff=lodash@4.17.21
Best for: Comparing installed package versions when investigating what changed between two npm installs. Less useful for branch-to-branch comparisons.
The Security Angle: Why This Matters Beyond Code Review
Dependency diffs are one of the most underused parts of a security review. When a new package is added to your project, you're trusting that:
- The package author hasn't published malicious code
- The package's own dependencies are clean
- The version you're pinning doesn't have a known CVE
A side-by-side diff makes the attack surface visible. When you see "5 new packages added", that's 5 supply chain vectors to evaluate — much easier to spot in a visual diff than buried in 120 lines of JSON.
After reviewing the diff visually, always run:
npm audit
This cross-references your dependencies against the npm advisory database. A version bump that looks harmless in the diff may resolve — or introduce — a known vulnerability.
Handling Monorepos
If you manage multiple package.json files across a monorepo (apps/web/, apps/api/, packages/ui/), script the extraction:
# Extract package.json files from main branch
git show main:apps/web/package.json > web-main.json
git show main:apps/api/package.json > api-main.json
git show main:packages/ui/package.json > ui-main.json
# Then paste each pair into an online diff tool
This is how version drift gets caught — where apps/web is on React 18.2 and packages/ui is still on React 17, causing subtle incompatibilities that only surface at runtime.
For automated checks across all packages:
for dir in packages/*/; do
echo "=== $dir ==="
git diff main..feature -- "$dir/package.json"
done
A Real Code Review Workflow
Here's how this fits into a real PR review process:
- Developer opens PR with dependency updates
- CI runs
npm audit— flags any known vulnerabilities - Reviewer extracts both
package.jsonversions and pastes into a diff tool - Reviewer sees at a glance: 2 new packages (zod, date-fns), 1 version bump (react
^18.2.0 → ^18.3.0) - Reviewer checks the CHANGELOG for new packages
- Reviewer confirms the React bump is a minor version (safe)
- Approve and merge
- After merge:
npm install, CI tests pass
This takes 3 minutes. Without the diff, it takes 10 minutes of squinting at JSON, and you're still not confident you caught everything.
Key Takeaways
- Use
git difffor fast local checks before pushing - Use GitHub's PR view for reviewing changes before merging
- Use an online diff tool for detailed audits and sharing
- Always diff the lockfile alongside
package.json - Run
npm auditafter any dependency comparison - In monorepos, script the extraction to catch version drift across all packages
What's your workflow for reviewing dependency changes? Drop it in the comments — always curious how teams handle this at scale.
Originally published at online-diff.com/blog/compare-package-json
Top comments (0)