π Mastering Code Quality: A Complete Guide to Static Analysis Tools
Ensuring code quality is no longer optionalβit's a critical part of building reliable, scalable, and maintainable software. High-quality code not only reduces bugs and improves performance, but also fosters better collaboration and easier onboarding for new developers.
This comprehensive guide walks you through setting up a static code analysis pipeline using industry-standard tools. We'll use a React project as our reference implementation, but the principles and tools discussed here can be applied to any Node.js-based project.
You'll learn how to integrate and configure essential tools such as:
-
ESLint for JavaScript/TypeScript linting
-
Prettier for consistent code formatting
-
Stylelint for CSS/SCSS style validation
-
markdownlint for markdown files
-
cspell for detecting spelling issues in code and documentation
-
Husky and lint-staged for enforcing quality checks before commits
Whether you're starting a new project or improving an existing one, this guide will help you establish a solid foundation for automated static analysis, keeping your codebase clean, readable, and error-free.
Let's dive in and build a better code quality pipelineβstep by step.
π‘ Why Static Code Analysis Mattersβ
Static code analysis helps catch issues before they make it into production. By automating checks for code style, potential bugs, and even spelling errors, you can:
- β Maintain consistent code style across your team
- π Catch bugs early in the development process
- π§Ή Reduce technical debt
- π Improve code readability and maintainability
- π Enforce best practices
π§ The Static Analysis Toolchainβ
Let's visualize the complete toolchain we'll be setting up:
ποΈ Setting Up Your React Projectβ
Let's start by creating a new React application:
npx create-react-app my-app --use-npm
cd my-app
git init
π¦ Installing Dependenciesβ
We'll need several development dependencies to set up our static analysis pipeline:
yarn add -D eslint prettier stylelint husky lint-staged stylelint-config-standard cspell
stylelint-config-standard markdownlint markdownlint-cli
π Tool Configuration Workflowβ
The configuration process follows this pattern:
π‘οΈ Configuring ESLintβ
ESLint helps identify and report on patterns in JavaScript/TypeScript code:
npx eslint --init
Create .eslintrc.json
:
{
"extends": ["react-app", "eslint:recommended", "plugin:prettier/recommended"],
"rules": {
"prettier/prettier": "error"
}
}
Create .eslintignore
:
# Third party
**/node_modules
# Build products
build/
static/
docs/
Add scripts to package.json
:
"scripts": {
"lint:ts": "eslint \"./src/**/*.{ts,tsx}\" --max-warnings 0",
"lint:ts:fix": "eslint --fix \"./src/**/*.{ts,tsx}\" --max-warnings 0"
}
β¨ Configuring Prettierβ
Prettier ensures consistent code formatting:
Create .prettierrc
:
{
"arrowParens": "always",
"bracketSpacing": true,
"printWidth": 100,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "none"
}
Create .prettierignore
:
.git
.github
.yarn
.husky
build
node_modules
static
Add scripts to package.json
:
"scripts": {
"format": "prettier --write .",
"format:diff": "prettier --list-different ."
}
π¨ Configuring Stylelintβ
Stylelint helps maintain consistent CSS/SCSS:
Create .stylelintrc
:
{
"extends": "stylelint-config-standard",
"rules": {
"selector-class-pattern": null,
"value-keyword-case": ["lower", { "camelCaseSvgKeywords": true }]
}
}
Add scripts to package.json
:
"scripts": {
"lint:style": "stylelint \"**/*.css\"",
"lint:style:fix": "yarn lint:style --fix"
}
π Configuring markdownlintβ
markdownlint ensures consistent Markdown formatting and structure:
Create .markdownlint.json
:
{
"default": true,
"MD013": { "line_length": 100 },
"MD033": false,
"MD041": false,
"no-hard-tabs": true,
"whitespace": true
}
Add scripts to package.json
:
"scripts": {
"lint:md": "markdownlint \"**/*.md\" --ignore node_modules",
"lint:md:fix": "markdownlint \"**/*.md\" --ignore node_modules --fix"
}
π Configuring cspell (Spell Checking)β
cspell helps catch spelling errors in your code and documentation:
npx cspell --init
Modify .cspell.json
:
{
"version": "0.2",
"language": "en",
"ignorePaths": ["node_modules", "build", "static", ".docusaurus", "i18n"],
"dictionaryDefinitions": [
{
"name": "project-words",
"path": "./project-words.txt",
"noSuggest": true
}
],
"dictionaries": [
"css",
"html",
"fonts",
"typescript",
"softwareTerms",
"companies",
"lorem-ipsum",
"project-words"
]
}
Create a project-words.txt
file for custom terminology.
Add scripts to package.json
:
"scripts": {
"lint:spelling": "cspell \"docs/**/*.md\" \"blog/**/*.md\" \"src/**/*.js\" \"src/**/*.tsx\"
\"docusaurus.config.js\" --no-progress --show-context --show-suggestions",
"lint:spelling:fix": "yarn rimraf project-words.txt && echo \"# Project Words - DO NOT TOUCH -
This is updated through CI\" >> project-words.txt && yarn -s lint:spelling --words-only --unique
--no-exit-code --no-summary \"**\" | cross-env LC_ALL=en_US.UTF-8 sort --ignore-case >> project-words.txt"
}
π Automating with Git Hooksβ
Git hooks help enforce quality standards before code is committed or pushed:
πΆ Setting up Huskyβ
npx husky init
Add pre-commit hook:
echo "yarn run lint-staged" > .husky/pre-commit
Add pre-push hook:
echo "yarn run lint-staged" > .husky/pre-push
β‘ Configuring lint-stagedβ
Add to package.json
:
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write",
"cspell --no-progress --show-context --show-suggestions"
],
"src/**/*.{css,scss}": [
"stylelint --fix",
"prettier --write"
],
"{docs,blog}/**/*.{md,mdx}": [
"markdownlint --fix",
"prettier --write",
"cspell --no-progress --show-context --show-suggestions"
]
}
π§ͺ Testing Your Setupβ
Run these commands to verify your setup:
yarn lint:ts
yarn format
yarn lint:style
yarn lint:md
yarn lint:spelling
π Comprehensive Quality Check Scriptβ
Add a comprehensive check script to package.json
:
"scripts": {
"quality-check": "yarn lint:ts && yarn lint:style && yarn lint:md && yarn lint:spelling && yarn format:diff"
}
π§© VSCode Extensions for Your Toolchainβ
To make your development experience even better, install these VSCode extensions that integrate with your static analysis tools:
ESLintβ
ESLint by Dirk Baeumer
https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
Integrates ESLint into VS Code to highlight linting errors in your JavaScript/TypeScript code.
code --install-extension dbaeumer.vscode-eslint
Prettierβ
Prettier - Code formatter by Prettier
https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
Formats your code using Prettier on save or with a command.
code --install-extension esbenp.prettier-vscode
Stylelintβ
Stylelint by Stylelint
https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint
Highlights CSS/SCSS linting errors in your stylesheets.
code --install-extension stylelint.vscode-stylelint
markdownlintβ
markdownlint by David Anson
https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
Provides linting for Markdown files.
code --install-extension davidanson.vscode-markdownlint
Code Spell Checkerβ
Code Spell Checker by Street Side Software
https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker
Checks your code for spelling errors.
code --install-extension streetsidesoftware.code-spell-checker
Error Lensβ
Error Lens by Alexander
https://marketplace.visualstudio.com/items?itemName=usernamehw.errorlens
Improves error highlighting, making errors, warnings, and other language diagnostics stand out more prominently.
code --install-extension usernamehw.errorlens
GitLensβ
GitLens by GitKraken
https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens
Helps you visualize code authorship and navigate through Git repositories.
code --install-extension eamodio.gitlens
Settings Syncβ
Settings Sync by Shan Khan
https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync
Synchronize your VSCode settings across different machines.
code --install-extension shan.code-settings-sync
Install All Extensions at Onceβ
You can install all these extensions with a single command:
code --install-extension dbaeumer.vscode-eslint --install-extension esbenp.prettier-vscode
--install-extension stylelint.vscode-stylelint --install-extension davidanson.vscode-markdownlint
--install-extension streetsidesoftware.code-spell-checker --install-extension usernamehw.errorlens
--install-extension eamodio.gitlens --install-extension shan.code-settings-sync
π Benefits of This Approachβ
π Static Analysis Tools Comparisonβ
π Best Practices for Team Adoptionβ
- π Gradual Implementation: Start with basic rules and gradually increase strictness
- π Documentation: Clearly document why each tool is used and how to work with it
- βοΈ CI Integration: Add these checks to your CI pipeline
- π¨βπ» Team Training: Ensure everyone understands the tools and their benefits
- π Regular Updates: Keep your tools and configurations up to date
- π οΈ Customize Rules: Adapt rules to fit your team's specific needs and preferences
- π€ Automate Fixes: Use the
--fix
option where possible to automate corrections
β Common Issues and Solutionsβ
Issue | Solution |
---|---|
π΅ Too many errors after initial setup | Start with a subset of rules and gradually add more |
π₯ Conflicts between tools | Ensure tools are configured to work together (e.g., Prettier with ESLint) |
π€ False positives in spell checking | Add legitimate terms to your custom dictionary |
β±οΈ Slow pre-commit hooks | Use lint-staged to only check changed files |
π ββοΈ Team resistance | Demonstrate the benefits and provide clear documentation |
π Conclusionβ
By implementing this comprehensive static code analysis setup, you'll significantly improve your React project's code quality and maintainability. The initial investment in configuration pays dividends through reduced bugs, consistent code style, and improved developer experience.
With the addition of markdownlint, you now have complete coverage across all file types in your project:
- βοΈ JavaScript/TypeScript (ESLint)
- π¨ CSS/SCSS (Stylelint)
- π Markdown (markdownlint)
- π All files (cspell for spelling, Prettier for formatting)
Remember that the goal isn't to create obstacles but to establish guardrails that help your team deliver better code more efficiently. As your project evolves, don't hesitate to adjust your configuration to better suit your team's needs.
Happy coding! π