Inspiration: The Problem of "Polyfill Rot"

As a web developer, I've often worked on legacy projects where the package.json is a graveyard of old dependencies. Many of these, especially polyfills like whatwg-fetch or intersection-observer, were once essential. Today, with the web platform maturing and the Baseline initiative clearly defining modern browser capabilities, these polyfills are often just "dead code" bloating our applications.

This problem of "polyfill rot" is tedious and risky to solve manually. A developer has to:

  1. Identify a potential polyfill.
  2. Manually search the entire codebase to see if it's even used.
  3. Research if its native equivalent is now part of Baseline.
  4. Finally, decide to remove it.

The inspiration for Baseline Cleaner was simple: what if a tool could automate this entire, painful process? The Baseline Tooling Hackathon was the perfect catalyst to build it.

How I Built It: The "Intelligent" Engine

I built baseline-cleaner as a modern, professional command-line tool using Node.js, TypeScript, and the oclif framework. Its intelligence comes from a powerful three-step process:

  1. Dependency Scan: The tool first reads the project's package.json and compares its dependencies against a curated, extensible "knowledge base" (library-map.json) of known polyfills and the native web features they correspond to.

  2. Static Code Analysis (AST): This is the core of the tool's intelligence. Instead of just guessing, baseline-cleaner uses the Babel parser to transform the entire source code into an Abstract Syntax Tree (AST). It then traverses this tree to confirm if a candidate polyfill is actually being import-ed and used. This prevents false positives for dependencies that are installed but no longer referenced in the code.

  3. Baseline Check & Reporting: For every polyfill that is confirmed to be in use, the tool uses the official web-features package as a source of truth. It checks the feature's Baseline status and generates a clear, actionable report directly in the terminal using Ink and React, providing a polished and modern user experience.

Challenges I Faced: The Toolchain Gauntlet

The biggest challenge was not the core logic, but the modern JavaScript toolchain itself. Building a reliable, distributable ESM-based TypeScript CLI tool turned into a deep debugging marathon.

  • Module Mayhem: I faced numerous issues related to the conflict between CommonJS (the format of older tools like @babel/traverse) and the ES Modules (import/export) standard I chose for the project. This led to a series of TypeError: is not a function and SyntaxError problems that required deep investigation into tsconfig.json options like moduleResolution, esModuleInterop, and how oclif's ts-node runner operates.

  • The "Compile-First" Pivot: After fighting the development-mode runner, I made a key architectural decision to pivot to a "compile-first" strategy. This involved configuring tsc to build the project into a dist folder and running the pure JavaScript output, which finally stabilized the entire application. It was a powerful lesson in creating a robust build process.

  • Data-Driven Debugging: I initially made assumptions about the featureId keys in the web-features package, which led to incorrect 'unknown' statuses in my reports. This forced me to build "inspection" logic into the tool itself to query the data structure and find the correct keys, reinforcing the developer mantra: "don't assume, verify."

What I Learned

This hackathon was an incredible learning experience.

  • I gained a deep, practical understanding of Abstract Syntax Trees and how powerful they are for creating "code-aware" tools.
  • I learned (the hard way) about the nuances of the JavaScript module ecosystem and how to build and configure a modern, ESM-first TypeScript project from scratch.
  • I discovered the power of Ink for building beautiful, modern CLI user interfaces with React.
  • Most importantly, I learned the value of perseverance and methodical debugging. By treating every frustrating error not as a wall but as a clue, I was able to navigate a complex set of problems and build a tool I am incredibly proud of.

Built With

Share this project:

Updates