ESLint
ESLint 是被广泛采用的代码检查工具,主要用于脚本文件。
安装
首先你需要安装 ESLint。目前支持 ESLint v8。
npm install eslint -D
yarn add eslint -D
pnpm install eslint -D
bun install eslint -d
配置
使用其它配置文件
如果你想要使用其它配置文件,请使用 eslint-ts-patch。
ESM
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import { eslint } from '@modyqyw/fabric';
// or
// import { eslint } from '@modyqyw/fabric/eslint';
export default eslint();
CJS
// eslint.config.cjs
// or eslint.config.js without "type": "module" in package.json
const { eslint } = require('@modyqyw/fabric');
// or
// const { eslint } = require('@modyqyw/fabric/eslint');
module.exports = eslint();
CLI
更新你的 package.json
,增加 lint:eslint
命令。
{
"scripts": {
"lint:eslint": "eslint . --fix --cache"
}
}
自定义
参数自定义
给导出的 eslint
方法传参可以自定义配置,eslint
方法接收两个参数。
第一个参数用于基本自定义,你可以传递 undefined
或对象。要明确地启用或禁用某一个配置,需要明确在传递的对象中设置 boolean 值。
目前支持以下配置:
- gitignore:基于 eslint-config-flat-gitignore,支持读取并使用 .gitignore 和 .eslintignore 内容作为平面配置的 ignores 选项,默认启用
- ignores:基于平面配置的 ignores 选项,默认启用
- imports:基于 eslint-plugin-i 和 eslint-plugin-import,检查导入相关问题,默认启用
- javascript:基于 @eslint/js,检查 JavaScript 相关问题,默认启用
- jsdoc:基于 eslint-plugin-jsdoc,检查 JSDoc 相关问题,默认禁用
- jsonc:基于 eslint-plugin-jsonc,检查 JSONC 相关问题,默认启用
- markdown:基于 eslint-plugin-markdown,检查 Markdown 相关问题,默认启用
- next:基于 @next/eslint-plugin-next,检查 Next 相关问题,安装 Next 后默认启用,否则默认禁用
- node:基于 eslint-plugin-n,检查 Node 相关问题,默认启用
- nuxt:基于 eslint-plugin-nuxt,检查 Nuxt 相关问题,安装 Nuxt 后默认启用,否则默认禁用
- perfectionist:基于 eslint-plugin-perfectionist,检查排序,默认启用
- perttier:基于 eslint-plugin-prettier 和 eslint-config-prettier,禁用代码样式规则,默认启用
- react:基于 eslint-plugin-react、eslint-plugin-react-hooks 和 eslint-plugin-react-refresh,检查 React 相关问题,安装 React 后默认启用,否则默认禁用
- reactNative:基于 eslint-plugin-react-native,检查 ReactNative 相关问题,安装 ReactNative 后默认启用,否则默认禁用
- regexp:基于 eslint-plugin-regexp,检查正则相关问题,默认启用
- solid:基于 eslint-plugin-solid,检查 solid 相关问题,安装 solid 后默认启用,否则默认禁用
- typescript:基于 @typescript-eslint/eslint-plugin,检查 TypeScript 相关问题,安装 TypeScript 后默认启用,否则默认禁用
- unicorn:基于 eslint-plugin-unicorn,默认启用
- unocss:基于 eslint-plugin-unocss,检查 UnoCSS 相关问题,安装 UnoCSS 后默认启用,否则默认禁用
- vue:基于 eslint-plugin-vue 和 eslint-plugin-vue-scoped-css,检查 Vue 相关问题,安装 Vue 后默认启用,否则默认禁用
- yml:基于 eslint-plugin-yml,检查 YML 相关问题,默认启用
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import {
eslint,
hasNext,
hasNuxt,
hasReact,
hasReactNative,
hasSolid,
hasTypeScript,
hasUnoCss,
hasVue,
} from '@modyqyw/fabric';
export default eslint({
// 基于 eslint-plugin-flat-gitignore
// 默认为 true,即启用
gitignore: true,
// 基于平面配置的 ignores 选项
// 默认为 true,即启用
ignores: true,
// 基于 eslint-plugin-i 和 eslint-plugin-import
// 默认为 true,即启用
imports: true,
// 基于 @eslint/js
// 默认为 true,即启用
javascript: true,
// 基于 eslint-plugin-jsdoc
// 默认为 false,即禁用
jsdoc: false,
// 基于 eslint-plugin-jsonc
// 默认为 true,即启用
jsonc: true,
// 基于 eslint-plugin-markdown
// 默认为 true,即启用
markdown: true,
// 基于 @next/eslint-plugin-next
// 安装 Next 后默认启用,否则默认禁用
next: hasNext,
// 基于 eslint-plugin-n
// 默认为 true,即启用
node: true,
// 基于 eslint-plugin-nuxt
// 安装 Nuxt 后默认启用,否则默认禁用
nuxt: hasNuxt,
// 基于 eslint-plugin-perfectionist
// 默认为 true,即启用
perfectionist: true,
// 基于 eslint-plugin-prettier 和 eslint-config-prettier
// 默认为 true,即启用
prettier: true,
// 基于 eslint-plugin-react、eslint-plugin-react-hooks 和 eslint-plugin-react-refresh
// 安装 React 后默认启用,否则默认禁用
react: hasReact,
// 基于 eslint-plugin-react-native
// 安装 ReactNative 后默认启用,否则默认禁用
reactNative: hasReactNative,
// 基于 eslint-plugin-regexp
// 默认为 true,即启用
regexp: true,
// 基于 eslint-plugin-solid
// 安装 solid 后默认启用,否则默认禁用
solid: hasSolid,
// 基于 @typescript-eslint/eslint-plugin
// 安装 TypeScript 后默认启用,否则默认禁用
typescript: hasTypeScript,
// 基于 eslint-plugin-unicorn
// 默认为 true,即启用
unicorn: true,
// 基于 eslint-plugin-unocss
// 安装 UnoCSS 后默认启用,否则默认禁用
unocss: hasUnoCss,
// 基于 eslint-plugin-vue 和 eslint-plugin-vue-scoped-css
// 安装 Vue 后默认启用,否则默认禁用
vue: hasVue,
// 基于 eslint-plugin-yml
// 默认为 true,即启用
yml: true,
});
除了传递 Boolean 值,你也可以直接传递配置项。这将视为启用配置,并使用传入的配置项。
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import { eslint } from '@modyqyw/fabric';
export default eslint({
gitignore: {
files: ['.gitignore', '.eslintignore'],
strict: false,
},
});
潜在冲突
eslint-plugin-perfectionist 可能与 @ianvs/prettier-plugin-sort-imports、@trivago/prettier-plugin-sort-imports、prettier-plugin-organize-imports、prettier-plugin-organize-attributes 冲突。如果你想启用四者之一,请关闭 eslint-plugin-perfectionist,见 Prettier 章节自定义部分。
eslint-plugin-jsonc 默认情况下不会与 prettier-plugin-packagejson 冲突。如果你想要使用 eslint-plugin-jsonc 对 package.json 排序,见 组合自定义,并禁用 prettier-plugin-packagejson,。
eslint-plugin-unocss 可能与 prettier-plugin-tailwindcss 冲突。当你同时使用 TailwindCSS 和 UnoCSS 时,请手动关闭其中之一。如果你想禁用 prettier-plugin-tailwindcss,见 Prettier 章节自定义部分。
第二个参数用于更进一步的自定义,你可以传递一个对象,用于调整生成的配置。
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import { eslint } from '@modyqyw/fabric';
export default eslint(undefined, [
// 默认地,在 scripts/**/* 和 cli.* 中使用 console 不会报错和警告
// 调整后,在 scripts/**/* 和 cli.* 中使用 console 会报错
// 需要改用专门的日志库,如 winston、consola、pino 等
{
files: ['scripts/**/*', 'cli.*'],
rules: {
'no-console': 'error',
},
},
]);
组合自定义
除了使用参数自定义外,你还可以通过组合来实现自定义。
比如只使用 JavaScript 和 TypeScript 规则:
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import { combine } from '@modyqyw/fabric';
import { javascript, typescript } from '@modyqyw/fabric/eslint';
export default combine(javascript(), typescript());
你也可以传递参数,来调整部分规则。
// eslint.config.mjs
// or eslint.config.js with "type": "module" in package.json
import { combine } from '@modyqyw/fabric';
import { javascript, typescript } from '@modyqyw/fabric/eslint';
export default combine(
javascript({ rules: { 'no-console': 'error' } }),
typescript(),
);
在上面的基础上,增加 Svelte 支持(需要自行安装相应的依赖):
// eslint.config.mjs
import * as _parserBabel from '@babel/eslint-parser';
// or eslint.config.js with "type": "module" in package.json
import {
GLOB_DTS,
GLOB_SCRIPT,
GLOB_SVELTE,
GLOB_TS,
GLOB_TSX,
GLOB_VUE,
combine,
interopDefault,
} from '@modyqyw/fabric';
import { javascript, typescript } from '@modyqyw/fabric/eslint';
import * as _parserTypeScript from '@typescript-eslint/parser';
import * as _pluginSvelte from 'eslint-plugin-svelte';
import * as _parserSvelte from 'svelte-eslint-parser';
const parserSvelte = interopDefault(_parserSvelte);
const parserBabel = interopDefault(_parserBabel);
const parserTypeScript = interopDefault(_parserTypeScript);
const pluginSvelte = interopDefault(_pluginSvelte);
export default combine(
// 匹配 Svelte 文件
javascript({ files: [GLOB_SCRIPT, GLOB_VUE, GLOB_SVELTE] }),
typescript({ files: [GLOB_DTS, GLOB_TS, GLOB_TSX, GLOB_VUE, GLOB_SVELTE] }),
// 增加 Svelte 支持
[
{
files: ['**/*.svelte'],
languageOptions: {
ecmaFeatures: {
globalReturn: false,
jsx: false,
},
ecmaVersion: 'latest',
extraFileExtensions: ['.svelte'],
parser: {
js: parserBabel,
jsx: parserBabel,
ts: parserTypeScript,
tsx: parserTypeScript,
},
requireConfigFile: false,
sourceType: 'module',
},
plugins: {
svelte: pluginSvelte,
},
processor: pluginSvelte.processors['.svelte'],
rules: {
// ESLint core rules known to cause problems with `.svelte`.
'no-inner-declarations': 'off', // The AST generated by svelte-eslint-parser will false positives in it rule because the root node of the script is not the `Program`.
// "no-irregular-whitespace": "off",
// Self assign is one of way to update reactive value in Svelte.
'no-self-assign': 'off',
// eslint-plugin-svelte rules
'svelte/comment-directive': 'error',
'svelte/system': 'error',
...pluginSvelte.configs.recommended.rules,
...pluginSvelte.configs.prettier.rules,
},
},
],
);
整合
VSC
先安装 对应的 ESLint 插件。
{
// 启用 ESLint 平面配置
// "eslint.experimental.useFlatConfig": true, // ESLint 插件 < 3.0.10
"eslint.useFlatConfig": true, // ESLint 插件 >= 3.0.10
// ESLint 检查的语言
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue",
"markdown",
"json",
"jsonc",
"yaml",
],
// JavaScript、JSX、TypeScript、TypeScript JSX 手动保存后 ESLint 自动修复
"[javascript][javascriptreact][typescript][typescriptreact]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
},
// Vue 手动保存后 ESLint 自动修复
"[vue]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
},
// markdown 手动保存后 ESLint 自动修复
"[markdown][yaml][json][jsonc]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
},
// JSON、JSONC 手动保存后 ESLint 自动修复
"[json][jsonc]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
},
// YAML 手动保存后 ESLint 自动修复
"[yaml]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
},
},
}
WebStorm
WebStorm 自带 ESLint,可参考 VSC 自行调整。
lint-staged
如果你使用该库提供的 lint-staged 配置,请查看 lint-staged 章节。
如果你没有使用该库提供的 lint-staged 配置,可以参考以下配置。
// lint-staged.config.mjs
// or lint-staged.config.js with "type": "module" in package.json
export default {
'*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,vue}':
'eslint --fix --cache --no-error-on-unmatched-pattern',
'*.{json,jsonc,json5}':
'eslint --fix --cache --no-error-on-unmatched-pattern',
'*.{yaml,yml}': 'eslint --fix --cache --no-error-on-unmatched-pattern',
};
为什么不检查类型?
类型规则有一个问题。通过在配置中包含
parserOptions.project
,你会因要求 TypeScript 在 ESLint 进行 linting 之前构建项目而遭受性能损失。对于小型项目,这需要的时间可以忽略不计(几秒或更短);对于大型项目,可能需要更长的时间。
引自 typescript-eslint.io/linting/typed-linting#how-is-performance。
直接运行 tsc / vue-tsc 可以避免这部分性能损失,同时可以进行更完整的类型检查。请查看 tsc 章节。