Lint JavaScript code
JavaScript code is linted with ESLint to detect errors and enforce coding standards.
- Set up ESLint with `pnpm dlx eslint --init`
- Use shared configs (eslint:recommended, @typescript-eslint)
- Integrate with your editor for real-time feedback
- Add lint checks to CI/CD pipeline
Rule Details
JavaScript linting tools such as ESLint (opens in new tab), Biome (opens in new tab), and typescript-eslint (opens in new tab) catch syntax errors, enforce coding standards, and keep code quality consistent across development teams.
Code Examples
Installation and Basic Setup
# Install ESLint
pnpm add -D eslint
# Initialize ESLint configuration
pnpm dlx eslint --init
# Install popular configurations
pnpm add -D @eslint/js
pnpm add -D eslint-config-airbnb-base
pnpm add -D eslint-config-standard
# For React projects
pnpm add -D eslint-plugin-react eslint-plugin-react-hooks
pnpm add -D eslint-config-react-app
# For TypeScript
pnpm add -D @typescript-eslint/parser @typescript-eslint/eslint-plugin
# For Vue.js
pnpm add -D eslint-plugin-vue
# Additional useful plugins
pnpm add -D eslint-plugin-import
pnpm add -D eslint-plugin-node
pnpm add -D eslint-plugin-promise
pnpm add -D eslint-plugin-securityBasic Configuration
// .eslintrc.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
jest: true
},
extends: [
'eslint:recommended',
'airbnb-base'
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module'
},
rules: {
// Error prevention
'no-console': 'warn',
'no-debugger': 'error',
'no-alert': 'error',
'no-unused-vars': 'error',
'no-undef': 'error',
'no-unreachable': 'error',
// Code style
'indent': ['error', 2],
'quotes': ['error', 'single'],
'semi': ['error', 'never'],
'comma-dangle': ['error', 'never'],
'object-curly-spacing': ['error', 'always'],
'array-bracket-spacing': ['error', 'never'],
// Best practices
'eqeqeq': ['error', 'always'],
'curly': ['error', 'all'],
'dot-notation': 'error',
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
'no-script-url': 'error',
// ES6+
'prefer-const': 'error',
'prefer-arrow-callback': 'error',
'arrow-spacing': 'error',
'no-var': 'error',
'object-shorthand': 'error',
'prefer-template': 'error',
// Import rules
'import/order': ['error', {
'groups': [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index'
],
'newlines-between': 'always'
}],
'import/no-unresolved': 'error',
'import/no-unused-modules': 'warn'
},
ignorePatterns: [
'node_modules/',
'dist/',
'build/',
'*.min.js',
'coverage/'
]
}Why It Matters
Linting catches bugs before runtime, enforces team coding standards, and prevents common mistakes that slip through code review.
Framework-Specific Configurations
React ESLint Configuration
// .eslintrc.js for React
module.exports = {
env: {
browser: true,
es2021: true,
jest: true
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended'
],
plugins: [
'react',
'react-hooks',
'jsx-a11y'
],
parserOptions: {
ecmaFeatures: {
jsx: true
},
ecmaVersion: 'latest',
sourceType: 'module'
},
settings: {
react: {
version: 'detect'
}
},
rules: {
// React specific rules
'react/react-in-jsx-scope': 'off', // Not needed in React 17+
'react/prop-types': 'error',
'react/jsx-uses-react': 'error',
'react/jsx-uses-vars': 'error',
'react/jsx-no-duplicate-props': 'error',
'react/jsx-no-undef': 'error',
'react/jsx-pascal-case': 'error',
'react/no-deprecated': 'error',
'react/no-direct-mutation-state': 'error',
'react/no-typos': 'error',
'react/require-render-return': 'error',
'react/style-prop-object': 'error',
// React Hooks rules
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// JSX accessibility rules
'jsx-a11y/alt-text': 'error',
'jsx-a11y/anchor-has-content': 'error',
'jsx-a11y/aria-props': 'error',
'jsx-a11y/aria-proptypes': 'error',
'jsx-a11y/aria-unsupported-elements': 'error',
'jsx-a11y/click-events-have-key-events': 'warn',
'jsx-a11y/heading-has-content': 'error',
'jsx-a11y/img-redundant-alt': 'error',
'jsx-a11y/label-has-associated-control': 'error',
'jsx-a11y/no-access-key': 'error'
}
}TypeScript Configuration
// .eslintrc.js for TypeScript
module.exports = {
parser: '@typescript-eslint/parser',
plugins: [
'@typescript-eslint'
],
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'@typescript-eslint/recommended-requiring-type-checking'
],
parserOptions: {
ecmaVersion: 2021,
sourceType: 'module',
tsconfigRootDir: __dirname,
project: ['./tsconfig.json']
},
rules: {
// TypeScript specific rules
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'warn',
'@typescript-eslint/explicit-module-boundary-types': 'warn',
'@typescript-eslint/prefer-nullish-coalescing': 'error',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/strict-boolean-expressions': 'error',
'@typescript-eslint/prefer-readonly': 'error',
'@typescript-eslint/prefer-readonly-parameter-types': 'warn',
// Disable base ESLint rules that are covered by TypeScript
'no-unused-vars': 'off',
'no-undef': 'off', // TypeScript handles this
'no-dupe-args': 'off',
'no-dupe-keys': 'off',
'no-unreachable': 'off',
'valid-typeof': 'off',
// Override recommended rules for better TypeScript experience
'@typescript-eslint/no-non-null-assertion': 'warn',
'@typescript-eslint/ban-ts-comment': ['error', {
'ts-expect-error': 'allow-with-description',
'ts-ignore': true,
'ts-nocheck': true,
'ts-check': false
}]
},
overrides: [
{
files: ['*.test.ts', '*.test.tsx', '*.spec.ts', '*.spec.tsx'],
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-non-null-assertion': 'off'
}
}
]
}Vue.js ESLint Configuration
// .eslintrc.js for Vue.js
module.exports = {
env: {
browser: true,
es2021: true,
node: true
},
extends: [
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:vue/vue3-strongly-recommended',
'plugin:vue/vue3-recommended'
],
plugins: [
'vue'
],
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
parser: '@babel/eslint-parser',
requireConfigFile: false
},
rules: {
// Vue specific rules
'vue/html-indent': ['error', 2],
'vue/html-quotes': ['error', 'double'],
'vue/html-self-closing': ['error', {
'html': {
'void': 'always',
'normal': 'never',
'component': 'always'
},
'svg': 'always',
'math': 'always'
}],
'vue/max-attributes-per-line': ['error', {
'singleline': 3,
'multiline': 1
}],
'vue/multiline-html-element-content-newline': 'error',
'vue/no-multi-spaces': 'error',
'vue/no-spaces-around-equal-signs-in-attribute': 'error',
'vue/require-default-prop': 'error',
'vue/require-prop-types': 'error',
'vue/v-bind-style': ['error', 'shorthand'],
'vue/v-on-style': ['error', 'shorthand'],
'vue/component-name-in-template-casing': ['error', 'PascalCase'],
'vue/prop-name-casing': ['error', 'camelCase']
}
}Advanced Linting Configurations
Security-Focused ESLint Setup
// Security-focused configuration
module.exports = {
plugins: [
'security',
'no-secrets'
],
extends: [
'eslint:recommended',
'plugin:security/recommended'
],
rules: {
// Security rules
'security/detect-buffer-noassert': 'error',
'security/detect-child-process': 'error',
'security/detect-disable-mustache-escape': 'error',
'security/detect-eval-with-expression': 'error',
'security/detect-new-buffer': 'error',
'security/detect-no-csrf-before-method-override': 'error',
'security/detect-non-literal-fs-filename': 'warn',
'security/detect-non-literal-regexp': 'error',
'security/detect-non-literal-require': 'warn',
'security/detect-object-injection': 'error',
'security/detect-possible-timing-attacks': 'error',
'security/detect-pseudoRandomBytes': 'error',
'security/detect-unsafe-regex': 'error',
// Prevent secrets in code
'no-secrets/no-secrets': 'error',
// Dangerous patterns
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
'no-script-url': 'error',
'no-proto': 'error',
'no-with': 'error'
}
}Performance-Focused Rules
module.exports = {
rules: {
// Performance rules
'no-loop-func': 'error',
'prefer-const': 'error',
'no-var': 'error',
// Memory leaks prevention
'no-global-assign': 'error',
'no-implicit-globals': 'error',
'no-unused-vars': ['error', {
'argsIgnorePattern': '^_',
'varsIgnorePattern': '^_'
}],
// Efficient patterns
'prefer-template': 'error',
'prefer-spread': 'error',
'prefer-rest-params': 'error',
'no-useless-concat': 'error',
'no-useless-call': 'error',
// Array/Object efficiency
'prefer-destructuring': ['error', {
'array': true,
'object': true
}, {
'enforceForRenamedProperties': false
}]
}
}Custom ESLint Rules
Creating Custom Rules
// rules/no-console-log.js
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Disallow console.log statements',
category: 'Best Practices',
recommended: false
},
fixable: 'code',
schema: []
},
create(context) {
return {
MemberExpression(node) {
if (node.object.name === 'console' && node.property.name === 'log') {
context.report({
node,
message: 'console.log statements are not allowed',
fix(fixer) {
return fixer.remove(node.parent)
}
})
}
}
}
}
}
// Custom rule for enforcing component naming
// rules/component-naming.js
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Enforce PascalCase for React component names'
}
},
create(context) {
function isPascalCase(name) {
return /^[A-Z][a-zA-Z0-9]*$/.test(name)
}
return {
FunctionDeclaration(node) {
if (node.id && node.id.name) {
const { name } = node.id
// Check if function returns JSX (simplified check)
const hasJSXReturn = context.getSourceCode().getText(node).includes('return')
if (hasJSXReturn && !isPascalCase(name)) {
context.report({
node: node.id,
message: `Component '${name}' should use PascalCase naming`
})
}
}
}
}
}
}
// Using custom rules in configuration
module.exports = {
plugins: [
'local' // For local custom rules
],
rules: {
'local/no-console-log': 'error',
'local/component-naming': 'error'
}
}Build Tool Integration
Webpack ESLint Integration
// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
plugins: [
new ESLintPlugin({
extensions: ['js', 'jsx', 'ts', 'tsx'],
fix: true, // Auto-fix issues
failOnError: false,
failOnWarning: false,
emitError: true,
emitWarning: true,
quiet: false,
outputReport: {
filePath: 'reports/eslint-report.html',
formatter: 'html'
}
})
]
}Vite ESLint Integration
// vite.config.js
import { defineConfig } from 'vite'
import eslint from 'vite-plugin-eslint'
export default defineConfig({
plugins: [
eslint({
include: ['src/**/*.js', 'src/**/*.jsx', 'src/**/*.ts', 'src/**/*.tsx'],
exclude: ['node_modules', 'dist'],
fix: true
})
]
})Next.js ESLint Integration
// next.config.js
module.exports = {
eslint: {
// Run ESLint during build
dirs: ['pages', 'utils', 'components', 'lib'],
// Ignore ESLint during production builds (not recommended)
ignoreDuringBuilds: false
},
// Custom webpack config for ESLint
webpack: (config, { dev, isServer }) => {
if (dev && !isServer) {
config.module.rules.push({
test: /\.(js|jsx|ts|tsx)$/,
exclude: /node_modules/,
use: [
{
loader: 'eslint-loader',
options: {
cache: true,
fix: true
}
}
]
})
}
return config
}
}IDE Integration
VS Code ESLint Setup
// .vscode/settings.json
{
"eslint.enable": true,
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.format.enable": true,
"eslint.lintTask.enable": true,
"eslint.run": "onSave",
"eslint.autoFixOnSave": true,
"eslint.codeActionsOnSave.mode": "all",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascriptreact]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescriptreact]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
}
}
// .vscode/extensions.json
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-vscode.vscode-typescript-next"
]
}Automated Testing and CI Integration
Pre-commit Hooks
# Install husky and lint-staged
npm install --save-dev husky lint-staged
# Setup husky
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"
# Setup pre-push hook
npx husky add .husky/pre-push "npm run lint"// package.json
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix",
"prettier --write",
"git add"
]
},
"scripts": {
"lint": "eslint src --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint src --ext .js,.jsx,.ts,.tsx --fix",
"lint:report": "eslint src --ext .js,.jsx,.ts,.tsx --format html --output-file reports/eslint-report.html"
}
}GitHub Actions ESLint Workflow
# .github/workflows/eslint.yml
name: ESLint Check
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
eslint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: |
npm run lint
npm run lint:report
continue-on-error: true
- name: Annotate code with ESLint results
uses: ataylorme/eslint-annotate-action@v2
if: failure()
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
report-json: "reports/eslint-report.json"
- name: Upload ESLint report
uses: actions/upload-artifact@v3
if: always()
with:
name: eslint-report
path: reports/
retention-days: 30
- name: Comment PR with lint results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs')
if (fs.existsSync('reports/eslint-report.json')) {
const report = JSON.parse(fs.readFileSync('reports/eslint-report.json', 'utf8'))
let comment = '## ESLint Results\n\n'
let totalErrors = 0
let totalWarnings = 0
report.forEach(file => {
totalErrors += file.errorCount
totalWarnings += file.warningCount
if (file.errorCount > 0 || file.warningCount > 0) {
comment += `**${file.filePath.replace(process.cwd(), '')}:**\n`
comment += `- Errors: ${file.errorCount}\n`
comment += `- Warnings: ${file.warningCount}\n\n`
}
})
comment += `### Summary\n`
comment += `- Total Errors: ${totalErrors}\n`
comment += `- Total Warnings: ${totalWarnings}\n`
if (totalErrors === 0) {
comment += '\n✅ No ESLint errors found!'
} else {
comment += '\n❌ Please fix ESLint errors before merging.'
}
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})
}Advanced Linting Techniques
Code Quality Metrics
// eslint-complexity-rules.js
module.exports = {
rules: {
// Complexity rules
'complexity': ['error', { max: 10 }],
'max-depth': ['error', 4],
'max-lines': ['error', { max: 300, skipComments: true }],
'max-lines-per-function': ['error', { max: 50, skipComments: true }],
'max-nested-callbacks': ['error', 3],
'max-params': ['error', 5],
'max-statements': ['error', 20],
'max-statements-per-line': ['error', { max: 1 }],
// File organization
'max-classes-per-file': ['error', 1],
'one-var': ['error', 'never'],
'prefer-object-spread': 'error',
// Code duplication
'no-duplicate-imports': 'error',
'no-useless-return': 'error',
'no-useless-constructor': 'error',
'no-useless-rename': 'error'
}
}Team Collaboration Rules
module.exports = {
rules: {
// Documentation
'valid-jsdoc': ['error', {
requireReturn: false,
requireParamDescription: false,
requireReturnDescription: false
}],
'require-jsdoc': ['warn', {
require: {
FunctionDeclaration: true,
MethodDefinition: true,
ClassDeclaration: true
}
}],
// Naming conventions
'camelcase': ['error', { properties: 'never' }],
'new-cap': ['error', { newIsCap: true }],
'no-underscore-dangle': ['error', { allowAfterThis: true }],
// Code organization
'sort-imports': ['error', {
ignoreCase: false,
ignoreDeclarationSort: false,
ignoreMemberSort: false,
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single']
}],
// Error handling
'handle-callback-err': 'error',
'no-throw-literal': 'error',
'prefer-promise-reject-errors': 'error'
}
}Performance Monitoring and Reporting
ESLint Performance Analysis
// scripts/eslint-performance.js
const { ESLint } = require('eslint')
const fs = require('fs')
class ESLintPerformanceAnalyzer {
constructor(options = {}) {
this.eslint = new ESLint({
baseConfig: options.config || {},
useEslintrc: options.useEslintrc !== false,
fix: options.fix || false
})
}
async analyzeProject(patterns) {
const startTime = Date.now()
try {
const results = await this.eslint.lintFiles(patterns)
const duration = Date.now() - startTime
const analysis = {
duration,
totalFiles: results.length,
totalErrors: results.reduce((sum, result) => sum + result.errorCount, 0),
totalWarnings: results.reduce((sum, result) => sum + result.warningCount, 0),
fileAnalysis: results.map(result => ({
filePath: result.filePath,
errorCount: result.errorCount,
warningCount: result.warningCount,
messages: result.messages.map(msg => ({
ruleId: msg.ruleId,
severity: msg.severity,
message: msg.message,
line: msg.line,
column: msg.column
}))
})),
ruleBreakdown: this.analyzeRuleBreakdown(results),
performanceMetrics: {
averageTimePerFile: duration / results.length,
filesWithErrors: results.filter(r => r.errorCount > 0).length,
filesWithWarnings: results.filter(r => r.warningCount > 0).length
}
}
return analysis
} catch (error) {
throw new Error(`ESLint analysis failed: ${error.message}`)
}
}
analyzeRuleBreakdown(results) {
const ruleStats = new Map()
results.forEach(result => {
result.messages.forEach(message => {
const ruleId = message.ruleId || 'unknown'
const existing = ruleStats.get(ruleId) || { count: 0, errors: 0, warnings: 0 }
existing.count++
if (message.severity === 2) existing.errors++
if (message.severity === 1) existing.warnings++
ruleStats.set(ruleId, existing)
})
})
return Array.from(ruleStats.entries())
.map(([ruleId, stats]) => ({ ruleId, ...stats }))
.sort((a, b) => b.count - a.count)
}
generateReport(analysis, outputPath) {
const report = {
summary: {
totalFiles: analysis.totalFiles,
totalErrors: analysis.totalErrors,
totalWarnings: analysis.totalWarnings,
duration: `${analysis.duration}ms`,
averageTimePerFile: `${analysis.performanceMetrics.averageTimePerFile.toFixed(2)}ms`
},
topRules: analysis.ruleBreakdown.slice(0, 10),
filesWithMostIssues: analysis.fileAnalysis
.sort((a, b) => (b.errorCount + b.warningCount) - (a.errorCount + a.warningCount))
.slice(0, 10)
.map(file => ({
file: file.filePath.replace(process.cwd(), ''),
issues: file.errorCount + file.warningCount,
errors: file.errorCount,
warnings: file.warningCount
})),
timestamp: new Date().toISOString()
}
if (outputPath) {
fs.writeFileSync(outputPath, JSON.stringify(report, null, 2))
console.log(`Report saved to ${outputPath}`)
}
return report
}
printSummary(analysis) {
console.log('\n=== ESLint Analysis Summary ===')
console.log(`Files analyzed: ${analysis.totalFiles}`)
console.log(`Total errors: ${analysis.totalErrors}`)
console.log(`Total warnings: ${analysis.totalWarnings}`)
console.log(`Analysis time: ${analysis.duration}ms`)
console.log(`Average time per file: ${analysis.performanceMetrics.averageTimePerFile.toFixed(2)}ms`)
if (analysis.ruleBreakdown.length > 0) {
console.log('\n=== Top Rule Violations ===')
analysis.ruleBreakdown.slice(0, 5).forEach((rule, index) => {
console.log(`${index + 1}. ${rule.ruleId}: ${rule.count} issues`)
})
}
}
}
// Usage
async function main() {
const analyzer = new ESLintPerformanceAnalyzer({
fix: false,
config: {
extends: ['eslint:recommended']
}
})
const analysis = await analyzer.analyzeProject(['src/**/*.js', 'src/**/*.jsx'])
analyzer.printSummary(analysis)
analyzer.generateReport(analysis, 'reports/eslint-analysis.json')
}
if (require.main === module) {
main().catch(console.error)
}
module.exports = ESLintPerformanceAnalyzerBest Practices
Start from the official ESLint getting started guide (opens in new tab) or the typescript-eslint starter setup (opens in new tab) instead of inventing a rule stack from scratch on day one.
- Start with Recommended: Begin with
eslint:recommendedand gradually add rules - Team Consistency: Establish rules that your entire team can follow
- Gradual Adoption: Introduce stricter rules incrementally
- IDE Integration: Ensure real-time linting feedback in development
- Automated Fixing: Use
--fixflag to automatically resolve fixable issues - Regular Updates: Keep ESLint and plugins updated
- Custom Rules: Create custom rules for team-specific patterns
- Performance Monitoring: Track linting performance in large codebases
- Documentation: Document custom rules and team conventions
- CI Integration: Include linting in continuous integration pipelines
Common ESLint Errors and Solutions
Typical Configuration Issues
// Common fixes for ESLint issues
// 1. Parsing errors with modern JavaScript
{
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
}
}
// 2. React not defined errors
{
"rules": {
"react/react-in-jsx-scope": "off" // React 17+
}
}
// 3. TypeScript parsing issues
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
}
}
// 4. Import resolution errors
{
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".jsx", ".ts", ".tsx"]
}
}
}
}Remember that ESLint configuration should match your team's coding standards and project requirements. Regular review and adjustment of rules ensures the linting setup continues to serve your development goals effectively.
Exceptions
- Some patterns are acceptable in generated, transpiled, or framework-managed output even when they are poor choices for hand-written application code.
- Do not flag a low-level implementation detail as the primary problem when a stronger architectural or runtime issue is causing the real failure.
- If the codebase already has a stricter lint or type-system rule that catches the same bug earlier, document that stronger source of truth.
Verification
Automated Checks
- Run the linter in CI and locally, then verify the changed code path still behaves correctly in the browser if the autofix touched runtime code.
Manual Checks
- Confirm the code still behaves correctly when the feature is delayed, lazy-loaded, or fails.
Use with AI
Copy these prompts to use with your AI assistant, or install the MCP server to use directly from Claude, Cursor, or Windsurf.
Check
Verify implementation
Set up JavaScript linting tools like ESLint to automatically detect syntax errors, enforce coding standards, and maintain consistent code quality across the team.
Fix
Auto-fix issues
Configure ESLint with appropriate rules and plugins, integrate it into your development workflow, and fix all linting errors and warnings.
Explain
Learn more
Explain how JavaScript linting prevents bugs, enforces consistent coding standards, improves code readability, and catches potential issues before runtime.
Review
Code review
Review scripts, client components, and browser execution paths related to Lint JavaScript code. Flag exact imports, event handlers, runtime side effects, or blocking operations that violate the rule, and state how the change should be verified in the browser.