First thing to note is that the eslint.config.js file should be at the root level of your project; you can target specific files and folders within the project structure from this one central configuration if need be i.e. in a monorepo.
The "extends" property does not exist under the new ESLint flat configuration schema, as per the 'Configuration Objects' specified in their documentation. You can directly import a configuration and declare it within the new eslint.config.js, however if that configuration extends other configurations this won't work - I can't see your '@ui' configuration definition so I have assumed in my code block that it does not extend configurations within itself (if it does, see blog link below on using @eslint/eslintrc 'compat' to bring in such configurations).
The "parserOptions" is also not a top-level property under the new schema and falls inside the 'languageOptions' property.
// eslint.config.js at the project root
import ParserTypescriptEslint from '@typescript-eslint/parser'
import PluginImport from 'eslint-plugin-import';
import PluginJest from 'eslint-plugin-jest';
import UIConfig from 'ui-config-path';
import globals from 'globals';
export default [
UIConfig,
{
files: [ "// Specify the files you wish to target with this configuration" ],
languageOptions: {
ecmaVersion: 2021,
sourceType: 'module',
globals: {
...globals.browser,
...globals.es2021,
},
parser: ParserTypescriptEslint,
parserOptions: {
project: ["./tsconfig.json"],
tsconfigRootDir: __dirname,
},
},
plugins: {
import: PluginImport,
jest: PluginJest
},
rules: {
"jest/no-deprecated-functions": "off"
},
settings: {
"import/resolver": {
...PluginImport.configs.typescript.settings['import/resolver'],
typescript: {
project: ["tsconfig.json"],
},
},
},
}
]
If you have multiple sub-configurations that you wish to use for different folders/systems - React, Express, Jest, etc - then you can write those configurations following the new schema and spread them into the main eslint.config.js file. This is a snippet of my main eslint.config.js that uses several different sub-configurations.
import { EslintConfig, ConfigPrettier } from '@packages/eslint-config';
import { EslintConfigReact } from '@packages/eslint-config-react';
import { EslintConfigReactTest } from '@packages/eslint-config-react-test';
import { EslintConfigExpress } from '@packages/eslint-config-express';
export default [
ConfigPrettier,
{
ignores: ['**/node_modules', '**/dist', '**/build', '**/__snapshots__', '**/mocks', '**/coverage'],
},
{
// Client - React
files: [
'apps/*/frontend/**/*.ts',
'apps/*/frontend/**/*.tsx',
'apps/*/frontend/**/*.jsx',
'apps/*/frontend/**/*.js',
],
languageOptions: { ...EslintConfig.languageOptions, ...EslintConfigReact.languageOptions },
plugins: { ...EslintConfig.plugins, ...EslintConfigReact.plugins },
rules: { ...EslintConfig.rules, ...EslintConfigReact.rules },
settings: { ...EslintConfig.settings, ...EslintConfigReact.settings },
}
];
The following blog post was useful to me in setting up the new ESLint flat configuration in a monorepo structure: migration-eslint-to-flat-config
Answer from SS87 on Stack OverflowVideos
extends uses a config file which applies set of rules when you add that to the extends options. A plugin on the other hand provides you with a set of rules that you can individually apply depending on your need. Just having a plugin does not enforce any rule. You have to choose which rules you need. A plugin may provide you with zero, one, or more configuration files. If the plugin provides configuration file, then you can load that in your extends section after adding the plugin in the plugins section.
So essentially, plugins given you some rules that have been coded and you can choose which ones are relevant. It may also provide config files to apply rules that the authors think are logically grouped/relevant but providing a config file is not mandatory for a plugin. extends, on the other hand, provides you the ability to apply rules in bulk based on config file specifications.
Example Plugin - eslint-plugin-react
{
"plugins": [
"react"
],
"extends": [
"eslint:recommended",
"plugin:react/recommended"
]
}
Example Config - eslint-config-google
{
"extends": [
"google"
]
}
In addition to shmit's good answer:
extends
is about extending configurations in general, not only plugins. Potential values are:
"eslint:recommended""eslint:all"- Shareable configuration from npm package (
eslint-config-xxxor scoped name) - Plugin configuration from npm package (
eslint-plugin-xxxor scoped name) - Another configuration file, like
"./my/path/.eslintrc.js"
Plugin notation: plugin:<package name>/<configuration name>, e.g. for eslint-plugin-react:
Copy "extends": ["plugin:react/recommended"]
By extending from a plugin config, we can get recommended rules without adding them manually.
plugins
A plugin is a special eslint npm package, that provides additional rule definitions (rules), environments, processors and configs for different configurations of recommended / default rule values.
The plugins property in .eslintrc.js is merely a flag to enable a given plugin after installation with npm i. We now can refer to the plugin's rules, but have to set all rules values manually.
Think of plugins as a way to activate a plugin - to use its rules, you need to add the plugin once in the chain in every case.
plugins is not needed in your own config, if it is already defined in a configuration, that you extend from by extends.
Example:
eslint-plugin-react already contains plugins: [ 'react' ], hence this entry is not needed anymore in own config and plugin rules can be used directly.