Skip to main content
Rev-dep is a high-performance dependency analysis tool built in Go that analyzes JavaScript and TypeScript codebases at exceptional speed.

Architecture Overview

Rev-dep’s architecture is designed for maximum performance through several key design decisions:

Go-Based Implementation

Rev-dep is written entirely in Go, which provides:
  • Native compilation - Runs directly on the OS without a JavaScript runtime
  • Efficient memory management - Go’s garbage collector is optimized for high-throughput applications
  • Concurrent execution - Built-in goroutines enable true parallelism across CPU cores

Core Components

1. File Discovery & Parsing

Rev-dep discovers and parses source files using a multi-stage process:
// From main.go:1443
func GetMinimalDepsTreeForCwd(cwd string, ...) {
    // Discover all files in the codebase
    files = GetFiles(cwd, []string{}, allExcludePatterns)
    
    // Parse imports from files in parallel
    fileImportsArr, _ := ParseImportsFromFiles(files, ignoreTypeImports, ParseModeBasic)
    
    // Resolve imports to actual file paths
    fileImportsArr, sortedFiles, resolverManager := ResolveImports(...)
    
    // Build minimal dependency tree
    minimalTree := TransformToMinimalDependencyTreeCustomParser(fileImportsArr)
}
The parser (parseImports.go) uses a custom-built lexer that:
  • Handles import and export statements
  • Detects require() calls
  • Skips comments, strings, and template literals
  • Processes Vue and Svelte single-file components

2. Dependency Graph Construction

Rev-dep builds a minimal dependency tree representation:
// From buildDepsGraph.go:9
func buildDepsGraphForMultiple(deps MinimalDependencyTree, entryPoints []string, ...) {
    // Build graph using depth-first traversal
    var inner func(path string, visited map[string]bool, depth int, parent *SerializableNode)
    
    // For each entry point, build its subgraph
    for _, entryPoint := range entryPoints {
        root := inner(entryPoint, sharedVisited, 1, nil)
        roots[entryPoint] = root
    }
}
The graph structure:
  • Nodes represent files
  • Edges represent import relationships
  • Vertices store children and parent references
  • Modules track external dependencies

3. Analysis Engines

Each check type has its own optimized analysis engine: Circular Dependency Detection (circularDeps.go):
func FindCircularDependencies(deps MinimalDependencyTree, ...) [][]string {
    var dfs func(node string) bool
    dfs = func(node string) bool {
        visited[node] = true
        recStack[node] = true
        
        // Traverse dependencies
        for _, dep := range nodeDeps {
            if recStack[depPath] {
                // Cycle detected!
                cycles = append(cycles, cycle)
            }
        }
    }
}
Unused Files Detection: Identifies files not reachable from any entry point by inverting the dependency graph. Unused Exports Detection: Tracks which exports are imported elsewhere in the codebase.

Execution Flow

Single Command Execution

  1. Parse CLI arguments - Cobra framework handles command routing
  2. Discover files - Walk directory tree, apply gitignore patterns
  3. Parse imports - Parallel parsing with worker pool (GOMAXPROCS × 2)
  4. Resolve imports - Match import requests to actual files
  5. Build graph - Construct in-memory dependency tree
  6. Run analysis - Execute the requested check
  7. Format output - Display results to user

Config-Based Execution

When running rev-dep config run, the process is optimized:
// Pseudo-code from config processing
func ProcessConfig() {
    // 1. Build dependency tree once for all rules
    minimalTree := GetMinimalDepsTreeForCwd(...)
    
    // 2. Process rules in parallel
    for _, rule := range config.Rules {
        go func(rule) {
            // 3. Run all checks for this rule in parallel
            var wg sync.WaitGroup
            for _, check := range rule.Checks {
                wg.Add(1)
                go runCheck(check, minimalTree)
            }
            wg.Wait()
        }(rule)
    }
}
This approach provides significant performance benefits:
  • Single tree build - Dependency graph is built once and reused
  • Parallel rule processing - Multiple rules run simultaneously
  • Parallel check execution - All checks within a rule run concurrently

Parallelization Strategy

Rev-dep leverages Go’s concurrency primitives extensively:

File Parsing Parallelization

// From parseImports.go:1505
func ParseImportsFromFiles(filePaths []string, ...) {
    maxConcurrency := runtime.GOMAXPROCS(0) * 2
    sem := make(chan struct{}, maxConcurrency)
    
    for _, filePath := range filePaths {
        wg.Add(1)
        sem <- struct{}{} // Acquire semaphore
        
        go func(path string) {
            defer func() { <-sem }() // Release semaphore
            parseContent := fileContent
            imports := ParseImportsByte(parseContent, ...)
        }(filePath)
    }
}

Graph Building Parallelization

When analyzing multiple entry points:
// From main.go:310
maxConcurrency := runtime.GOMAXPROCS(0) * 2
sem := make(chan struct{}, maxConcurrency)

for _, entryPoint := range entryPoints {
    wg.Add(1)
    sem <- struct{}{}
    go func(ep string) {
        defer func() { <-sem }()
        buildGraph(ep, &depsGraphs, &wg, &mu)
    }(entryPoint)
}

Import Resolution

Rev-dep implements comprehensive import resolution:

TypeScript Path Aliases

Reads tsconfig.json and resolves path aliases like:
{
  "compilerOptions": {
    "paths": {
      "@components/*": ["src/components/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

Package.json Exports

Supports the modern exports field in package.json:
{
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js"
    },
    "./utils": "./dist/utils.js"
  }
}

Monorepo Support

Automatically detects and resolves workspace packages:
  • Reads pnpm-workspace.yaml, package.json workspaces
  • Resolves cross-package imports
  • Validates dependencies are declared in package.json

Performance Impact

The Go-based architecture with parallel processing enables Rev-dep to analyze 500k+ LoC codebases in under 500ms, making it 10x-200x faster than JavaScript-based alternatives.

Build docs developers (and LLMs) love