Introduction
ESLint is the go-to linting tool for JavaScript in 2026, capable of detecting over 500 potential errors, enforcing code conventions, and auto-fixing issues with --fix. In a fast-growing ecosystem, ESLint prevents bugs, standardizes style, and speeds up code reviews—like a vigilant guard fixing your code before unit tests even run.
This intermediate tutorial walks you through an optimal setup: from installation to Prettier and VSCode integration. You'll end up with a production-ready config, complete examples for vanilla JS projects (extensible to React or Node.js). Your team will gain productivity, typically cutting merge conflicts by 40%. Ready to turn warnings into flawless code?
Prerequisites
- Node.js 20+ installed
- An existing JavaScript project (or create one with
npm init -y) - Basic knowledge of npm and JSON
- An editor like VSCode (recommended for the ESLint extension)
Installing ESLint and Dependencies
npm init -y
npm install --save-dev eslint eslint-config-prettier prettier @eslint/js globalsThis command initializes a project and installs ESLint with Prettier for auto-formatting, @eslint/js for modern JS configs, and globals for global variables like console. Skip the outdated eslint --init in 2026; go for a flat config instead. Verify with npx eslint --version.
Basic ESLint Configuration
Now, let's create the main config file. ESLint has used flat config since v9—simpler and more performant than the old .eslintrc. It offers greater modularity, like importing shared configs.
Basic ESLint Flat Config File
import js from '@eslint/js';
import globals from 'globals';
export default [
js.configs.recommended,
{
languageOptions: {
globals: globals.browser,
sourceType: 'module',
},
rules: {
'no-unused-vars': 'warn',
'no-console': 'off',
},
},
];This config imports ESLint's recommended rules and extends them with browser globals to avoid false positives on window or document. It disables no-console for development but keeps no-unused-vars as a warning. Test with npx eslint .—fix errors to validate.
Adding Custom Rules and Plugins
For real projects, extend with strict rules for imports and promises. Also add eslint-plugin-import to sort imports alphabetically.
Installing and Configuring the Import Plugin
npm install --save-dev eslint-plugin-importInstalls the plugin to analyze static imports. Required for rules like import/order. Rerun ESLint afterward to apply changes.
Extended ESLint Config with Import Rules
import js from '@eslint/js';
import globals from 'globals';
import importPlugin from 'eslint-plugin-import';
export default [
js.configs.recommended,
...importPlugin.configs.recommended,
{
plugins: { import: importPlugin },
languageOptions: {
globals: globals.browser,
sourceType: 'module',
},
rules: {
'no-unused-vars': 'error',
'no-console': 'warn',
'import/order': [
'error',
{
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
'newlines-between': 'always',
},
],
'import/no-unresolved': 'error',
},
},
];Adds the import plugin with its recommended configs and an import/order rule that separates import groups with newlines. Upgrades no-unused-vars to 'error' to block dirty commits. This enforces a clean, sorted style like a tidy catalog.
Integrating with Prettier
Prettier handles auto-formatting; ESLint does linting. Combining them avoids conflicts: ESLint defers style rules to Prettier.
Prettier Config and npm Scripts
{
"name": "eslint-tutorial",
"version": "1.0.0",
"scripts": {
"lint": "eslint . --ext .js",
"lint:fix": "eslint . --ext .js --fix && prettier --write .",
"format": "prettier --check .",
"format:fix": "prettier --write ."
},
"prettier": {
"semi": true,
"singleQuote": true,
"trailingComma": "es5"
}
}Adds scripts like lint:fix to run ESLint fixes followed by Prettier. Inline Prettier config sets semicolons and quotes. Use npm run lint:fix to clean everything in one go.
Sample File to Lint
console .log('Hello');
function unused() {}
import fs from 'fs';
import { readFile } from 'fs/promises';
async function test() {
const data = await readFile('./file.txt');
console.log(data.toString());
}
test();This code has issues: space before .log, unused function, unsorted imports. Run npm run lint to see ESLint flag them all. Then lint:fix sorts imports, fixes the space, and removes the unused function.
VSCode Integration
Install the ESLint (by Microsoft) and Prettier extensions in VSCode. Add to .vscode/settings.json: { "eslint.format.enable": true, "editor.formatOnSave": true } for auto-fixing on save.
ESLint Ignore File
node_modules/
dist/
*.min.js
build/Ignores build folders and dependencies to speed up linting (up to 10x faster). Essential in CI/CD to avoid scanning millions of irrelevant lines.
Best Practices
- Use flat config: Faster and more modern than
.eslintrc. - Hook into pre-commit: Use Husky + lint-staged for
lint:fixbefore push. - Progressive rules: Start with 'warn', escalate to 'error' post-migration.
- Share configs: Publish
eslint.config.json npm for monorepos. - CI required: Add
npm run lintto GitHub Actions to block dirty PRs.
Common Pitfalls to Avoid
- Prettier/ESLint conflicts: Don't forget
eslint-config-prettier—add it last in config to disable style rules. - Missing globals: Without
globals.nodeorbrowser, false positives onprocessorfetch. - Skip
--fix: 80% of errors auto-fix; always run it. - Incomplete ignores: Linting node_modules slows everything; always use
.eslintignore.
Next Steps
Level up to TypeScript with @typescript-eslint/eslint-plugin or React via eslint-plugin-react-hooks. Check out our advanced ESLint training for monorepos and CI/CD. Official docs: eslint.org. Join our Discord for shared configs.