文章目录
-
-
- [**1. 引言:为什么需要编码规范?**](#1. 引言:为什么需要编码规范?)
- [**2. 三大神器概览**](#2. 三大神器概览)
-
- [**2.1 核心分工与协作流程图**](#2.1 核心分工与协作流程图)
- [**2.2 各自的核心定位**](#2.2 各自的核心定位)
- [**3. TypeScript:JavaScript 的超集**](#3. TypeScript:JavaScript 的超集)
-
- [**3.1 什么是 TypeScript?**](#3.1 什么是 TypeScript?)
- [**3.2 实战示例:从 JavaScript 到 TypeScript**](#3.2 实战示例:从 JavaScript 到 TypeScript)
- [**3.3 TypeScript 配置 (tsconfig.json)**](#3.3 TypeScript 配置 (tsconfig.json))
- [**4. ESLint:代码质量检查工具**](#4. ESLint:代码质量检查工具)
-
- [**4.1 什么是 ESLint?**](#4.1 什么是 ESLint?)
- [**4.2 实战示例:ESLint 规则与自动修复**](#4.2 实战示例:ESLint 规则与自动修复)
- [**4.3 ESLint 命令行使用**](#4.3 ESLint 命令行使用)
- [**5. Prettier:代码格式化工具**](#5. Prettier:代码格式化工具)
-
- [**5.1 什么是 Prettier?**](#5.1 什么是 Prettier?)
- [**5.2 实战示例:Prettier 格式化效果**](#5.2 实战示例:Prettier 格式化效果)
- [**5.3 Prettier 命令行使用**](#5.3 Prettier 命令行使用)
- [**6. 完美协作:集成到开发工作流**](#6. 完美协作:集成到开发工作流)
-
- [**6.1 编辑器配置 (VS Code)**](#6.1 编辑器配置 (VS Code))
- [**6.2 完整的开发流程集成**](#6.2 完整的开发流程集成)
- [**6.3 Git Hooks 集成**](#6.3 Git Hooks 集成)
- [**7. 完整项目配置示例**](#7. 完整项目配置示例)
-
- [**7.1 项目目录结构**](#7.1 项目目录结构)
- [**7.2 完整的配置文件**](#7.2 完整的配置文件)
- [**8. 总结:三大神器的协同效应**](#8. 总结:三大神器的协同效应)
-
1. 引言:为什么需要编码规范?
在大型前端项目中,随着团队规模的扩大和代码量的增长,我们会面临诸多挑战:
- 代码一致性:不同开发者的编码风格各异,导致代码库像"补丁集合"。
- 潜在错误:JavaScript 的动态类型特性使得很多错误在运行时才能被发现。
- 维护成本:混乱的代码结构和隐藏的 Bug 使得代码难以阅读和维护。
- 协作效率:在代码审查中需要花费大量时间讨论代码风格问题。
为了解决这些问题,现代前端开发形成了以 TypeScript 、ESLint 、Prettier 为核心的工具链,它们各司其职,共同构建了健壮的代码质量保障体系。
2. 三大神器概览
2.1 核心分工与协作流程图
为了直观理解这三者的关系和它们在开发流程中的分工,我们先通过下面的流程图来建立整体认知:
Yes No Yes No 开发者编写代码 TypeScript 类型检查 类型错误? 修复类型错误 ESLint 代码质量检查 代码质量问题? ESLint 自动修复 Prettier 代码格式化 保存文件/提交代码 获得规范
整洁的代码
2.2 各自的核心定位
- TypeScript :类型安全卫士 - 在编码阶段捕获类型相关的错误。
- ESLint :代码质量检察官 - 发现并修复代码中的潜在问题和不良模式。
- Prettier :代码格式化专家 - 自动统一代码风格,让代码看起来一致美观。
3. TypeScript:JavaScript 的超集
3.1 什么是 TypeScript?
TypeScript 是由 Microsoft 开发和维护的编程语言,它是 JavaScript 的一个超集,主要提供了静态类型系统 和对ECMAScript 新特性的支持。
核心价值:
- 类型安全:在编译时发现类型错误,减少运行时错误。
- 更好的开发体验:智能代码补全、接口提示、重构支持。
- 代码可维护性:类型声明即文档,便于理解和维护。
3.2 实战示例:从 JavaScript 到 TypeScript
改造前:脆弱的 JavaScript 代码
javascript
// user.js
export function getUserInfo(user) {
return {
name: user.name,
age: user.age,
email: user.email
};
}
// 调用时可能出现各种问题
const userInfo = getUserInfo({ name: "Alice" }); // age 和 email 是 undefined
console.log(userInfo.age + 1); // NaN,运行时才会报错
const result = getUserInfo(null); // 运行时崩溃:Cannot read properties of null
改造后:类型安全的 TypeScript 代码
typescript
// user.ts
// 1. 定义明确的接口
interface User {
id: number;
name: string;
age: number;
email: string;
phone?: string; // 可选属性
}
interface UserInfo {
name: string;
age: number;
email: string;
}
// 2. 类型化的函数
export function getUserInfo(user: User): UserInfo {
return {
name: user.name,
age: user.age,
email: user.email
};
}
// 3. 安全的函数调用
const user: User = {
id: 1,
name: "Alice",
age: 25,
email: "alice@example.com"
};
const userInfo = getUserInfo(user);
console.log(userInfo.age + 1); // 26,类型安全
// 4. 编译时错误检测
// const result = getUserInfo(null);
// 错误: Argument of type 'null' is not assignable to parameter of type 'User'
// const result2 = getUserInfo({ name: "Bob" });
// 错误: Missing properties: id, age, email
// 5. 高级类型功能
type PartialUser = Partial<User>; // 所有属性变为可选
type UserWithoutId = Omit<User, 'id'>; // 排除 id 属性
const updateUser = (id: number, updates: PartialUser): void => {
// 更新用户逻辑
};
// 6. 泛型支持
interface ApiResponse<T> {
data: T;
code: number;
message: string;
}
const userResponse: ApiResponse<User> = {
data: user,
code: 200,
message: "success"
};
3.3 TypeScript 配置 (tsconfig.json)
json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"allowJs": true,
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true, // 与构建工具配合时使用
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts"
]
}
4. ESLint:代码质量检查工具
4.1 什么是 ESLint?
ESLint 是一个静态代码分析工具,用于识别和报告 JavaScript/TypeScript 代码中的模式问题。它通过规则来定义什么是"好代码"。
核心价值:
- 发现潜在错误:未使用的变量、可能的空指针等。
- 强制编码规范:命名约定、代码组织等。
- 保持代码一致性:在整个项目中保持统一的代码风格。
4.2 实战示例:ESLint 规则与自动修复
.eslintrc.js 配置文件
javascript
module.exports = {
root: true,
parser: '@typescript-eslint/parser', // TypeScript 解析器
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module',
project: './tsconfig.json'
},
plugins: [
'@typescript-eslint',
'import',
'prettier'
],
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'prettier' // 禁用与 Prettier 冲突的规则
],
rules: {
// TypeScript 规则
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/prefer-const': 'error',
// ES6+ 规则
'prefer-arrow-callback': 'error',
'no-var': 'error',
// 导入/导出规则
'import/order': [
'error',
{
'groups': [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index'
],
'newlines-between': 'always'
}
],
// 代码质量规则
'no-console': 'warn',
'no-debugger': 'error',
'eqeqeq': ['error', 'always'],
// Prettier 集成
'prettier/prettier': 'error'
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true
}
}
},
env: {
browser: true,
node: true,
es6: true
}
};
ESLint 检查示例
typescript
// 有问题的代码 (problematic-code.ts)
var myName = "Alice"; // ESLint: 使用 'let' 或 'const' 代替 'var'
console.log("Hello"); // ESLint: 意外的 console 语句
function getUser(id) { // ESLint: 缺少返回类型注解
if (id = null) { // ESLint: 条件中使用了赋值操作符
return null;
}
let data; // ESLint: 'data' 已定义但未使用
return {
name: "Alice",
age: 25
};
}
interface Options {
timeout?: number;
}
function fetchData(options: any) { // ESLint: 避免使用 `any` 类型
// ...
}
// 自动修复后的代码
const myName = "Alice";
function getUser(id: number | null): { name: string; age: number } | null {
if (id === null) {
return null;
}
return {
name: "Alice",
age: 25
};
}
function fetchData(options: Options): void {
// ...
}
4.3 ESLint 命令行使用
bash
# 检查代码
npx eslint src/**/*.{js,ts}
# 检查并自动修复
npx eslint src/**/*.{js,ts} --fix
# 生成报告
npx eslint src/**/*.{js,ts} -f json -o eslint-report.json
5. Prettier:代码格式化工具
5.1 什么是 Prettier?
Prettier 是一个"有主见"的代码格式化工具,它通过解析代码并按照统一的规则重新打印代码,强制保持一致的代码风格。
核心价值:
- 结束风格争论:团队不再需要讨论代码风格细节。
- 自动格式化:保存时自动格式化,提高开发效率。
- 支持多种语言:JavaScript、TypeScript、CSS、HTML、JSON 等。
5.2 实战示例:Prettier 格式化效果
.prettierrc.js 配置文件
javascript
module.exports = {
// 一行最多多少个字符
printWidth: 100,
// 使用 2 个空格缩进
tabWidth: 2,
// 不使用 tab 缩进,而使用空格
useTabs: false,
// 行尾需要有分号
semi: true,
// 使用单引号代替双引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: 'as-needed',
// jsx 使用单引号代替双引号
jsxSingleQuote: true,
// 末尾不需要逗号
trailingComma: 'es5',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: 'always',
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// 换行符使用 lf
endOfLine: 'lf'
};
格式化前后对比
typescript
// 格式化前的代码 (格式混乱)
const user={id:1,name:"Alice",age:25,email:"alice@example.com",phone:"12345678901"};
function getUserInfo
(user){
const {id,name,age,email,phone}=user;
return{id,name,age,email,phone};}
const numbers=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25];
// 格式化后的代码 (整洁统一)
const user = {
id: 1,
name: 'Alice',
age: 25,
email: 'alice@example.com',
phone: '12345678901',
};
function getUserInfo(user) {
const { id, name, age, email, phone } = user;
return { id, name, age, email, phone };
}
const numbers = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
];
5.3 Prettier 命令行使用
bash
# 检查代码格式
npx prettier --check src/
# 格式化所有文件
npx prettier --write src/
# 格式化指定文件
npx prettier --write src/components/Button.tsx
6. 完美协作:集成到开发工作流
6.1 编辑器配置 (VS Code)
.vscode/settings.json
json
{
// TypeScript 配置
"typescript.preferences.importModuleSpecifier": "relative",
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.suggest.autoImports": true,
// ESLint 配置
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.codeAction.showDocumentation": {
"enable": true
},
"eslint.format.enable": true,
// Prettier 配置
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.organizeImports": true
},
// 文件关联
"files.associations": {
"*.tsx": "typescriptreact",
"*.ts": "typescript"
}
}
6.2 完整的开发流程集成
package.json 脚本配置
json
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint src/**/*.{js,ts,tsx} --fix",
"lint:check": "eslint src/**/*.{js,ts,tsx}",
"format": "prettier --write src/**/*.{js,ts,tsx,json,css,md}",
"format:check": "prettier --check src/**/*.{js,ts,tsx,json,css,md}",
"type-check": "tsc --noEmit",
"validate": "npm run type-check && npm run lint:check && npm run format:check",
"prepare": "husky install"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"@typescript-eslint/typescript-estree": "^5.0.0",
"eslint": "^8.0.0",
"eslint-config-prettier": "^8.0.0",
"eslint-plugin-import": "^2.25.0",
"eslint-plugin-prettier": "^4.0.0",
"prettier": "^2.7.0",
"typescript": "^4.9.0",
"husky": "^8.0.0",
"lint-staged": "^13.0.0"
}
}
6.3 Git Hooks 集成
lint-staged 配置
javascript
// lint-staged.config.js
module.exports = {
'*.{js,ts,tsx}': [
'eslint --fix',
'prettier --write'
],
'*.{json,md,html,css,scss}': [
'prettier --write'
]
};
Husky 配置
bash
# .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx lint-staged
npx tsc --noEmit
# .husky/pre-push
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run validate
npm run build
7. 完整项目配置示例
7.1 项目目录结构
my-project/
├── .vscode/
│ └── settings.json
├── .husky/
│ ├── pre-commit
│ └── pre-push
├── src/
│ ├── components/
│ │ └── Button.tsx
│ ├── utils/
│ │ └── api.ts
│ └── App.tsx
├── .eslintrc.js
├── .eslintignore
├── .prettierrc.js
├── .prettierignore
├── tsconfig.json
├── package.json
└── lint-staged.config.js
7.2 完整的配置文件
.eslintignore
node_modules/
dist/
build/
*.min.js
*.bundle.js
coverage/
.prettierignore
node_modules/
dist/
build/
package-lock.json
yarn.lock
*.min.js
coverage/
8. 总结:三大神器的协同效应
通过本文的详细讲解,我们可以看到 TypeScript、ESLint 和 Prettier 如何各司其职又完美协作:
- TypeScript 提供类型安全,在编码阶段捕获错误。
- ESLint 检查代码质量,发现潜在问题和不良模式。
- Prettier 统一代码风格,结束无意义的格式争论。
它们共同构建了一个强大的质量保障体系:
- 开发阶段:编辑器实时提示 + 保存时自动修复
- 提交阶段:Git Hooks 自动检查,阻止不规范代码进入仓库
- 构建阶段:CI/CD 流水线进行最终验证
最佳实践建议:
- 渐进式采用:可以先从 Prettier 开始,逐步引入 ESLint 和 TypeScript。
- 团队共识:工具配置需要团队成员共同讨论决定。
- 持续优化:根据项目发展定期回顾和调整规则配置。
- 自动化一切:将检查流程集成到开发工作流的各个环节。
通过正确配置和使用这三大工具,你的团队可以显著提升代码质量、开发效率和协作体验,让开发者能够更专注于业务逻辑而不是代码风格问题。
