ESLint Reference
ESLint is a JavaScript package that you can add to your project. It lets you set up rules to self-enforce high-quality and consistent code.
It won't do anything unless you extend someone else's config file or explicitly turn on rules in your config file.
Quick Start and basic knowledge needed
Install with ESLint's setup help
npm init @eslint/config
OR clean install
yarn add --dev eslint
Run it with the ESLint CLI:
npx eslint [options] file.js [file.js] [dir]
OR create a script in your package.json
file (CLI source).
Configuring ESLint (source)
ESLint's config file is .eslintrc.js
. Assume it's blank:
module.exports = {};
Rules (source)
ESLint comes with a bunch of rules that you can manually turn on.
module.exports = {
rules: {
eqeqeq: "error",
quotes: ["warn", "double"],
semi: "2",
},
};
"eqeqeq"
is the rule name, found on ESLint's docs or from a plugin's ruleset. After that is either the rule severity ("error"
) or a list that has the severity followed by options you can set formatted as string/object/... it depends on the specific rule (["warn", "double"]
). You can declare the severity with words or numbers: "0" = "off", "1" = "warn", "2" = "error"
.
You can also use specific rules in certain files with comments
/* eslint eqeqeq: "off", curly: "error" */
Again, you see the format - rule name : rule value
Or you can enable/disable rules in certain files
/* eslint-disable no-console -- For entire file*/
console.log("won't show");
alert("foo"); // eslint-disable-line no-alert -- Specific rule, this line only
// eslint-enable-next-line -- All rules, next line only
console.log("hey");
/* eslint-disable-next-line no-alert */
alert("foo");
Plugins (source)
ESLint lets you define your own rules, or import someone else's rules that they created and published as an NPM package, eg. eslint-plugin-react
which has linting rules for React and JSX. Or, eslint-plugin-react-hooks
which has linting rules for React Hooks.
yarn add --dev eslint-plugin-react
module.exports = {
"plugins" ["react"],
"rules" {
"react/jsx-uses-vars": "error",
}
}
Note, plugins require you to add the rules manually, if you don't want to do this then you should extend their config file.
Sharable Config Files (source)
Manually adding rules and importing plugins gets tedious. Skip the work by extending someone else's config file which already includes plugins and rules declared. Eg. eslint: recommended
which comes with the eslint
package or ones you've installed like eslint-config-airbnb
. Extending a config file also imports their plugins. Below, we extend the Airbnb config file which includes the react and react-hook plugins so we don't need to manually install or declare them anymore, aka we can ~~"plugins": ["react"]
~~!
module.exports = {
"extends": [
"eslint:recommended",
"airbnb",
"airbnb/hooks"
],
(...)
}
Instead of downloading a separate config file, eslint-config-{pkgName}
, some plugins also come with a config file that you can use. Eg. eslint-plugin-react
. Using it is as simple as:
module.exports = {
extends: ["plugin:react/recommended"],
};
The plugin:
syntax tells ESLint to look for the shared config file in the eslint-plugin-react
package that we've installed.
Advanced
These are sometimes not needed if you're extending from a config like eslint-config-next. Still helpful knowledge to have.
Environments (source)
Tell ESLint what environment your code runs in so that it knows the predefined global variables (e.g. the "browser"
environment comes with vars like window
).
module.exports = {
"env": {
"browser": true,
"node": true,
"es6": true
}
(...)
}
Parser Options
Tell ESLint what syntax you're using. ES3-ES5 is ESLint's default but ES6/ES2015 and beyond are modern-day JavaScript. Specifying module
is important if you use import
/export
and jsx
is important if you're using React.
module.exports = {
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
}
(...)
}
Custom rules
It gets fairly involved, here's a good article on it.
My setup for a NextJS Website
Config files I extend:
- eslint:recommended
- eslint-config-next which includes in it:
- Extends
plugin:react/recommended
- Extends
plugin:react-hooks/recommended
- Extends
plugin:@next/next/recommended
- Extends
- eslint-config-prettier OR eslint-plugin-prettier
- Add this last so that prettier can override other configs.
- Run the prettier script (
prettier --write
) before the ESLint script (eslint --fix
) or else you'll get issues when the prettier format conflicts with your ESLint rules.- A package called prettier-eslint will do this for you (running Prettier then ESLint) but it's easy enough to do it yourself.
.eslintrc.json
// .eslintrc.json
{
"extends": [
"eslint:recommended",
"next",
"next/core-web-vitals"
"plugin:prettier/recommended",
],
"rules": {
"prettier/prettier": "error",
"react/react-in-jsx-scope": "off",
"react/prop-types": "off",
"react/no-unescaped-entities": "off",
"no-var": "error", // use let or const instead
"require-await": "warn", // Disallow async functions which have no await expression
"semi-style": ["warn", "last"], // semicolons must be at the end
"semi": ["warn", "always"], // must use semi colons
"quotes": [
"warn",
"double",
{ "allowTemplateLiterals": true, "avoidEscape": true }
], // must use double quotes
"no-unused-vars": "warn" // don't have unused variables
}
}
package.json
//package.json
{
"scripts": {
"lint": "eslint .",
"lint-fix": "eslint . --fix",
"prettier-check": "prettier --check .",
"prettier-write": "prettier --write .",
"clean": "prettier --write . && eslint . --fix"
},
"devDependencies": {
"eslint": "8.28.0",
"eslint-config-next": "13.0.4",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "2.8.1"
}
}