$ npm install --save-dev @fullstacksjs/eslint-config eslint prettier
⚡️ That's it, you don't need to install any eslint-plugin! If you already have some plugins installed, please remove them.
To use the configuration, all you need is to export the generated config by the defineConfig
function. It automatically enables required plugins with Auto Module Detection.
import { defineConfig } from '@fullstacksjs/eslint-config';
export default defineConfig({
typescript: {
tsconfigRootDir: import.meta.dirname, // If you are using TypeScript
}
});
const { defineConfig } = require('@fullstacksjs/eslint-config');
module.exports = defineConfig({
tsconfigRootDir: import.meta.dirname, // If you are using TypeScript
});
Automatic module detection enables ESLint plugins based on the dependencies listed in your package.json
. It scans your project to identify which tools you're using, and then activates the corresponding ESLint plugins accordingly.
For example, if your package.json
includes vitest
as a dependency, the configuration will automatically enable eslint-plugin-vitest
for you. (You don't need to install the plugin itself)
You can fine-tune module detection by overriding it, the defineConfig
function accepts options as its first argument to control enabled modules.
interface Options {
react?: boolean; // controls react, react-hooks, jsx/a11y plugins
typescript?: ParserOptions // https://typescript-eslint.io/packages/parser#configuration
node?: boolean; // controls node plugin
sort?: boolean; // controls perfectionist plugin
strict?: boolean; // controls strict rules
import?: { internalRegExp?: string; lifetime?: number; }; // controls import plugin
esm?: boolean; // controls esm plugin
test?: boolean; // controls test formatting plugin
jest?: boolean; // controls jest plugin
vitest?: boolean; // controls vitest plugin
cypress?: boolean; // controls cypress plugin
playwright?: boolean // controls playwright plugin
storybook?: boolean; // controls storybook plugin
tailwind?: boolean | { callee?: string[] }; // controls tailwindcss plugin
next?: boolean; // controls next plugin
prettier?: boolean; // controls prettier plugin
disableExpensiveRules?: boolean; // controls expensive rules
}
You can pass any number of arbitrary custom config overrides to defineConfig
function:
import { defineConfig } from '@fullstacksjs/eslint-config';
export default defineConfig(
{
typescript: true,
// You can pass extends here
rules: {
'no-console': 'error'
}
},
// And any number of extra configurations
{
files: ['**/*.ts'],
rules: {},
}, {
rules: {},
})
You can still use any ESLint plugin, even if it's not supported by automatic detection. Simply install the plugin manually and add it to the defineConfig
. There are no limitations.
import { defineConfig } from '@fullstacksjs/eslint-config';
import pluginVue from 'eslint-plugin-vue';
export default defineConfig(
{ /* Options */},
...pluginVue.configs['flat/recommended']
)
This configuration includes built-in support for Next.js. The warning you're seeing from Next.js is misleading—it simply checks whether the plugin is explicitly listed in your package.json.
You can safely ignore this warning. Alternatively, you can update your lint script from next lint to eslint to avoid it entirely.
Balancing the benefits of linting rules against their performance impact is crucial. Below is a table highlighting the most resource-intensive linting rules encountered in a real-world React project:
Rule | Time (ms) | Relative |
---|---|---|
prettier/prettier | 3299.631 | 19.2% |
@typescript-eslint/no-misused-promises | 2473.767 | 14.4% |
import/no-cycle | 1177.111 | 6.8% |
import/namespace | 1148.731 | 6.7% |
As illustrated, certain rules significantly increase linting time, potentially hindering the developer experience by slowing down the feedback loop. To mitigate this, you may consider disabling these resource-intensive rules in the development environment. However, they can remain active in environments where performance is less critical, such as Continuous Integration (CI) systems or during pre-commit checks (git hooks).
To conditionally disable expensive linting rules, you can modify your configuration as follows:
List of expensiveRules
to be affected:
@typescript-eslint/no-floating-promises
@typescript-eslint/no-misused-promises
import/default # (disabled in TS env)
import/export # (disabled in TS env)
import/named # (disabled in TS env)
import/no-named-as-default-member # (disabled in TS env)
import/namespace
import/no-cycle
import/no-deprecated
export default defineConfig({
disableExpensiveRules: !process.env.CI || !process.env.HUSKY // Or anywhere you want
prettier: false // So you should run the formatter explicitly.
});
- @eslint-react/eslint-plugin
- @next/eslint-plugin-next
- @stylistic/eslint-plugin
- eslint-plugin-cypress
- eslint-plugin-import-x
- eslint-plugin-jest
- eslint-plugin-jest-formatting
- eslint-plugin-jsx-a11y
- eslint-plugin-n
- eslint-plugin-perfectionist
- eslint-plugin-playwright
- eslint-plugin-prettier
- eslint-plugin-promise
- eslint-plugin-react-hooks
- eslint-plugin-storybook
- eslint-plugin-tailwindcss
- eslint-plugin-vitest
- typescript-eslint
That's all. Feel free to use 💛