How to Add JSDoc to a Legacy JavaScript Codebase
Legacy JavaScript codebases often suffer from poor documentation. Function names may be descriptive, but their parameters, return types, and intended behavior are rarely documented. This makes onboarding new developers difficult, increases the risk of regressions, and complicates refactoring efforts.
Why JSDoc Matters
JSDoc provides a standard format for documenting JavaScript code. When properly applied, it enables:
- IDE autocomplete and inline documentation
- Static type checking with TypeScript or Flow
- Automated documentation generation
- Better code reviews through explicit contracts
Step 1: Assess Your Current State
Before adding documentation, understand what you're working with. Run an automated analysis tool to scan your codebase:
legacy-doc-ai check
This identifies files with missing or incomplete documentation. For example, analyzing a legacy testing library with 13 JavaScript files reported 184 functions and 5 classes. Only 22 functions (about 12%) had docstrings.
Step 2: Identify High-Priority Targets
Not all functions need documentation at the same time. Prioritize based on:
- Public APIs - Functions that external users call
- Complex logic - Functions with multiple parameters or conditional branches
- Entry points - Functions called frequently across the codebase
Step 3: Generate Draft Documentation
Manual documentation of 160+ functions would take days. Use an automated tool to generate draft JSDoc blocks based on function signatures:
legacy-doc-ai docstrings --dry-run
The --dry-run flag shows what documentation would be added without modifying any files, allowing you to review the output and adjust configuration if needed.
Step 4: Review and Refine
Automated documentation is never perfect. Spend time reviewing the dry-run output, focusing on:
- Functions with complex parameter structures
- Callback functions and event handlers
- Functions with non-standard return types
Step 5: Commit Documentation in Batches
Rather than committing all new docstrings at once, break them into logical groups. Start with utility functions before moving to core functionality. This makes reviewing changes easier and reduces merge conflicts.
Common Pitfalls to Avoid
- Over-documenting obvious code - Simple accessors like
getName()rarely need docstrings unless they have side effects - Missing JSDoc - If documenting parameters, use
@paramconsistently across all functions - Documentation drift - Update docstrings when function signatures change
The Result
Transforming a codebase from 12% function coverage to 100% is achievable with automated tools. Once documentation is in place, consider adding CI checks to catch undocumented functions in new code.