The Breaking Change Exposure scanner identifies dependencies that are known to cause migration friction before you begin an upgrade. Rather than discovering these issues mid-upgrade, you can scope the work accurately from the start.
What It Detects
This scanner flags four categories of upgrade friction:
Deprecated Packages
Packages where maintainers have explicitly declared end-of-life or recommended alternatives:
| Package | Status | Recommended Replacement |
|---|---|---|
request | Deprecated since Feb 2020 | node-fetch, undici, got, or native fetch |
node-sass | Deprecated since Mar 2020 | sass (Dart Sass) |
tslint | Deprecated since Dec 2019 | eslint with @typescript-eslint/ plugins |
moment | Maintenance mode since Sep 2020 | date-fns, dayjs, or luxon |
Legacy Node API Polyfills
Packages that fill gaps in older Node.js versions but are unnecessary on Node 18+:
| Package | Native Alternative | Notes |
|---|---|---|
node-fetch | globalThis.fetch | Native fetch available since Node 18.0.0 |
abort-controller | globalThis.AbortController | Native since Node 15.0.0 |
form-data | globalThis.FormData | Native since Node 18.0.0 |
Note: Keeping these polyfills is not harmful, but removing them reduces bundle size and eliminates maintenance overhead.
Peer Dependency Conflicts
Version mismatches between packages that declare peer dependencies. Common examples:
react-queryvs@tanstack/react-query(package rename)- Multiple React major versions in the same tree
- ESLint plugin version mismatches
Maintenance Mode Packages
Packages still functional but no longer receiving feature updates or security patches beyond critical fixes.
Exposure Score
The exposure score (0–100) quantifies how much upgrade friction exists in your dependency tree:
| Score Range | Risk Level | Interpretation |
|---|---|---|
| 0–20 | 🟢 Minimal | Few or no known pain points. Standard upgrade expected. |
| 21–50 | 🟡 Moderate | Some friction expected. Budget additional time for migration. |
| 51–100 | 🔴 Significant | Major migration work needed. Plan dedicated upgrade sprints. |
The score is calculated based on:
- Number of deprecated packages (weighted by usage frequency)
- Depth of migration required (API changes vs drop-in replacements)
- Presence of peer conflicts
Configuration
Enable or disable this scanner in your config file:
// vibgrate.config.ts
const config: VibgrateConfig = {
scanners: {
breakingChangeExposure: {
enabled: true,
// Optional: ignore specific packages
ignore: ['moment'], // keeping moment intentionally
},
},
};
Example Output
{
"breakingChangeExposure": {
"score": 35,
"riskLevel": "moderate",
"deprecated": [
{
"package": "request",
"status": "deprecated",
"deprecatedSince": "2020-02-11",
"replacements": ["node-fetch", "got", "axios", "undici"]
},
{
"package": "node-sass",
"status": "deprecated",
"deprecatedSince": "2020-03-26",
"replacements": ["sass"]
}
],
"polyfills": [
{
"package": "node-fetch",
"nativeAvailableSince": "18.0.0",
"currentNodeTarget": "18.x"
}
],
"peerConflicts": [
{
"conflict": "react-query@3.x vs @tanstack/react-query@4.x",
"resolution": "Migrate to @tanstack/react-query"
}
]
}
}
Remediation Guidance
High-Impact Migrations
For packages like request or moment that may be deeply integrated:
- Audit usage: Search for import statements across your codebase
- Estimate scope: Count files and call sites affected
- Choose replacement: Select based on your use case (see table above)
- Migrate incrementally: Replace one usage pattern at a time
Low-Impact Polyfill Removal
For packages like node-fetch on modern Node.js:
- Verify Node target: Ensure
engines.nodeis>=18 - Remove package:
npm uninstall node-fetch - Update imports: Replace
import fetch from 'node-fetch'with native usage - Test thoroughly: Native fetch has subtle API differences
Tip: The native fetch API has slight differences from node-fetch. Review the Node.js fetch documentation before removing the polyfill.