格式和风格规范
VUP 项目采用统一的代码格式和风格规范,确保团队协作的一致性和代码质量。本指南详细介绍了项目中使用的所有格式化和代码质量工具及其配置。
工具概览
VUP 项目使用以下工具来保证代码质量和格式统一:
- ESLint - 代码质量检查和最佳实践
- Prettier - 代码格式化
- TypeScript - 类型检查和编译
- Tailwind CSS - 样式框架
- PostCSS - CSS 后处理器
- VSCode - 编辑器配置和插件
ESLint 配置
基础配置
项目使用 @antfu/eslint-config
- 由 Anthony Fu 开发的现代化、有主见的 ESLint 配置:
javascript
// eslint.config.js
import antfu from '@antfu/eslint-config';
export default antfu({
// 基础配置
typescript: true,
vue: true,
stylistic: false,
// 项目特定覆盖
overrides: [
// Vue 项目配置
{
files: ['apps/vue-template/**/*.{js,ts,vue}'],
rules: {
// Vue 特定规则
},
},
// Nuxt 项目配置
{
files: ['apps/nuxt-template/**/*.{js,ts,vue}'],
rules: {
'no-undef': 'off', // Nuxt 全局函数
},
},
// 配置文件
{
files: [
'**/*.config.{js,ts}',
'**/vite.config.*',
'**/nuxt.config.*',
'**/tailwind.config.*',
],
rules: {
'no-undef': 'off',
},
},
],
// 忽略模式
ignores: [
'**/node_modules/**',
'**/dist/**',
'**/build/**',
'**/.nuxt/**',
'**/.output/**',
'**/.nitro/**',
'**/.vitepress/cache/**',
'**/.wxt/**',
],
});
主要特性
@antfu/eslint-config
提供:
- TypeScript 支持 - 完整的 TypeScript 集成和严格规则
- Vue 3 支持 - 针对 Vue 3 Composition API 优化
- 现代 JavaScript - ES2022+ 特性和最佳实践
- 自动导入支持 - 与 unplugin-auto-import 配合使用
- 最小化配置 - 有主见的默认值,最少配置即可
- 性能优化 - 快速 linting,最小开销
配置选项
配置支持多种选项:
javascript
export default antfu({
// 启用 TypeScript 支持
typescript: true,
// 启用 Vue 支持
vue: true,
// 禁用样式规则(使用 Prettier 代替)
stylistic: false,
// 启用格式化器
formatters: true,
// 启用 unocss 支持
unocss: true,
// 自定义规则
rules: {
// 覆盖特定规则
},
});
Prettier 配置
基础配置
javascript
// prettier.config.js
export default {
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
printWidth: 100,
endOfLine: 'lf',
bracketSameLine: false,
overrides: [
{
files: '*.md',
options: {
printWidth: 80,
proseWrap: 'always',
},
},
],
};
配置说明
- semi:
true
- 使用分号 - singleQuote:
true
- 使用单引号 - tabWidth:
2
- 缩进宽度为2个空格 - trailingComma:
"es5"
- 在ES5中有效的地方添加尾随逗号 - printWidth:
100
- 行宽限制为100字符 - endOfLine:
"lf"
- 使用LF换行符 - bracketSameLine:
false
- 多行JSX元素的>
放在下一行
Markdown 特殊配置
javascript
// Markdown文件特殊处理
{
files: "*.md",
options: {
printWidth: 80, // 行宽限制为80字符
proseWrap: "always", // 总是换行
},
}
TypeScript 配置
根配置
json
// tsconfig.json
{
"extends": "@tsconfig/node18/tsconfig.json",
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"removeComments": false,
"noImplicitAny": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"resolveJsonModule": true,
"isolatedModules": true,
"baseUrl": "."
},
"exclude": [
"node_modules",
"dist",
"build",
"**/.nuxt/**",
"**/.output/**",
"**/.nitro/**",
"**/.vitepress/cache/**",
"**/.wxt/**"
]
}
应用配置
json
// apps/*/tsconfig.json
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./.output",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@shared/*": ["../../_shared/*"]
}
},
"include": [
"src/**/*",
"src/**/*.vue",
"src/*.vue",
"./auto-imports.d.ts",
"src/vue-shim.d.ts"
]
}
Tailwind CSS 配置
基础配置
javascript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./apps/**/*.{vue,js,ts,jsx,tsx,html}',
'./packages/**/*.{vue,js,ts,jsx,tsx,html}',
'./_shared/**/*.{vue,js,ts,jsx,tsx,html}',
'./apps/vitepress-template/.vitepress/theme/**/*.{vue,js,ts,jsx,tsx,html}',
'./apps/vitepress-template/src/**/*.{vue,js,ts,jsx,tsx,html,md}',
'./index.html',
],
theme: {},
plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')],
};
插件说明
- @tailwindcss/forms - 表单样式重置和增强
- @tailwindcss/typography - 排版样式插件
PostCSS 配置
javascript
// postcss.config.js
export default {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {},
},
};
插件说明
- postcss-import - 支持@import语法
- tailwindcss - Tailwind CSS处理器
- autoprefixer - 自动添加浏览器前缀
VSCode 配置
编辑器设置
json
// .vscode/settings.json
{
"editor.codeActionsOnSave": {
"source.organizeImports": "never",
"source.removeUnusedImports": "never",
"source.fixAll.eslint": "never"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSaveMode": "file",
"editor.tabSize": 2,
"files.eol": "\n",
"typescript.preferences.importModuleSpecifier": "relative",
"scss.lint.unknownAtRules": "ignore",
"eslint.enable": true,
"eslint.validate": ["javascript", "typescript", "vue"],
"eslint.workingDirectories": [".", "apps/*"],
"typescript.preferences.includePackageJsonAutoImports": "auto",
"typescript.suggest.autoImports": true,
"typescript.updateImportsOnFileMove.enabled": "always",
"typescript.preferences.organizeImports": {
"enabled": false
}
}
推荐插件
json
// .vscode/extensions.json
{
"recommendations": [
"esbenp.prettier-vscode",
"dbaeumer.vscode-eslint",
"ms-vscode.vscode-typescript-next",
"ms-vscode.vscode-json",
"bradlc.vscode-tailwindcss",
"vue.volar",
"pflannery.vscode-versionlens"
]
}
插件说明
- esbenp.prettier-vscode - Prettier格式化插件
- dbaeumer.vscode-eslint - ESLint代码检查插件
- ms-vscode.vscode-typescript-next - TypeScript支持
- ms-vscode.vscode-json - JSON文件支持
- bradlc.vscode-tailwindcss - Tailwind CSS智能提示
- vue.volar - Vue 3语言服务
- pflannery.vscode-versionlens - 版本号显示
脚本命令
根目录脚本
json
// package.json
{
"scripts": {
"dev:all": "pnpm --filter '*' dev",
"build:all": "pnpm --filter '*' build",
"lint:all": "pnpm --filter '*' lint",
"lint:fix:all": "pnpm --filter '*' lint:fix",
"format:all": "pnpm --filter '*' format",
"format:check:all": "pnpm --filter '*' format:check",
"type-check:all": "pnpm --filter '*' type-check",
"prepare": "husky",
"changeset": "changeset",
"version-packages": "changeset version",
"deploy": "vercel --prod",
"deploy:preview": "vercel"
}
}
应用脚本
json
// apps/*/package.json
{
"scripts": {
"dev": "vite",
"build": "tsc --noEmit && vite build",
"lint": "eslint src/ --ext .vue,.ts,.js",
"lint:fix": "eslint src/ --ext .vue,.ts,.js --fix",
"format": "prettier --write \"src/**/*.{js,ts,vue,json,css,scss}\"",
"format:check": "prettier --check \"src/**/*.{js,ts,vue,json,css,scss}\""
}
}
使用指南
开发时格式化
bash
# 格式化所有文件
pnpm format
# 检查格式是否正确
pnpm format:check
# 修复ESLint问题
pnpm lint:fix
提交前检查
项目配置了 Husky Git hooks,在提交前自动运行:
bash
# pre-commit hook 会自动运行
git add .
git commit -m "feat: add new feature"
# 自动执行: pnpm lint-staged
类型检查
bash
# 检查TypeScript类型
pnpm type-check
# 构建时也会进行类型检查
pnpm build
最佳实践
1. 代码风格
- 使用单引号而不是双引号
- 使用2个空格缩进
- 行宽限制为100字符
- 使用尾随逗号
- 使用分号
2. 导入顺序
javascript
// 正确的导入顺序
import { ref, computed } from 'vue'; // 1. 内置模块
import { defineStore } from 'pinia'; // 2. 外部依赖
import { useRouter } from 'vue-router'; // 3. 外部依赖
import { api } from '@/utils/api'; // 4. 内部模块
import { formatDate } from '@/utils/date'; // 5. 内部模块
import type { User } from '@/types/user'; // 6. 类型导入
3. Vue 组件
vue
<template>
<div class="container">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
interface Props {
title: string;
description?: string;
}
const props = withDefaults(defineProps<Props>(), {
description: '',
});
const isVisible = ref(true);
const displayTitle = computed(() => props.title.toUpperCase());
</script>
<style scoped>
.container {
@apply p-4 bg-white rounded-lg shadow-md;
}
</style>
4. TypeScript 类型
typescript
// 使用明确的类型定义
interface User {
id: number;
name: string;
email: string;
createdAt: Date;
}
// 使用类型导入
import type { User } from '@/types/user';
// 使用泛型
function createApi<T>(url: string): Promise<T> {
return fetch(url).then((res) => res.json());
}
依赖
ESLint 依赖
json
{
"devDependencies": {
"@antfu/eslint-config": "^5.4.1",
"eslint": "^9.34.0"
}
}
关键依赖
- @antfu/eslint-config - 现代化、有主见的 ESLint 配置
- eslint - JavaScript/TypeScript 代码检查工具
- prettier - 代码格式化工具
- typescript - TypeScript 编译器
- vue-tsc - Vue TypeScript 检查器