frontend

Maintain a high quality codebase with an ease

Will4_U
#codebase#frontend#tools

Some tools exist to help developers keep the code consistent and easier to understand.

I want to show you various tools to help you write better quality software.

Note: this article was created with web developers in mind, but non-web folks can also find some exciting things.

Table of Contents

  1. Extensions
  2. Tools
  3. Tests (units, integrations and E2E)
  4. Principles

Extensions

Extensions

Those are the easiest ones to set up. The huge advantage is that they’re global, so you can use them everywhere without installing them in the project.

These are the ones that I use (and I can freely recommend them):

SonarLint

A great tool that gives you instant feedback based on your code. Can suggest some improvements and catch potential bugs.

Abracadabra, refactor this!

Enhances the refactoring options in VS Code, which makes the refactoring code easier. This won’t automatically make your code better, but it is a helpful tool to have.

JS Refactoring Assistant (paid)

This is a combination of the previous two extensions. It suggests refactoring changes to make the code cleaner and easier to read.

Tools

Tools

ESLint

A must-have utility for any JavaScript project. It helps to keep the code style consistent, and it can prevent different anti-patterns and common mistakes.

To make work with ESLint easier, there’s the ESLint extension for VS Code, which includes the commands to check the logs and restart the server, which makes it easier to debug the configs.

My personal config files

module.exports = {
  'env': {
    'browser': true,
    'es2022': true,
    'node': true
  },
  'extends': [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/strict',
    'plugin:react/jsx-runtime',
    'eslint-config-async'
  ],
  'overrides': [
  ],
  'parser': '@typescript-eslint/parser',
  'parserOptions': {
    sourceType: 'module',
    tsconfigRootDir: __dirname,
    project: ['./tsconfig.json'],
  },
  'plugins': [
    'react',
    '@typescript-eslint'
  ],
  'rules': {
    'quotes': [
      'warn',
      'single'
    ],
    'semi': [
      'warn',
      'never'
    ],
    '@typescript-eslint/no-floating-promises': 'error',
    '@typescript-eslint/no-unsafe-call': 'warn',
    '@typescript-eslint/no-unsafe-return': 'warn',
    '@typescript-eslint/no-unnecessary-type-assertion': 'warn',
    'no-shadow': 'error',
    'prefer-const': 'warn',
    'no-console': 'warn',
    'no-debugger': 'warn',
    'no-magic-numbers': ['error', { ignore: [1, 0, 404, 200, 500] }],
    'no-dupe-else-if': 'error',
    'max-depth': ['error', 4],
    'max-lines': 'warn',
    'max-params': ['error', 3],
    'no-unneeded-ternary': 'error',
    'react/boolean-prop-naming': 'error',
    'react/jsx-max-depth': ['warn', { max: 5 }],
    'import/no-default-export': 'error',
  }
}

I’ll describe the most important rule I decided to use:

You can read about the rules here.

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "noPropertyAccessFromIndexSignature": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "types": ["node", "jest", "@testing-library/jest-dom"]
  },
  "include": [
    "src",
    ".eslintrc.js",
  ],
}

You can adjust it to your needs.

Husky

Pre-commit hooks are (mostly) cool. Theo - ping.gg wouldn’t like this, but I don’t care.

Sometimes developers forget to run tests, or you accidentally push some invalid code to the repo.

Husky helps run the hooks (some tasks) that will be run, i.e. whenever you commit or push the changes to the repo.

This forces the validation to run before the code is pushed to the repo.

However, do not run heavy tasks like testing E2E or the whole project cause it will be time-consuming and highly annoying.

My personal recommendation:

Commit messages

PLEASE, please, make your commits consistent. This makes the Git history and pulls requests easier to track and potentially rollback the changes.

My go-to choice is Conventional Commits - give it a shot and connect it to Husky via Commitlint.

CI/CD (GitHub Actions, CircleCI, etc.)

They are helpful to automatically deploy your app (for example, to preview the deployment to test it manually) and run all the tests and linters to check whenever the branch is ready to review.

This is the most straightforward workflow file for GitHub Actions to run the tests whenever the pull request is created.

name: pull-request
on:
  pull_request:
    branches: [ main ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v3.3.0
      - name: Set up node 
        uses: actions/setup-node@v3.6.0
      - name: Install dependencies
        run: npm install
      - name: Run tests 
        run: npm test

You can adjust it to your needs.

Tests (units, integrations and E2E)

Tests

Those are the ones that will save your code from regression whenever you decide to refactor the code.

What tests should be like?

Like expect(condition).toBe(true) or expect(items.length).toBe(5)

You can learn about these here: bewebdev.tech - Testing.

Principles

Principles

No tool will save you from writing readable code.

All of these will make your code significantly easier to maintain and scale.

You can learn about these topics here: bewebdev.tech - Clean Code and bewebdev.tech - Design Patterns.


bewebdev.tech is a resource hub for web developers that helps them to keep up with industry needs.

← wracaj na bloga