Back to blog
5 min read
Adding ESLint to Webpack with React and TypeScript

Background

When working in a team of developers, it is best to have a standard code style. ESLint allows developers to adhere to those basic code conventions by enforcing the same rules and making your code look unified. This helps with maintaining a readable codebase for all developers and avoid any code 💩 smells. ESLint allows you to set up and enforce these rules across the codebase.

Note With TypeScript, there are 2 linting solutions: 1. ESLint and 2. TSLint. The TypeScript team has highlighted in their roadmap that they will be focusing their efforts on ESLint rather than TSLint where they state:

ESLint already has the more-performant architecture… we’ll be switching the TypeScript repository over to using ESLint… - Source

Setting up ESLint with Webpack and TypeScript

  • Install dependencies:
npm install eslint

Add Dependencies

npm install -D eslint-loader @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react

Add ESLint to Webpack configs

  • Update your webpack.config.js file with:
  • This will configure ESLInt as part of the Webpack’s build process with eslint-loader. After each build, any ESLint errors or warnings will be logged in your terminal with ESLint errors preventing your app to compile.
rules: [
  /**
   * ESLINT
   * First, run the linter.
   * It's important to do this before Babel processes the JS.
   * Only testing .ts and .tsx files (React code)
   */
  {
    test: /\.(ts|tsx)$/,
    enforce: 'pre',
    use: [
      {
        options: {
          eslintPath: require.resolve('eslint'),

        },
        loader: require.resolve('eslint-loader'),
      },
    ],
    exclude: /node_modules/,
  },
]

Add ESLint configuration file

  • Create an .eslintrc.js config file:
  • Note: By creating a JavaScript file instead of a JSON file (.eslintrc) we can add comments for other developers.
touch .eslintrc.js
  • Add ESLint rules to .eslintrc.js:
module.exports =  {
  parser:  '@typescript-eslint/parser',  // Specifies the ESLint parser
  extends:  [
    'plugin:react/recommended',  // Uses the recommended rules from @eslint-plugin-react
    'plugin:@typescript-eslint/recommended',  // Uses the recommended rules from @typescript-eslint/eslint-plugin
  ],
  parserOptions:  {
    ecmaVersion:  2018,  // Allows for the parsing of modern ECMAScript features
    sourceType:  'module',  // Allows for the use of imports
    ecmaFeatures:  {
      jsx:  true,  // Allows for the parsing of JSX
    },
  },
  rules:  {
    // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
    // e.g. '@typescript-eslint/explicit-function-return-type': 'off',
  },
  settings:  {
    react:  {
      version:  'detect',  // Tells eslint-plugin-react to automatically detect the version of React to use
    },
  },
};

Adding pre-commit hook with ESLint

To avoid 💩 code slipping in your codebase, pre-commit checks can be used to lint your code and check for ESLint errors and warnings before each commit (git commit). We will configure lint-staged and husky to run ESLint during the pre-commit check.

  • Install dev-dependencies:
npm i -D husky lint-staged
  • Add ESLint scripts to package.json file:
  • npm run lint: will lint .ts and .tsx files
  • npm run lint:fix: will lint .ts and .tsx files AND automatically fix any minor ESLint issues.
"scripts": {
    "lint": "eslint --ext .ts,.tsx",
    "lint:fix": "npm run lint -- --fix"
}
  • Add husky and lint-staged configs to packaged.json:
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "app/**/*.(ts|tsx)": [
      "npm run --silent lint:fix",
      "git add"
    ]
  }

During the pre-commit hook check, ESLint will fix any minor linting issues and add those changes directly to the current commit. If ESLint problems persist, lint-staged will prevent the commit from being made and log the ESLint errors and warnings to the console allowing for manual fixes.

Updates:

In v10 and later of lint-staged, we do not need to add git add in our lint-staged task. From lint-staged docs:

From v10.0.0 onwards any new modifications to originally staged files will be automatically added to the commit. If your task previously contained a git add step, please remove this. The automatic behaviour ensures there are less race-conditions, since trying to run multiple git operations at the same time usually results in an error. — Source

So we can remove the git add step:

  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "app/**/*.(ts|tsx)": [
      "npm run --silent lint:fix"
    ]
  }

Extra Resouces:

Happy Coding 🚀