w3resource

Dead Code Detective — AST-Based Unused Export Finder: Instantly Reduce Bundle Size and Clean Up Legacy Code


Introduction: The Silent Bloat in Every Codebase

Every software project starts with good intentions. A handful of files, a few carefully chosen dependencies, and a clean architecture. Fast-forward six months of feature work, refactors, and the occasional "we might need this later" commit, and suddenly you have files no one imports, exports drifting through the codebase like tumbleweeds, and packages in package.json that nothing touches.

This "dead code" isn't just an aesthetic problem. It's a drag on productivity, a source of confusion for new team members, and a direct contributor to larger bundle sizes and slower build times. As one tool creator puts it, dead code haunts your project like a ghost.

This is the problem Dead Code Detective solves. It's a browser-based tool that performs a comprehensive static analysis of your entire JavaScript/TypeScript project, builds a complete dependency graph, and highlights every export that is never imported anywhere across the codebase. It's dead code detection, weaponized with modern web technology.

What Dead Code Detective Does: Finding the Orphans

At its core, Dead Code Detective is a static analysis tool that hunts down unused exports in your project. Unlike traditional linters that operate on a single file, it analyzes your entire codebase holistically.

The User Experience

The tool is designed to be frictionless and accessible, requiring no installation or configuration.

  1. Drag-and-Drop Folder: Users paste their entire project folder via drag-and-drop into the browser.
  2. Parsing and Analysis: The tool uses a WASM-powered AST parser to process all JavaScript and TypeScript files at lightning speed.
  3. Dependency Graph: A complete graph of every import and export relationship across the entire project is built.
  4. Visual Highlighting: Any export that is never imported anywhere is highlighted in red.

The output is immediate and actionable. For every unused export, you can see where it was defined and confirm that nothing in your project references it. The tool also groups issues by category—unused files, unused exports, unused dependencies, and more.

What It Finds

Dead Code Detective doesn't just find unused exports. It performs a comprehensive sweep of your entire project in one pass, catching multiple categories of dead weight:

  • Unused Exports: Exports that were once part of a public API but are now orphaned and never consumed.
  • Unused Files: Files that are not reachable from any entry point.
  • Unused Dependencies: Packages sitting in package.json without a single import.
  • Unresolved Imports: Imports pointing to modules that do not exist.
  • Unused Type Exports: TypeScript types that no file consumes.
  • Unused Class and Enum Members: Internal members never referenced.

Why This Approach Works

Traditional linting tools like ESLint can flag unused variables within a single file, but they lack the cross-file awareness needed to determine if an exported function is actually used elsewhere in the project. They can't tell you if that utility function in utils/index.js is still needed by any other file. Dead Code Detective solves this by building a comprehensive project-wide dependency graph.

The Modern Tech Stack Behind Dead Code Detective

Building a tool that can parse thousands of files, build a dependency graph, and visualize the results—all in a browser—requires a sophisticated combination of modern web technologies.

1. WebAssembly (SWC or esbuild Parser for Speed)

JavaScript and TypeScript parsing is a computationally intensive task. Doing it in pure JavaScript in the browser would be slow, especially for large projects. This is where WebAssembly (WASM) comes in.

Dead Code Detective uses a WASM-powered parser—either SWC or esbuild's parser compiled to WASM. Both are "super-fast alternatives for Babel," written in Rust and compiled to WebAssembly for browser use.

The benefits are substantial:

  • Blazing Speed: WASM parsers can process thousands of files in seconds.
  • Direct TypeScript/JSX Support: Unlike pure JavaScript parsers that require a separate transform step, WASM parsers handle TypeScript and JSX directly.
  • Near-Native Performance: WebAssembly runs at near-native speed in the browser.

For example, the rs-module-lexer package uses SWC to parse TypeScript, JSX, and JavaScript files directly in a single call, collapsing what would be a multi-step transform pipeline into one fast operation.

A typical implementation in the browser might look like this:

javascript:


import { default as esbuild } from "https://esm.sh/[email protected]/";
await esbuild.initialize({
  wasmURL: "https://esm.sh/[email protected]/esbuild.wasm",
});

const res = await esbuild.transform(`
  export const member = 5;
  import { useState } from 'react';
`, {
  loader: "ts",
});

This approach is essential because "browsers have no file system access," but tools like esbuild's WASM module make it possible to compile code entirely in the browser.

2. File System Access API for Reading Folders

The first step in the user experience is accepting a drag-and-drop of an entire project folder. This is made possible by the File System Access API (also known as the File System API).

This API allows web applications to read (and optionally write back to) files and directories on the user's local file system. The modern approach uses DataTransferItem.getAsFileSystemHandle() to get a FileSystemDirectoryHandle object, which provides full access to read the directory's contents.

The implementation supports progressive enhancement:

  1. Modern Path: Uses DataTransferItem.getAsFileSystemHandle() (supported in Chrome and Edge).
  2. Fallback Path: Uses the non-standard DataTransferItem.webkitGetAsEntry() for broader browser support.
  3. Classic Path: Falls back to DataTransferItem.getAsFile() for basic file support.

The user experience is seamless—drag and drop your project folder, and Dead Code Detective starts scanning immediately.

3. IndexedDB for Graph Storage

Once the dependency graph is built, it needs to be stored somewhere. For large projects, this graph can be substantial—thousands of nodes representing files, exports, and imports.

IndexedDB provides the perfect solution. It's a low-level, asynchronous NoSQL database built into the browser that can store large amounts of structured data.

For Dead Code Detective, IndexedDB is used to:

  • Cache the Dependency Graph: Store the complete graph for fast re-rendering without re-parsing.
  • Persist Analysis Results: Keep the results of the analysis across sessions.
  • Enable Incremental Analysis: Store intermediate results to support incremental updates as files change.

IndexedDB operations are asynchronous, ensuring that the main UI thread stays responsive even when working with large datasets. For a graph with thousands of nodes, IndexedDB provides the performance and capacity needed for a smooth user experience.

4. Canvas 2D for Dependency Visualization

A list of unused exports is useful, but a visual representation of the dependency graph is transformative. Dead Code Detective uses Canvas 2D rendering to display the dependency graph as an interactive visualization.

Canvas 2D is a high-performance rendering API built into browsers. It's ideal for rendering large graphs because:

  • Hardware Acceleration: Canvas rendering is GPU-accelerated in modern browsers.
  • Scalability: Canvas can render thousands of elements without performance degradation.
  • Interactivity: Canvas supports event handling for zoom, pan, and click interactions.

For graph rendering, the tool uses a library like Cytoscape.js or a custom Canvas implementation. Cytoscape.js is particularly well-suited because it provides "a full graph theory library, developed not only for graph visualization but also for analysis," with a rich API for graph analytics and interactions.

The visualization is not just a static picture—it's interactive. Users can:

  • Zoom and Pan: Navigate through large graphs.
  • Click on Nodes: See detailed information about specific files or exports.
  • Filter by Node Type: Show only files, exports, or imports.
  • Follow Dependency Chains: Trace where an export is (or isn't) used.

For a comparable example, the xcode-graph package renders interactive, zoomable, filterable dependency graphs on canvas with hardware acceleration, demonstrating the power and flexibility of this approach.

User Benefits: Cleaner Code, Faster Builds, Better Team Onboarding

Instantly Reduce Bundle Size

Every unused export that remains in your codebase is a candidate for removal. Removing them shrinks your bundle size, leading to faster load times and better performance for your users. One tool reports that in typical projects, there are potential savings of 15 KB or more from dead code alone.

Clean Up Legacy Code

Software projects evolve. Functions that were once essential become obsolete as features change. Dead Code Detective makes it easy to find and remove this legacy code, preventing it from cluttering your codebase and confusing new developers.

Improve Maintainability

Codebases with high numbers of unused exports are harder to maintain. When a developer needs to change a utility function, they have to wonder: "Is this actually used anywhere, or is it dead code?" Dead Code Detective answers that question definitively, giving developers confidence to refactor and delete with impunity.

Prevent "Just in Case" Exports

The psychological impact of dead code is subtle but real. When developers know that unused exports will be flagged, they're less likely to create "just in case" exports that clutter the API surface. The tool encourages a cleaner, more deliberate approach to exports and API design.

Onboarding and Knowledge Transfer

For new team members, a codebase littered with unused exports is a minefield of confusion. Dead Code Detective helps new developers understand what's actually used and what's legacy, accelerating the onboarding process.

CI/CD Integration

The tool can be integrated into CI/CD pipelines for automated detection. When running in CI mode, the tool can exit with a non-zero code if any issues are found, allowing it to block deployments that introduce dead code.

Conclusion: Cutting the Dead Weight

Dead Code Detective represents a significant step forward in the fight against codebase bloat. By leveraging modern web technologies—WASM-powered parsing, the File System Access API, IndexedDB, and Canvas 2D rendering—it provides a fast, accessible, and comprehensive solution for finding and eliminating unused exports.

The tool joins a growing ecosystem of dead code detection tools, including Knip ("the dead code detective your codebase deserves") and DevGhost ("find dead code, dead imports, and dead dependencies before they haunt your project"). What sets Dead Code Detective apart is its browser-first approach: no installation, no configuration, just drag-and-drop your project and get results instantly.

In a world where every kilobyte matters and code complexity is the silent enemy of productivity, Dead Code Detective empowers developers to cut the dead weight and keep their codebases lean, clean, and maintainable. As one developer said about Knip, the name comes from the Dutch word for "cut"—and that's exactly what it does.



Follow us on Facebook and Twitter for latest update.