Blog.

Tools of Front End Developers — Static Code Analysis

Cover Image for Tools of Front End Developers — Static Code Analysis
Andrew Zheng
Andrew Zheng

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.

VSCode Integration · Prettier

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