ESLint静态代码分析工具
重要通知
如果您使用 ESLint,请安装 eslint-config-prettier 以使 ESLint 和 Prettier 彼此配合得很好。它会关闭所有不必要的或可能与 Prettier 冲突的 ESLint 规则。
基本概况
ESLint 是一种用于识别和报告在 ECMAScript/JavaScript 代码中发现的模式的工具。
规则效果实时演示:https://eslint.org/play/
ESLint与JSLint、JSHint的差异
- ESLint 使用Espree进行 JavaScript 解析。
- ESLint 使用 AST 来评估代码中的模式。
- ESLint 是完全可插拔的,每一条规则都是一个插件,你可以在运行时添加更多。
安装配置
> npm i -g eslint # 全局安装,注意是否影响其他项目
> npm init @eslint/config
> npm install eslint --save-dev # 局部安装
> ./node_modules/.bin/eslint --init # 初始化配置文件
> ./node_modules/.bin/eslint main.js # 运行相关文件
文件目录与优先级顺序
- .eslintrc.js
- .eslintrc.cjs
- .eslintrc.yaml
- .eslintrc.yml
- .eslintrc.json
- package.json
关闭ESLint校验语句
/* eslint-disable */ // 关闭单个文件校验,放在文件顶部
[code]
/* eslint-enable */ // 关闭段落校验
[code]
[code] // eslint-disable-line // 关闭当前行校验
// eslint-disable-next-line // 关闭下一行校验
[code]
命令行工具
> eslint */**/*.js # 检测当前目录所有js文件
注意事项
解决 Prettier 和 ESLint 的冲突
- eslint-plugin-prettier 将 Prettier 的规则设置到 ESLint 的规则中。
- eslint-config-prettier 关闭 ESLint 中与 Prettier 中会发生冲突的规则。
解析器
export default {
parser: "vue-eslint-parser"
}
开启自动检测
npm run lint检测指令
{
"scripts": {
"lint": "eslint \"src/**/*.{vue,ts,js}\" --fix",
"lint:eslint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
}
}
配置.vscode/settings.json
{
"editor.formatOnSave": true,
// 为ESLint启用“保存时自动修复”,并且仍然具有格式和快速修复功能
"editor.codeActionsOnSave": {
"source.fixAll": true,
"source.fixAll.eslint": true
}
}
.eslintignore
忽略文件目录
dist
node_modules
public
src/assets
.eslintrc.cjs
.prettierrc.cjs
.stylelintrc.cjs
package.json配置规则
{
"name": "ESLint",
"version": "1.0.0",
"eslintConfig": {
"plugins": ["example"],
"env": {
"example/custom": true,
"browser": true,
"node": true,
"es2021": true
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaVersion": 12,
"sourceType": "module"
},
"rules": {
"indent": ["error", 2],
"quotes": ["error", "single"],
"semi": ["error", "always"],
"no-console": "warn",
"no-unused-vars": ["warn", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false }]
}
}
}
推荐配置
在项目中经常的配置选项。
rules: {
"semi": ["error", "always"], # 分号
}
.eslintrc.js与package.json
package.json
{
"name": "erp_ding_fe",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite --mode serve-dev",
"build:test": "vite build --mode build-test",
"build": "vite build --mode build",
"preview": "vite preview",
"lint": "eslint --ext .js,.jsx,.vue,.ts,.tsx src --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"axios": "0.21.3",
"lib-flexible": "^0.3.2",
"miment": "^0.0.9",
"nprogress": "0.2.0",
"path": "0.12.7",
"pinia": "^2.1.3",
"qs": "^6.10.3",
"terser": "^5.19.2",
"vant": "^4.6.3",
"vue": "^3.3.4",
"vue-router": "^4.2.2"
},
"devDependencies": {
"@babel/eslint-parser": "7.16.3",
"@types/node": "15.0.1",
"@typescript-eslint/eslint-plugin": "5.5.0",
"@typescript-eslint/parser": "5.5.0",
"@vitejs/plugin-legacy": "1.6.4",
"@vitejs/plugin-vue": "1.10.2",
"@vitejs/plugin-vue-jsx": "1.3.1",
"@eslint/js": "^9.2.0",
"@rushstack/eslint-patch": "^1.2.0",
"postcss-pxtorem": "^6.0.0",
"prettier": "^2.8.8",
"sass": "^1.64.1",
"sass-loader": "^13.3.2",
"svg-sprite-loader": "^6.0.11",
"typescript-eslint": "^7.9.0",
"unplugin-vue-components": "^0.25.1",
"vite": "^4.3.9",
"vite-plugin-html": "^3.2.0",
"vite-plugin-svg-icons": "^2.0.1",
"typescript": "~4.5.0",
"vue-tsc": "^1.0.8",
"@vue/compiler-sfc": "3.2.26",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/tsconfig": "^0.1.3",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-define-config": "1.2.0",
"eslint-plugin-import": "2.25.3",
"eslint-plugin-prettier": "4.0.0",
"eslint-plugin-vue": "^9.0.0"
}
}
.eslintrc.js
// https://blog.csdn.net/Sheng_zhenzhen/article/details/108685176
module.exports = {
root: true,
env: {
browser: true,
commonjs: true,
es6: true,
node: true
},
globals: {
defineEmits: true,
document: true,
localStorage: true,
__APP_VERSION__: true,
GLOBAL_VAR: true,
window: true,
defineProps: true,
defineExpose: true,
ElementPlusLocaleZhCn: true,
pdfjsLib: true
},
plugins: ['@typescript-eslint', 'prettier', 'import'],
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:vue/vue3-recommended', 'prettier'],
parserOptions: {
parser: '@typescript-eslint/parser',
sourceType: 'module',
ecmaFeatures: {
jsx: true,
tsx: true
}
},
rules: {
"semi": ["error", "always"],
//close lf error
'import/no-unresolved': [0],
'vue/multi-word-component-names': 'off',
'vue/no-deprecated-router-link-tag-prop': 'off',
'import/extensions': 'off',
'import/no-absolute-path': 'off',
'no-async-promise-executor': 'off',
'import/no-extraneous-dependencies': 'off',
'vue/no-multiple-template-root': 'off',
'vue/html-self-closing': 'off',
'vue/attribute-hyphenation': 'off',
"vue/v-on-event-hyphenation": 'off',
"vue/no-v-html": "off",
"vue/valid-v-slot": "off",
"vue/valid-v-for": "off",
'no-console': 'off',
'no-plusplus': 'off',
'no-useless-escape': 'off',
'no-bitwise': 'off',
'@typescript-eslint/no-explicit-any': ['off'],
'@typescript-eslint/explicit-module-boundary-types': ['off'],
'@typescript-eslint/ban-ts-comment': ['off'],
'vue/no-setup-props-destructure': ['off'],
'@typescript-eslint/no-empty-function': ['off'],
'vue/script-setup-uses-vars': ['off'],
//can config to 2 if need more then required
'@typescript-eslint/no-unused-vars': [0],
'no-param-reassign': ['off']
}
}
eslint-config-prettier
关闭所有不必要的规则或可能与 Prettier 冲突的规则。
.eslintrc.json
基本规则
- 0 | "off": 关闭规则
- 1 | "warn": 将规则视为一个警告(不会影响退出码)
- 2 | "error": 将规则视为一个错误 (退出码为1)
基本配置
// 所有的规则默认都是禁用的。
{
// 配置环境
"env": {
"browser": true,
"commonjs": true,
"es6": true, // 自动启用es6语法,包括自动启用es6全局变量
"node": true,
"jest": true,
"worker": true,
"serviceworker": true
},
// 配置全局变量,ESLint规则将忽略此变量提示
"globals": {
"globalVAR1": "writable", // 允许重写变量
"globalVAR2": "readonly" // 不允许重写变量
},
// 解析器
"parser": "@typescript-eslint/parser",
"parser": "vue-eslint-parser", // 解决 出现 error Parsing error: '>' expected 的解析错误
"parser": "babel-eslint",
// 设置解析器选项, 所有语言选项默认都是 false, ESLint 默认使用Espree作为其解析器
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"jsx": true
}
},
"plugins": [
"vue",
"react",
"@typescript-eslint",
"prettier",
"react-hooks"
],
// 默认所有在 规则页面 被标记为"勾"的规则将会默认开启。
"extends": "eslint:recommended",
"extends": [
// 规则列表: https://eslint.bootcss.com/docs/rules/
"eslint:recommended", // 启用推荐规则,所有在[规则页面]被标记为""的规则将会默认开启,报告一些常见的问题,在下文中这些推荐的规则都带有一个标记。
"eslint-config-airbnb",
"plugin:@typescript-eslint/recommended",
"prettier",
"plugin:prettier/recommended",
"plugin:vue/vue3-recommended"
],
"overrides": [],
// 匹配规则列表
"rules": {
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
"no-useless-constructor": "warn",
"eqeqeq": "warn",
"react/no-did-update-set-state": "warn",
"no-loop-func": "off",
"no-void": "off",
"camelcase": "off", // 驼峰命名
"array-callback-return": "off",
"import/order": "off",
"no-return-assign": "off",
"prefer-spread": "off",
"import/no-relative-packages": "off",
"max-classes-per-file": "off",
"no-empty": "off",
"no-prototype-builtins": "off",
"prefer-destructuring": "off",
"consistent-return": "off",
"no-return-await": "off",
"no-await-in-loop": "off",
"class-methods-use-this": "off",
"no-param-reassign": "off",
"radix": "off",
"no-bitwise": "off",
"no-lonely-if": "off",
"no-plusplus": "off",
"prettier/prettier": "error",
"indent": "off",
"guard-for-in": "off",
"global-require": "off",
"default-param-last": "off",
"semi": ["error", "always"], // 分号
"quotes": ["error", "double"], // 逗号
"no-undef": 2,
"no-unused-expressions": [
"error",
{
"allowTernary": true,
"allowShortCircuit": true,
"allowTaggedTemplates": true
}
],
"spaced-comment": ["error", "always", { "markers": ["/"] }],
"import/extensions": "off",
"import/no-unresolved": "off",
"import/no-dynamic-require": "off",
"import/prefer-default-export": "off",
"import/no-extraneous-dependencies": "off",
"no-shadow": "off",
"no-console": "off",
"no-continue": "off",
"no-nested-ternary": "off",
"no-underscore-dangle": "off",
"no-restricted-syntax": "off",
"no-use-before-define": "off",
"no-restricted-exports": "off",
"linebreak-style": ["error", "unix"],
"vue/multi-word-component-names": "off",
"vue/max-attributes-per-line": "off",
"jsx-a11y/alt-text": "off",
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off",
"jsx-a11y/no-noninteractive-element-interactions": "off",
"jsx-a11y/anchor-is-valid": "off",
"jsx-a11y/iframe-has-title": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/media-has-caption": "off",
"react/jsx-indent": "off",
"react/prop-types": "off",
"react/jsx-wrap-multilines": "off",
"react/jsx-filename-extension": "off",
"react/jsx-props-no-spreading": "off",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/no-unused-prop-types": "off",
"react/require-default-props": "off",
"react/destructuring-assignment": "off",
"react/jsx-one-expression-per-line": "off",
"react/jsx-boolean-value": ["error", "always"],
"react/function-component-definition": "off",
"react/no-arrow-function-lifecycle": "warn",
"react/sort-comp": "off",
"react/button-has-type": "off",
"react/static-property-placement": "off",
"react/no-unused-class-component-methods": "off",
"react/no-access-state-in-setstate": "off",
"react/no-find-dom-node": "off",
"react/state-in-constructor": "off",
"react/no-unused-state": "off",
"react/jsx-no-bind": "off",
"react/no-array-index-key": "off",
"react/no-unescaped-entities": "off",
"react/no-unstable-nested-components": "off",
"react/jsx-no-useless-fragment": "off",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-interface": "off",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/triple-slash-reference": "off",
"@typescript-eslint/no-triple-slash-reference": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-use-before-define": [
"error",
{
"variables": false,
"functions": false
}
],
"@typescript-eslint/no-unused-vars": [
"error",
{
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true
}
]
}
}
eslint-plugin-vue
Vue.js 的官方 ESLint 插件。