How to Configure Vite ESLint for React Projects: Complete Setup Guide
To configure Vite ESLint for React, use the flat config preset provided in the official React template at packages/create-vite/template-react/eslint.config.js, which includes React Hooks and Fast Refresh rules, then add a "lint": "eslint ." script to your package.json to run checks manually.
The vitejs/vite repository provides a first-class ESLint configuration designed specifically for React projects. Because Vite's dev server does not run linting automatically during development, understanding how to properly configure and invoke ESLint ensures you catch code quality issues before they reach production.
Default ESLint Configuration in Vite React Templates
When you bootstrap a React project using npm create vite@latest, the template includes a minimal eslint.config.js file located at packages/create-vite/template-react/eslint.config.js. This file uses the modern flat config format (defineConfig from eslint/config) and pre-configures:
- Core ESLint rules via
js.configs.recommendedfrom@eslint/js - React Hooks validation via
eslint-plugin-react-hooks - Fast Refresh compatibility via
eslint-plugin-react-refresh - Browser globals via
globals.browser - JSX parsing with ECMAScript 2020 support
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{js,jsx}'],
extends: [
js.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
rules: {
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
},
},
])
Step-by-Step Setup Guide
Creating the Project
Generate a new Vite React project using the official template. This ensures you inherit the base eslint.config.js and peer dependencies:
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm install
Installing Dependencies
The template's package.json already lists the required dev dependencies: eslint, @eslint/js, eslint-plugin-react-hooks, eslint-plugin-react-refresh, globals, and typescript-eslint (for TypeScript variants). Running npm install guarantees the exact versions vetted by the Vite team.
Adding the Lint Script
Vite does not automatically lint during development. Add a manual script to package.json to run checks on demand or in CI:
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"lint": "eslint ."
}
}
Execute npm run lint to validate the entire codebase against the configured rules.
Extending the Base Configuration
Adding React-Specific Plugins
For stricter React validation, install additional community plugins like eslint-plugin-react-x and eslint-plugin-react-dom:
npm install --save-dev eslint-plugin-react-x eslint-plugin-react-dom
Extend the base configuration by importing these plugins and adding them to the extends array:
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
import { defineConfig, globalIgnores } from 'eslint/config'
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{js,jsx}'],
extends: [
js.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
reactX.configs.recommended,
reactDom.configs.recommended,
],
plugins: { 'react-x': reactX, 'react-dom': reactDom },
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
rules: {
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
'react-x/no-unknown-property': 'error',
},
},
])
Enabling Type-Aware Linting
For TypeScript projects, leverage @typescript-eslint rules that require type information. The Vite repository's global configuration at packages/vite/eslint.config.js demonstrates a pattern for conditionally enabling type checking based on the VSCODE_PID environment variable.
To implement this in your project, reference your tsconfig.json in the parser options:
import tseslint from 'typescript-eslint'
export default defineConfig([
{
files: ['**/*.{ts,tsx}'],
languageOptions: {
parser: tseslint.parser,
parserOptions: {
project: ['./tsconfig.json'],
},
},
},
])
Set VSCODE_PID=1 npm run lint to activate type-aware rules during local development, or run the lint task directly from VS Code to trigger the enhanced checking.
Key Configuration Files Reference
| File | Role | Location |
|---|---|---|
eslint.config.js |
Default flat config for React templates including hooks and refresh plugins | packages/create-vite/template-react/eslint.config.js |
eslint.config.js |
Repository-wide baseline with Node rules, import ordering, and conditional type-checking | packages/vite/eslint.config.js |
package.json |
Defines ESLint dependencies and the "lint": "eslint ." script |
packages/create-vite/template-react/package.json |
vite.config.js |
Minimal Vite configuration loading @vitejs/plugin-react |
packages/create-vite/template-react/vite.config.js |
Summary
- Vite provides a ready-made ESLint setup via the React template at
packages/create-vite/template-react/eslint.config.js, using the modern flat config format with React Hooks and Fast Refresh rules pre-configured. - Manual execution is required because Vite's dev server does not lint automatically; add
"lint": "eslint ."topackage.jsonand runnpm run lint. - Extension is straightforward using the flat config API—import additional plugins like
eslint-plugin-react-x, add them to theextendsarray, and customize rules while preserving the base configuration. - Type-aware linting can be enabled for TypeScript projects by referencing
tsconfig.jsoninparserOptions.project, with conditional activation via environment variables as demonstrated in the repository's global config.
Frequently Asked Questions
Does Vite automatically lint code during development?
No, Vite's development server does not run ESLint automatically. You must manually invoke linting by adding a script such as "lint": "eslint ." to your package.json and running npm run lint, or by configuring your IDE to run ESLint on file save.
How do I add custom ESLint rules to a Vite React project?
Edit the eslint.config.js file in your project root. Import additional plugins (such as eslint-plugin-react-x), add them to the plugins object, include their recommended configs in the extends array, and define custom rules in the rules section. The flat config format allows you to extend the base Vite template configuration while adding project-specific requirements.
Can I use TypeScript-aware ESLint rules with Vite's default configuration?
Yes. Install typescript-eslint and configure the parserOptions.project field in your eslint.config.js to point to your tsconfig.json. The Vite repository demonstrates a pattern where type-aware linting is conditionally enabled based on the VSCODE_PID environment variable, allowing you to run heavy type-checking rules during local development while keeping CI linting fast.
Where does Vite store the default ESLint configuration for React templates?
The default configuration is located at packages/create-vite/template-react/eslint.config.js in the vitejs/vite repository. This file uses the ESLint flat config format and includes pre-configured rules for React Hooks (eslint-plugin-react-hooks) and React Fast Refresh (eslint-plugin-react-refresh), along with browser globals and recommended ESLint rules.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →