Tools of Front End Developers — Static Code Analysis
Introduction
The complexity of our web applications has grown drastically. Fixing bugs is part of the daily life of a developer. Luckily, there is a set of tools that can help us avoid some of the most common bugs and improve the overall developer experience.
This article will introduce a list of tools that I have used at work.
*This article is inspired by the awesome Kent C. Dodds 🧢
ESlint
ESlint is a well-known tool that statically analyzes the code and finds problems. It can fix many of those problems automatically so we as developers don’t have to spend precious time fixing those problems in the future. ESlint is also highly customizable, developers have the ability to customized the rules to support different coding styles.
To get started, we can create a new file .eslintrc
with something like this.
{
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"extends": ["eslint:recommended"],
"rules": {
"strict": ["error", "never"]
},
"env": {
"browser": true
}
}
parserOptions
: By default, ESlint expects ES5 syntax. Since most of the modern application is written in newer ECMAScript version and compile into ES5 using Babel TypeScript Compiler, we need to override the parser options to support our source code. In the example config, we want ESlint to use ES10 syntax and enable the support for ES Modules and JSX.
extends
: Instead of defining all the rules, we use eslint:recommended
rule set as our starting point.
rules
: We can add any additional rule as needed and it will override the same rules defined in extends
.
env
: We also want ESLint to be aware that our code is meant to execute in the browser environment. So ESlint will not throw any error for any browser-specific code/syntax such as console.log
.
Prettier
A well-formatted code base with consist code format is much easier to understand but developers don’t want to waste their precious time to formatting code. There is where Prettier comes into play.
Once we installed the Prettier package, we can simply play around with the config we want on Prettier Playground and copy the config JSON to .prettierrc
. We can simply use Prettier as npm script. --write
write will format the source files that match the string pattern. --list-different
will tell if any files will be formatted. We can think of it as Prettier’s dry-run option.
"scripts": {
"prettier": "prettier \"**/*.+(js|json)\"",
"format": "npm run prettier -- --write",
"check-format": "npm run prettier -- --list-different",
}
Since Prettier will format the source, we can turn off some of ESlint rules that will not occur, we can install eslint-config-prettier
and put it at the end of extends
config. ”extends”: [“eslint:recommended”, “eslint-config-prettier”]
Prettier has decent IDE/Editor integration which allows auto code format on-save. Here are the most common ones.
WebStorm/IntelliJ Setup · Prettier
TypeScript
TypeScript is a topic for another day. We will focus on enabling ESLint support for TypeScript files here. Once we install the TypeScript package, we need to create a tsconfig.json
for the ESlint’s TypeScript parser. It can be something as simple as the following if we already use Babel to transform TypeScript file. We are telling the compiler not to compile ("noEmit": true
) the TypeScript files into JavaScript for all files in the src
directory.
{
"compilerOptions": {
"noEmit": true,
"baseUrl": "./src"
}
}
ESlint does not understand TypeScript files by default. So we need to install @typescript-eslint/eslint-plugin
and @typescript-eslint/parser
to help us deal with those files. We will override default ESlint setting for all TS and TSX files in .eslintrc
"overrides": [
{
"files": "**/*.+(ts|tsx)",
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint/eslint-plugin"],
"extends": [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"eslint-config-prettier/@typescript-eslint"
]
}
]
Husky
Git hooks can be useful for preventing bad code being committed to the code base but configuring it is not as straightforward. Husky is a package that helps us config git hooks by handling the boilerplate stuff behind the scenes. Once the package is installed, we can create .huskyrc
with the git hook we need. In the following example, we want to make sure linting and type checking are passed befor any code is committed.
{
"hooks": {
"pre-commit": "npm run check-type && npm run check-format && npm run lint"
}
}
lint-staged
Husky and git hooks are great but it will starting run slower as our project grows. Most of the time, we only want to validate the file that will be committed. lint-stage will pass the files that match glob pattern as arguments to specific commands. We can create .lintstagedrc
with something similar to this:
{
"*.+(js|ts|tsx)": [
"eslint"
],
"*.+(|ts|tsx)": [
"tsc"
],
"*/*.+(js|json|ts|tsx)": [
"prettier --write",
"git add"
]
}
In the above example, we will
- Lint all Javascript and TypeScript files
- Check type for TypeScript files
- Format all JavaScript, TypeScript and JSON files with Prettier before stage those files
We can simplify the pre-commit hook with “pre-commit”: “lint-staged”
Conclusion
I hope this article gives a decent overview of some of the tools we can leverage to improve our code quality and developer experience. Each of the tool we have mentioned is highly customizable. I highly recommend everyone to explore them further.
You can find the source code at GitHub - xian0831/static-testing-starter: This project demonstrate a simple setup of some static code quality tool