Skip to main content
Scanners

Breaking Change Exposure Scanner

Flag packages and patterns known to cause upgrade pain.

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:

PackageStatusRecommended Replacement
requestDeprecated since Feb 2020node-fetch, undici, got, or native fetch
node-sassDeprecated since Mar 2020sass (Dart Sass)
tslintDeprecated since Dec 2019eslint with @typescript-eslint/ plugins
momentMaintenance mode since Sep 2020date-fns, dayjs, or luxon

Legacy Node API Polyfills

Packages that fill gaps in older Node.js versions but are unnecessary on Node 18+:

PackageNative AlternativeNotes
node-fetchglobalThis.fetchNative fetch available since Node 18.0.0
abort-controllerglobalThis.AbortControllerNative since Node 15.0.0
form-dataglobalThis.FormDataNative 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-query vs @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 RangeRisk LevelInterpretation
0–20🟢 MinimalFew or no known pain points. Standard upgrade expected.
21–50🟡 ModerateSome friction expected. Budget additional time for migration.
51–100🔴 SignificantMajor 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:

  1. Audit usage: Search for import statements across your codebase
  2. Estimate scope: Count files and call sites affected
  3. Choose replacement: Select based on your use case (see table above)
  4. Migrate incrementally: Replace one usage pattern at a time

Low-Impact Polyfill Removal

For packages like node-fetch on modern Node.js:

  1. Verify Node target: Ensure engines.node is >=18
  2. Remove package: npm uninstall node-fetch
  3. Update imports: Replace import fetch from 'node-fetch' with native usage
  4. 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.

Related Documentation