一尘子、道法自然、博客园、前端

Vue3 + TypeScript 项目中 ESLint 与 Prettier 的完美集成实践

前言

在现代前端开发中,代码质量和代码格式的一致性至关重要。ESLint 和 Prettier 是两个不可或缺的工具,但它们各自有不同的职责。本文将详细介绍如何在 Vue3 + TypeScript 项目中正确集成这两个工具,避免冲突,实现最佳实践。

一、ESLint 与 Prettier 的区别

ESLint:代码质量检查工具

职责:检查代码质量、发现潜在错误、强制执行最佳实践

功能

  • 发现未使用的变量和导入
  • 检查可能的逻辑错误
  • 强制代码规范(命名、复杂度等)
  • 检查 TypeScript 类型问题
  • 检查 Vue 组件规范

示例

// ESLint 会报错:'unusedVar' 已定义但未使用
const unusedVar = 123;

// ESLint 会报错:使用了未定义的变量
console.log(undefinedVar);

Prettier:代码格式化工具

职责:统一代码格式、美化代码

功能

  • 统一缩进(制表符/空格)
  • 统一引号(单引号/双引号)
  • 统一分号
  • 统一换行
  • 统一对象/数组格式

示例

// Prettier 会格式化为:
const obj={a:1,b:2}

// 格式化后:
const obj = { a: 1, b: 2 };

两者的关系

  • 互补关系:ESLint 关注"做什么"(代码质量),Prettier 关注"怎么做"(代码格式)
  • 必须配合使用:只用 ESLint 无法保证格式统一,只用 Prettier 无法发现代码质量问题

二、为什么需要集成?

问题场景

当 ESLint 和 Prettier 同时运行时,可能会出现以下冲突:

  1. 规则冲突:ESLint 的格式化规则与 Prettier 的格式化规则冲突
  2. 重复检查:两个工具都在检查格式化问题,造成重复
  3. 维护成本:需要手动关闭大量格式化相关的 ESLint 规则

解决方案

使用 eslint-config-prettiereslint-plugin-prettier 来:

  • 自动禁用 ESLint 中与 Prettier 冲突的规则
  • 将 Prettier 的格式化错误作为 ESLint 错误显示
  • 实现统一的代码检查和格式化流程

三、完整配置步骤

步骤 1:安装必要的依赖

yarn add -D eslint-config-prettier eslint-plugin-prettier

或者使用 npm:

npm install -D eslint-config-prettier eslint-plugin-prettier

步骤 2:配置 ESLint (.eslintrc.js)

module.exports = {
	root: true,
	env: {
		browser: true,
		es2021: true,
		node: true,
	},
	parser: 'vue-eslint-parser',
	parserOptions: {
		ecmaVersion: 12,
		parser: '@typescript-eslint/parser',
		sourceType: 'module',
	},
	extends: [
		'eslint:recommended',
		'plugin:@typescript-eslint/recommended',
		'plugin:vue/vue3-essential',
		'plugin:prettier/recommended', // 必须放在最后,集成 Prettier 并禁用冲突规则
	],
	plugins: ['vue', '@typescript-eslint', 'prettier'],
	overrides: [
		{
			files: ['*.ts', '*.tsx', '*.vue'],
			rules: {
				'no-undef': 'off',
			},
		},
	],
	rules: {
		// Prettier 集成 - 将 Prettier 错误作为 ESLint 错误
		'prettier/prettier': 'error',

		// TypeScript 规则
		// http://eslint.cn/docs/rules/
		// https://typescript-eslint.io/rules/no-unused-vars/
		'@typescript-eslint/ban-ts-ignore': 'off',
		'@typescript-eslint/explicit-function-return-type': 'off',
		'@typescript-eslint/no-explicit-any': 'off',
		'@typescript-eslint/no-var-requires': 'off',
		'@typescript-eslint/no-empty-function': 'off',
		'@typescript-eslint/no-use-before-define': 'off',
		'@typescript-eslint/ban-ts-comment': 'off',
		'@typescript-eslint/ban-types': 'off',
		'@typescript-eslint/no-non-null-assertion': 'off',
		'@typescript-eslint/explicit-module-boundary-types': 'off',
		'@typescript-eslint/no-redeclare': 'error',
		'@typescript-eslint/no-non-null-asserted-optional-chain': 'off',
		'@typescript-eslint/no-unused-vars': [2],

		// Vue 规则
		// https://eslint.vuejs.org/rules/
		// 注意:格式化相关的规则已由 eslint-config-prettier 自动禁用
		'vue/custom-event-name-casing': 'off',
		'vue/one-component-per-file': 'off',
		'vue/no-multiple-template-root': 'off',
		'vue/require-default-prop': 'off',
		'vue/no-v-model-argument': 'off',
		'vue/no-arrow-functions-in-watch': 'off',
		'vue/no-template-key': 'off',
		'vue/no-v-html': 'off',
		'vue/comment-directive': 'off',
		'vue/no-parsing-error': 'off',
		'vue/no-deprecated-v-on-native-modifier': 'off',
		'vue/multi-word-component-names': 'off',

		// 其他规则
		'no-useless-escape': 'off',
		'no-sparse-arrays': 'off',
		'no-prototype-builtins': 'off',
		'no-constant-condition': 'off',
		'no-use-before-define': 'off',
		'no-restricted-globals': 'off',
		'no-restricted-syntax': 'off',
		'generator-star-spacing': 'off',
		'no-unreachable': 'off',
		'no-unused-vars': 'off', // 使用 @typescript-eslint/no-unused-vars 代替
		'no-case-declarations': 'off',
		'no-console': 'off',
		'no-redeclare': 'off',
	},
};

关键点

  • plugin:prettier/recommended 必须放在 extends 数组的最后
  • 这会自动启用 eslint-config-prettiereslint-plugin-prettier
  • 自动禁用所有与 Prettier 冲突的 ESLint 规则

步骤 3:配置 Prettier (.prettierrc.js)

module.exports = {
	// 一行最多多少个字符
	printWidth: 150,
	// 指定每个缩进级别的空格数
	tabWidth: 2,
	// 使用制表符而不是空格缩进行
	useTabs: true,
	// 在语句末尾打印分号
	semi: true,
	// 使用单引号而不是双引号
	singleQuote: true,
	// 更改引用对象属性的时间
	quoteProps: 'as-needed',
	// 在JSX中使用单引号而不是双引号
	jsxSingleQuote: false,
	// 多行时尽可能打印尾随逗号
	trailingComma: 'es5',
	// 在对象文字中的括号之间打印空格
	bracketSpacing: true,
	// jsx 标签的反尖括号需要换行
	jsxBracketSameLine: false,
	// 在单独的箭头函数参数周围包括括号
	arrowParens: 'always',
	// 使用默认的折行标准
	proseWrap: 'preserve',
	// 指定HTML文件的全局空格敏感度
	htmlWhitespaceSensitivity: 'css',
	// Vue文件脚本和样式标签缩进
	vueIndentScriptAndStyle: false,
	// 换行符使用 lf
	endOfLine: 'lf',
};

步骤 4:创建 .prettierignore

创建 .prettierignore 文件,忽略不需要格式化的文件:

# 依赖
node_modules
package-lock.json
yarn.lock
pnpm-lock.yaml

# 构建输出
dist
build
coverage
*.min.js
*.min.css

# 日志
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# 环境配置
.env
.env.local
.env.*.local

# IDE
.vscode
.idea
*.swp
*.swo
*~

# 其他
.DS_Store
Thumbs.db

步骤 5:配置 package.json 脚本

{
	"scripts": {
		"format": "prettier --write \"**/*.{js,ts,tsx,vue,json,css,scss,md}\"",
		"format:check": "prettier --check \"**/*.{js,ts,tsx,vue,json,css,scss,md}\"",
		"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
	}
}

四、工作流程

推荐的开发流程

┌─────────────────┐
│   你的代码       │
└────────┬────────┘
         │
    ┌────┴────┐
    │         │
    ▼         ▼
┌────────┐ ┌──────────┐
│Prettier│ │ ESLint   │
│格式化  │ │质量检查  │
└────────┘ └──────────┘
    │         │
    └────┬────┘
         │
    ┌────▼────┐
    │ 最终代码 │
    └─────────┘

使用命令

# 1. 格式化所有代码
yarn format

# 2. 检查代码格式是否符合规范
yarn format:check

# 3. 修复 ESLint 错误(包括 Prettier 格式问题)
yarn lint-fix

五、最佳实践

1. 配置顺序很重要

plugin:prettier/recommended 必须放在 extends 数组的最后,确保它能覆盖其他配置中的冲突规则。

2. 职责分离

  • Prettier:只负责格式化(缩进、引号、分号等)
  • ESLint:只负责代码质量(未使用变量、类型错误等)

3. 不要手动关闭格式化规则

使用 eslint-config-prettier 自动处理,而不是手动关闭每个格式化相关的规则。

4. 统一团队配置

.eslintrc.js.prettierrc.js 提交到版本控制,确保团队成员使用相同的配置。

5. 集成到 CI/CD

在 CI/CD 流程中添加格式检查:

{
	"scripts": {
		"ci:format": "prettier --check \"**/*.{js,ts,tsx,vue,json,css,scss,md}\"",
		"ci:lint": "eslint --ext .js,.jsx,.ts,.tsx,.vue src/"
	}
}

六、常见问题

Q1: 为什么 plugin:prettier/recommended 必须放在最后?

A: 因为 ESLint 的配置是按顺序应用的,后面的配置会覆盖前面的。放在最后可以确保 Prettier 的配置能够覆盖所有其他配置中的冲突规则。

Q2: 如何只格式化特定文件?

A: 使用 Prettier 的文件路径参数:

prettier --write "src/**/*.vue"

Q3: ESLint 和 Prettier 冲突怎么办?

A: 确保已安装并正确配置 eslint-config-prettier。如果仍有冲突,检查 extends 数组的顺序。

Q4: 如何在 VS Code 中自动格式化?

A: 在 VS Code 设置中添加:

{
	"editor.defaultFormatter": "esbenp.prettier-vscode",
	"editor.formatOnSave": true,
	"editor.codeActionsOnSave": {
		"source.fixAll.eslint": true
	}
}

Q5: 如何处理 HTML void 元素?

A: 确保使用自闭合标签,例如:

<!-- ❌ 错误 -->
<img src="..." alt=""></img>

<!-- ✅ 正确 -->
<img src="..." alt="" />

七、配置对比

优化前(不符合规范)

// ❌ 手动关闭大量格式化规则
extends: ['plugin:vue/vue3-essential', 'eslint:recommended'],
rules: {
	'vue/html-closing-bracket-newline': 'off',
	'vue/max-attributes-per-line': 'off',
	'vue/multiline-html-element-content-newline': 'off',
	// ... 更多手动关闭的规则
}

优化后(符合规范)

// ✅ 自动处理冲突规则
extends: [
	'eslint:recommended',
	'plugin:@typescript-eslint/recommended',
	'plugin:vue/vue3-essential',
	'plugin:prettier/recommended', // 自动禁用冲突规则
],
rules: {
	'prettier/prettier': 'error',
	// 只需要关注代码质量规则
}

八、总结

通过正确集成 ESLint 和 Prettier,我们可以:

  1. 提高代码质量:ESLint 发现潜在错误
  2. 统一代码格式:Prettier 保证格式一致
  3. 降低维护成本:自动处理规则冲突
  4. 提升开发效率:自动化格式化和检查
  5. 符合业界规范:使用标准的最佳实践

关键要点

  • ESLint 和 Prettier 是互补工具,应该同时使用
  • 使用 eslint-config-prettier 自动处理冲突
  • plugin:prettier/recommended 放在 extends 最后
  • 职责分离:Prettier 负责格式,ESLint 负责质量
  • 统一团队配置,提交到版本控制

参考资源

posted @ 2025-12-03 16:49  一尘子!  阅读(2)  评论(0)    收藏  举报
Live2D
返回顶端