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
- Install dev dependencies:
- eslint-loader : eslint webpack loader
- @typescript-eslint/parser : The parser that will allow ESLint to lint TypeScript code
- @typescript-eslint/eslint-plugin : A plugin that contains ESLint rules that are TypeScript specific
- eslint-plugin-react : React specific linting rules for ESLint
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
filesnpm 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
andlint-staged
configs topackaged.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"
]
}