What is Dependency Analysis?
In modern JavaScript and TypeScript projects, files import and export functionality from each other. These import relationships form a dependency graph where:- Nodes represent files or modules
- Edges represent import statements
- Direction shows which file depends on which
Button.tsx→utils/text.tsButton.tsx→Button.css
Why Dependency Analysis Matters
As codebases grow, understanding dependencies becomes critical:🔍 Find Dead Code
Files and functions that are never imported can be safely removed, reducing bundle size and maintenance burden.🔄 Detect Circular Dependencies
When File A imports File B, and File B imports File A (directly or transitively), it creates initialization issues and makes refactoring difficult.🏗️ Enforce Architecture
Ensure UI components don’t import from data layers, or that public APIs don’t depend on internal implementation details.📦 Optimize Dependencies
Identify unused npm packages, missing declarations, or accidental usage of dev dependencies in production code.Types of Issues Rev-dep Detects
Circular Dependencies
What it is: A cycle in the import graph where modules depend on each other in a loop.- Causes initialization order issues
- Can lead to runtime errors with undefined values
- Makes code harder to understand and refactor
Orphan Files (Dead Code)
What it is: Files that are never imported by any entry point. Why it’s problematic:- Increases repository size
- Confuses developers about what code is active
- Wastes CI/CD resources building/testing unused code
Unused Exports
What it is: Exported functions, classes, or variables that are never imported anywhere.- Creates maintenance burden
- Increases bundle size (if not tree-shaken)
- Misleads developers about API surface
Unused Node Modules
What it is: Packages declared inpackage.json but never imported in code.
- Increases
node_modulessize - Slows down
npm install - Creates unnecessary security audit surface
- Wastes disk space in deployed containers
Missing Node Modules
What it is: Imports from packages not declared inpackage.json.
- Code works locally (if package is hoisted) but fails in CI or production
- Violates package manager workspace resolution rules
- Creates hidden coupling between packages in monorepos
Unresolved Imports
What it is: Import statements that can’t be resolved to actual files.- Causes build failures
- Breaks at runtime
- Often happens after refactoring moves
Dev Dependencies in Production
What it is: Imports fromdevDependencies in production code paths.
devDependenciesaren’t installed in production environments- Causes runtime errors
- Increases bundle size with test utilities
devDependencies:
Rev-dep’s Approach
Rev-dep takes a static analysis approach:1. Parse Source Code
Custom-built lexer extracts all import/export statements without executing code:2. Resolve Import Paths
Convert import requests to absolute file paths:- TypeScript path aliases (
@components/*) - Node module resolution (
node_moduleslookup) - Relative paths (
../utils) - Package.json exports
- Monorepo workspace packages
3. Build Dependency Graph
Construct in-memory representation of all relationships:4. Run Analysis Algorithms
Each check uses graph algorithms:- Circular dependencies - Depth-first search with recursion tracking
- Orphan files - Inverse reachability from entry points
- Unused exports - Cross-reference all exports with all imports
- Module checks - Compare graph edges with package.json
Type-Only Imports
Rev-dep distinguishes between runtime and type imports:ignoreTypeImports flag:
- Circular dependency detection can ignore type cycles (often safe)
- Orphan detection can exclude files only imported for types
- Module checks can allow type-only imports from devDependencies
Configuration Approach
Rev-dep’s config system allows running multiple checks in a single pass, analyzing the dependency graph once and applying all rules in parallel. This is significantly faster than running individual commands separately.
Entry Points
Many analyses start from entry points - files that aren’t imported by anything else:- Application entry points:
src/index.ts,src/main.tsx - Page routes:
pages/**/*.tsx(Next.js, etc.) - Test files:
**/*.test.ts - Build scripts:
scripts/**/*.ts
