惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
C
Cisco Blogs
Help Net Security
Help Net Security
I
Intezer
Simon Willison's Weblog
Simon Willison's Weblog
Know Your Adversary
Know Your Adversary
Hacker News: Ask HN
Hacker News: Ask HN
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
WordPress大学
WordPress大学
小众软件
小众软件
Jina AI
Jina AI
量子位
T
Threatpost
Forbes - Security
Forbes - Security
L
LINUX DO - 最新话题
S
Securelist
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
C
Cyber Attacks, Cyber Crime and Cyber Security
有赞技术团队
有赞技术团队
博客园_首页
T
Threat Research - Cisco Blogs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
The Exploit Database - CXSecurity.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Scott Helme
Scott Helme
博客园 - 【当耐特】
IT之家
IT之家
Hugging Face - Blog
Hugging Face - Blog
月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
大猫的无限游戏
大猫的无限游戏
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Last Watchdog
The Last Watchdog
Attack and Defense Labs
Attack and Defense Labs
Google DeepMind News
Google DeepMind News
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
博客园 - 叶小钗
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
罗磊的独立博客
The Cloudflare Blog
S
Schneier on Security
爱范儿
爱范儿
N
News and Events Feed by Topic
NISL@THU
NISL@THU
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

WMI

How to Activate MySQL for Multiple Devices - WMI Yarn NPM Registry Configuration - WMI Yarn Guides - WMI Set Up ADB Wireless Debugging on Android: A Full Guide - WMI How to Fill Tax Information on Google Adsense - WMI Migrate ESLint v9 for prettier typescript javascript - WMI PySide6 button click open new window - WMI PySide6 autocomplete input text - WMI Mobile Legends To The Stars Event Clue - WMI [PHP] generate random proxy IP:PORT from CIDR - WMI [PHP] generate big text file for testing purpose - WMI List of Chrome Driver command line arguments - WMI Happy eid mubarak - WMI Install markdown engine on vite ESM typescript - WMI Android Activity lifecycle - WMI OkHttp cookie handling on android (webview supported) - WMI Turn git log history into markdown - WMI enable automatic memory heap resizing of android studio - WMI is defining screen density can reduce build time ? - WMI
ESLint Flat Config for JS, TS, React, and Prettier - WMI
Dimas Lanjaka · 2025-08-20 · via WMI

Why Use ESLint Flat Config?

The new ESLint Flat Config format (eslint.config.js) offers a more flexible, modern, and JavaScript-native way to configure your linter. It allows you to:

  • Use full JavaScript for dynamic configuration.
  • Share and compose configs easily.
  • Integrate with modern tools like Babel, TypeScript, and Prettier.
  • Avoid legacy config pitfalls and limitations.

This article provides a complete, production-ready Flat Config setup for projects using JavaScript, TypeScript, React, and Prettier, with support for Babel and JSONC (JSON with comments) for Prettier configuration.


Requirements

yarn add -D eslint @eslint/js eslint-config-prettier eslint-plugin-prettier @babel/core @babel/eslint-parser @babel/preset-react @babel/plugin-syntax-import-assertions typescript typescript-eslint eslint-plugin-react eslint-plugin-react-hooks globals jsonc-parser

Write Prettier Config

Save below config to .prettierrc.json

{
  // Prettier config
  "semi": true,
  "singleQuote": true,
  "printWidth": 100,
  "tabWidth": 2,
  "trailingComma": "es5"
}

Write ESLint Configuration

// ESLint Flat Config for JS, TS, React, and Prettier
// ---------------------------------------------------
// This configuration uses Flat Config (`eslint.config.js`)
// and integrates:
//   - Base JS rules (@eslint/js)
//   - Babel parser for modern JS & JSX
//   - TypeScript parser for TS/TSX
//   - React + React Hooks plugins
//   - Prettier as an ESLint plugin
//   - jsonc-parser for Prettier config (supports comments)
// Requirements:
//   yarn add -D \
// eslint @eslint/js eslint-config-prettier eslint-plugin-prettier \
// @babel/core @babel/eslint-parser @babel/preset-react @babel/plugin-syntax-import-assertions \
// typescript typescript-eslint \
// eslint-plugin-react eslint-plugin-react-hooks \
// globals jsonc-parser
// ---------------------------------------------------

import babelParser from '@babel/eslint-parser';
import eslint from '@eslint/js';
import prettierConfig from 'eslint-config-prettier';
import prettier from 'eslint-plugin-prettier';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import globals from 'globals';
import { parse as parseJSONC } from 'jsonc-parser';
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import tseslint from 'typescript-eslint';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const prettierrc = parseJSONC(fs.readFileSync(path.resolve(__dirname, '.prettierrc.json'), 'utf-8'));

export default tseslint.config(
  // ---------------------------------------------------
  // 🌍 Global config (applies to all files)
  // ---------------------------------------------------
  eslint.configs.recommended,
  tseslint.configs.recommended,
  {
    ignores: [
      '**/*.md', // Ignore Markdown files
      '**/*.html', // Ignore raw HTML files
      '**/*.py', // Ignore Python scripts
      '**/*.txt', // Ignore plain text
      '**/tmp/**', // Ignore temp files
      '**/app/**', // Ignore custom app output
      '**/dist/**', // Ignore build output
      '**/node_modules/**', // Ignore dependencies
      '**/coverage/**', // Ignore test coverage
      '**/logs/**', // Ignore logs
      '**/vendor/**', // Ignore vendor code
      '**/min.*', // Ignore minified assets
      '**/*.lock', // Ignore lockfiles
      '**/public/**', // Ignore public assets
      '**/.yarn/**' // Ignore Yarn cache
    ],

    // Global language options
    languageOptions: {
      globals: {
        // Browser globals (window, document, etc.)
        ...globals.browser,
        // Node.js globals (process, __dirname, etc.)
        ...globals.node,
        // Jest testing globals
        ...globals.jest,
        // Google reCAPTCHA
        grecaptcha: 'readonly',
        // jQuery $
        $: 'readonly',
        // jQuery object
        jQuery: 'readonly',
        // Google Ads
        adsbygoogle: 'writable',
        // Hexo static site generator
        hexo: 'readonly'
      },
      // Support latest ECMAScript syntax
      ecmaVersion: 'latest',
      // Enable ES modules
      sourceType: 'module'
    },

    plugins: { prettier },

    rules: {
      // ✅ Run Prettier as an ESLint rule (using config with comments)
      'prettier/prettier': ['error', prettierrc],

      // ✅ Disable stylistic rules that conflict with Prettier
      ...prettierConfig.rules,

      // Example JS style relaxations
      'arrow-body-style': 'off', // Allow any arrow fn body style
      'prefer-arrow-callback': 'off', // Allow normal function callbacks
      // ⚙️ Allow unused variables starting with "_"
      'no-unused-vars': [
        'error',
        {
          argsIgnorePattern: '^_',
          varsIgnorePattern: '^_',
          caughtErrorsIgnorePattern: '^_'
        }
      ]
    }
  },

  // ---------------------------------------------------
  // 📜 ESM (JS, MJS, JSX)
  // ---------------------------------------------------
  {
    files: ['**/*.{js,mjs,jsx}'],
    languageOptions: {
      // Use Babel parser for modern JS/JSX
      parser: babelParser,
      parserOptions: {
        // Allow parsing without .babelrc
        requireConfigFile: false,
        babelOptions: {
          // Handle JSX in JS files
          presets: ['@babel/preset-react'],
          // Support `import ... with { type: "json" }`
          plugins: ['@babel/plugin-syntax-import-assertions']
        },
        ecmaFeatures: {
          // Enable JSX parsing
          jsx: true
        }
      },
      globals: {
        ...globals.browser,
        ...globals.node
      }
    },
    rules: {
      // Only use base no-unused-vars for JS, allow unused vars starting with _
      '@typescript-eslint/no-unused-vars': 'off',
      // Place custom no-unused-vars last to ensure it takes precedence
      'no-unused-vars': [
        'error',
        {
          argsIgnorePattern: '^_',
          varsIgnorePattern: '^_',
          caughtErrorsIgnorePattern: '^_'
        }
      ]
    }
  },

  // ---------------------------------------------------
  // 📦 CommonJS (CJS)
  // ---------------------------------------------------
  {
    files: ['**/*.cjs'],
    languageOptions: {
      sourceType: 'commonjs',
      parser: babelParser,
      parserOptions: {
        // Allow parsing without .babelrc
        requireConfigFile: false,
        babelOptions: {
          // Handle JSX in JS files
          presets: ['@babel/preset-env']
        }
      },
      globals: {
        ...globals.node
      }
    },
    rules: {
      // Allow require statements in CJS files
      '@typescript-eslint/no-var-requires': 'off',
      '@typescript-eslint/no-require-imports': 'off',
      '@typescript-eslint/no-unused-vars': 'off',
      'no-var-requires': 'off', // Allow require() in CJS
      'no-unused-vars': [
        'error',
        {
          argsIgnorePattern: '^_',
          varsIgnorePattern: '^_',
          caughtErrorsIgnorePattern: '^_'
        }
      ]
    }
  },

  // ---------------------------------------------------
  // 🟦 TypeScript (TS, TSX, MTS, CTS)
  // ---------------------------------------------------
  {
    files: ['**/*.{ts,tsx,mts,cts}'],
    languageOptions: {
      // TypeScript-aware parser
      parser: tseslint.parser,
      parserOptions: {
        // Point to project tsconfig
        project: './tsconfig.json'
      },
      globals: {
        ...globals.browser,
        ...globals.node
      }
    },
    rules: {
      // Replace base "no-unused-vars" with TS version
      'no-unused-vars': 'off',
      '@typescript-eslint/explicit-function-return-type': 'off', // No need to force return types
      '@typescript-eslint/no-explicit-any': 'off', // Allow `any`
      '@typescript-eslint/no-this-alias': [
        'error',
        {
          allowDestructuring: false,
          allowedNames: ['self', 'hexo'] // Allow aliasing `this` to self/hexo
        }
      ],
      // Place custom TS unused-vars rule last to ensure it takes precedence
      '@typescript-eslint/no-unused-vars': [
        'error',
        {
          argsIgnorePattern: '^_', // Allow ignored args starting with "_"
          varsIgnorePattern: '^_', // Allow ignored vars starting with "_"
          caughtErrorsIgnorePattern: '^_' // Allow ignored caught errors
        }
      ]
    }
  },

  // ---------------------------------------------------
  // ⚛️ React (JSX + TSX)
  // ---------------------------------------------------
  {
    files: ['**/*.{jsx,tsx}'],
    plugins: {
      react, // React linting rules
      'react-hooks': reactHooks, // Enforce hooks rules
      prettier
    },
    rules: {
      // ✅ React recommended rules
      ...react.configs.recommended.rules,
      ...react.configs['jsx-runtime'].rules,

      // ✅ React Hooks best practices
      ...reactHooks.configs.recommended.rules,

      // ✅ Prettier formatting
      'prettier/prettier': 'error',

      // ⚙️ Adjustments for modern React
      'react/react-in-jsx-scope': 'off', // Not needed in React 17+
      'react/prop-types': 'off' // Disable PropTypes if using TS
    },
    settings: {
      react: {
        version: 'detect' // Auto-detect installed React version
      }
    }
  }
);

Note:

  • For ESM projects ("type": "module" in package.json), use eslint.config.js or eslint.config.mjs.
  • For CommonJS projects (no "type": "module"), use eslint.config.cjs or eslint.config.js.
  • Choose the config file extension that matches your project's module system for best compatibility.

Key Features of This Config

  • Unified Linting: One config for JS, TS, React, and Prettier.
  • Modern Syntax Support: Babel parser for latest JS/JSX, TypeScript parser for TS/TSX.
  • React & Hooks: Best practices and rules for React and React Hooks.
  • Prettier Integration: Prettier runs as an ESLint rule, using config with comments.
  • Flexible Ignoring: Ignores common output, lock, and asset files.
  • Globals: Pre-configured for browser, Node.js, Jest, and common web globals.
  • Customizable: Easily extend or override for your project needs.
  • ESM & CJS Project Support: This ESLint config works for both ECMAScript Module (ESM) and CommonJS (CJS) projects—just use the appropriate file extension (.mjs, .js, or .cjs) for your eslint.config file to match your project's module system.

How to Use

  1. Install dependencies (see Requirements above).

  2. Copy the config into your project as eslint.config.js.

  3. Add a .prettierrc.json file (optionally with comments, thanks to JSONC support).

  4. Run ESLint on your codebase:

    npx eslint . --ext js,jsx,ts,tsx
  5. Integrate with your editor (e.g., VS Code) for real-time linting and formatting.


How to integrate with VSCode

Install plugins

Configure VSCode

Save below config to project settings .vscode/settings.json

{
  "terminal.integrated.env.linux": {
    // linux custom PATH environment variable
    "PATH": "${env:PATH}:${workspaceFolder}/node_modules/.bin:${workspaceFolder}/bin"
  },
  "terminal.integrated.env.windows": {
    // windows custom PATH environment variable
    "PATH": "${env:LOCALAPPDATA}\\nvm;C:\\nvm4w\\nodejs;C:\\Program Files\\Git\\cmd;C:\\Program Files\\Git\\usr\\bin;${env:PATH};${workspaceFolder}\\node_modules\\.bin;${workspaceFolder}\\bin;${workspaceFolder}\\vendor\\bin"
  },
  "javascript.suggestionActions.enabled": false,
  "eslint.useFlatConfig": true,
  "eslint.probe": [
    "astro",
    "civet",
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "html",
    "mdx",
    "vue",
    "markdown",
    "json",
    "jsonc"
  ],
  "eslint.validate": [
    "astro",
    "civet",
    "javascript",
    "javascriptreact",
    "typescript",
    "typescriptreact",
    "html",
    "mdx",
    "vue",
    "markdown",
    "json",
    "jsonc"
  ]
}

Troubleshooting & Tips

  • If you see parser errors, ensure all dependencies are installed and up to date.
  • For TypeScript, make sure your tsconfig.json is present and correct.
  • You can further customize rules for your team or project style.
  • For monorepos, you can share this config across packages.

References & Further Reading