ESLint

ESLint 是 JavaScript 和 TypeScript 的代码检查工具,用于发现和修复代码中的问题。

安装与配置

1
2
3
4
5
6
7
8
# 安装 ESLint
bun add -d eslint

# 初始化配置(交互式)
bunx eslint --init

# 或手动安装推荐的配置
bun add -d eslint @eslint/js typescript-eslint

ESLint v9+ 扁平配置

ESLint v9 使用新的扁平配置文件 eslint.config.js

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import vue from 'eslint-plugin-vue';
import react from 'eslint-plugin-react';
import importPlugin from 'eslint-plugin-import';
import unusedImports from 'eslint-plugin-unused-imports';

export default [
// 全局配置
{
files: ['**/*.{js,mjs,cjs,ts,jsx,tsx,vue}'],
languageOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
globals: {
browser: true,
es2021: true,
node: true,
},
},
},

// JavaScript 推荐规则
js.configs.recommended,

// TypeScript 推荐规则
...tseslint.configs.recommended,

// Vue 推荐规则
...vue.configs['flat/recommended'],

// React 配置(如果使用 React)
{
files: ['**/*.{jsx,tsx}'],
...react.configs.flat.recommended,
settings: {
react: {
version: 'detect',
},
},
},

// 导入规则
{
plugins: {
import: importPlugin,
'unused-imports': unusedImports,
},
rules: {
'import/order': ['error', {
groups: [
'builtin',
'external',
'internal',
'parent',
'sibling',
'index',
],
'newlines-between': 'always',
}],
'import/no-duplicates': 'error',
'unused-imports/no-unused-imports': 'error',
},
},

// 自定义规则
{
rules: {
// 通用规则
'no-console': ['warn', { allow: ['warn', 'error'] }],
'no-debugger': 'warn',
'no-unused-vars': 'off', // 使用 TypeScript 的规则

// TypeScript 规则
'@typescript-eslint/no-unused-vars': ['error', {
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
}],
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'warn',

// Vue 规则
'vue/multi-word-component-names': 'off',
'vue/no-v-html': 'warn',
'vue/require-default-prop': 'off',
'vue/attribute-hyphenation': ['error', 'always'],
'vue/v-on-event-hyphenation': ['error', 'always'],

// React 规则
'react/react-in-jsx-scope': 'off',
'react/prop-types': 'off',
},
},

// 忽略文件
{
ignores: [
'dist/**',
'node_modules/**',
'coverage/**',
'*.min.js',
'.output/**',
],
},
];

常用规则分类

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
26
27
28
29
// 代码质量规则
rules: {
// 错误处理
'nothrowliteralerror': 'error',
'no-unsafe-finally': 'error',

// 最佳实践
'curly': ['error', 'multi-line'],
'eqeqeq': ['error', 'always'],
'no-eval': 'error',
'no-implied-eval': 'error',
'no-new-func': 'error',
'no-return-await': 'error',

// 变量
'no-shadow': 'error',
'no-use-before-define': ['error', { functions: false }],

// 函数
'consistent-return': 'error',
'no-func-assign': 'error',

// 类
'no-class-assign': 'error',
'no-const-assign': 'error',

// 模块化
'no-duplicate-imports': 'error',
}

运行 ESLint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 检查所有文件
# 检查所有文件
bunx eslint .

# 检查特定目录
bunx eslint src/

# 检查特定文件
bunx eslint src/main.ts src/App.vue

# 自动修复
bunx eslint . --fix
bunx eslint src/ --fix

# 输出格式
bunx eslint . --format json
bunx eslint . --format stylish

# 使用缓存
bunx eslint . --cache --cache-location .eslintcache

与 IDE 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// .vscode/settings.json
{
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"vue"
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.options": {
"extensions": [".js", ".jsx", ".ts", ".tsx", ".vue"]
}
}

Prettier

Prettier 是代码格式化工具,确保代码风格统一。

安装与配置

1
2
3
4
5
6
# 安装 Prettier
# 安装 Prettier
bun add -d prettier

# 安装 ESLint 与 Prettier 的集成
bun add -d eslint-config-prettier eslint-plugin-prettier

Prettier 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"useTabs": false,
"trailingComma": "es5",
"printWidth": 100,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf",
"htmlWhitespaceSensitivity": "css",
"jsxSingleQuote": false,
"bracketSameLine": false,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"semi": true,
"singleAttributePerLine": false,
"vueIndentScriptAndStyle": true
}
1
2
3
4
5
6
7
8
9
10
// .prettierignore
dist
node_modules
coverage
public
*.min.js
*.min.css
pnpm-lock.yaml
yarn.lock
bun.lockb

与 ESLint 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// eslint.config.js
import prettier from 'eslint-plugin-prettier/recommended';

export default [
// 其他配置...

// Prettier 配置(必须放在最后)
prettier,

// 或者手动配置
{
plugins: {
prettier: prettierPlugin,
},
rules: {
'prettier/prettier': 'error',
// 关闭与 Prettier 冲突的规则
'arrow-body-style': 'off',
'prefer-arrow-callback': 'off',
},
},
];
1
2
3
4
5
6
7
8
9
// 使用 eslint-config-prettier 关闭冲突规则
import eslintConfigPrettier from 'eslint-config-prettier';

export default [
// 其他配置...

// 放在最后,关闭所有与 Prettier 冲突的 ESLint 规则
eslintConfigPrettier,
];

运行 Prettier

1
2
3
4
5
6
7
8
9
10
11
12
# 格式化所有文件
bunx prettier --write .

# 格式化特定目录
bunx prettier --write src/

# 检查格式(不修改文件)
bunx prettier --check .
bunx prettier --check src/

# 格式化特定文件
bunx prettier --write src/main.ts

与 Git 集成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// package.json
{
"scripts": {
"format": "prettier --write .",
"format:check": "prettier --check .",
"lint": "eslint . --fix",
"lint:check": "eslint ."
},
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{json,css,scss,md}": [
"prettier --write"
]
}
}
1
2
3
4
5
6
7
8
# 安装 lint-staged 和 husky
bun add -d lint-staged husky

# 初始化 husky
bunx husky init

# 在 .husky/pre-commit 中添加
bunx lint-staged

Biome

Biome 是一个用 Rust 编写的「一体化」前端工具链,将 Linter 和 Formatter 合并为单个工具,速度远快于 ESLint + Prettier 组合,且无需维护多套配置与插件兼容性。它原生支持 JavaScript、TypeScript、JSX/TSX、JSON、CSS、GraphQL、HTML 等格式,适合作为新项目的主力工具。

安装

1
2
3
4
5
# 安装 Biome
bun add -d @biomejs/biome

# 或使用官方脚手架初始化配置
bunx @biomejs/biome init

配置文件

Biome 使用 biome.json 作为配置文件,单个文件同时管理格式化、Lint 和代码辅助(assist)。

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// biome.json
{
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignore": ["dist/**", "node_modules/**", "coverage/**", "*.min.js"]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"lineEnding": "lf"
},
"linter": {
"enabled": true,
"rules": {
"preset": "recommended",
"style": {
"noNonNullAssertion": "warn",
"useImportType": "error"
},
"suspicious": {
"noExplicitAny": "warn",
"noConsoleLog": "warn"
},
"correctness": {
"noUnusedVariables": "error"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"semicolons": "always",
"trailingCommas": "es5",
"arrowParentheses": "always",
"jsxQuoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"recommended": true
}
}
}
}

Biome v2 中 organizeImports 已并入 assist 系统,通过 assist.actions.source 启用导入排序等安全动作;linter.rules.recommended 改用 linter.rules.preset(取值 recommended / all / none)。

运行 Biome

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 检查(Lint + 格式化检查合一)
bunx biome check .

# 检查并自动修复(格式化 + 安全的 Lint 修复)
bunx biome check --write .

# 仅格式化
bunx biome format --write .
bunx biome format . # 仅检查不写入

# 仅 Lint
bunx biome lint .
bunx biome lint --write . # 应用安全修复

# 检查特定文件
bunx biome check src/main.ts

# CI 友好的报告输出
bunx biome check . --reporter=github

与 Git 集成

1
2
3
4
5
6
7
8
9
10
11
// package.json
{
"scripts": {
"check": "biome check .",
"format": "biome check --write .",
"lint": "biome lint ."
},
"lint-staged": {
"*.{js,jsx,ts,tsx,vue,json,css}": ["biome check --write"]
}
}

与 IDE 集成

1
2
3
4
5
6
7
8
9
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "biomejs.biome",
"editor.codeActionsOnSave": {
"quickfix.biome": "explicit",
"source.organizeImports.biome": "explicit"
}
}

Biome vs ESLint + Prettier

维度ESLint + PrettierBiome
工具数量两个工具 + 多个插件单一工具
性能较慢(JS 实现)极快(Rust 实现)
配置需处理两者冲突统一一份 biome.json
类型感知需 typescript-eslint内置部分支持
生态插件极其丰富插件生态仍在成长

新项目若不依赖大量特殊 ESLint 插件,推荐直接用 Biome 替代 ESLint + Prettier 组合,配置与维护成本显著降低。

Tailwind CSS

Tailwind CSS 是一个功能优先的 CSS 框架,通过实用类快速构建自定义设计。

安装与配置

1
2
3
4
5
# 安装 Tailwind CSS
bun add -d tailwindcss postcss autoprefixer

# 初始化配置
bunx tailwindcss init -p

配置文件

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
// 内容文件(用于扫描使用的类)
content: [
'./index.html',
'./src/**/*.{vue,js,ts,jsx,tsx}',
],

// 主题配置
theme: {
// 扩展默认主题
extend: {
// 颜色
colors: {
'primary': {
50: '#f0f9ff',
100: '#e0f2fe',
200: '#bae6fd',
300: '#7dd3fc',
400: '#38bdf8',
500: '#0ea5e9',
600: '#0284c7',
700: '#0369a1',
800: '#075985',
900: '#0c4a6e',
950: '#082f49',
},
'secondary': '#ff6b6b',
'accent': '#ffd93d',
},

// 字体
fontFamily: {
'sans': ['Inter', 'system-ui', 'sans-serif'],
'serif': ['Merriweather', 'serif'],
'mono': ['Fira Code', 'monospace'],
},

// 字体大小
fontSize: {
'xs': ['0.75rem', { lineHeight: '1rem' }],
'sm': ['0.875rem', { lineHeight: '1.25rem' }],
'base': ['1rem', { lineHeight: '1.5rem' }],
'lg': ['1.125rem', { lineHeight: '1.75rem' }],
'xl': ['1.25rem', { lineHeight: '1.75rem' }],
'2xl': ['1.5rem', { lineHeight: '2rem' }],
'3xl': ['1.875rem', { lineHeight: '2.25rem' }],
'4xl': ['2.25rem', { lineHeight: '2.5rem' }],
'5xl': ['3rem', { lineHeight: '1' }],
},

// 间距
spacing: {
'18': '4.5rem',
'88': '22rem',
'128': '32rem',
},

// 边框半径
borderRadius: {
'4xl': '2rem',
'5xl': '2.5rem',
},

// 阴影
boxShadow: {
'inner-lg': 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
'glow': '0 0 20px rgba(14, 165, 233, 0.5)',
},

// 动画
animation: {
'fade-in': 'fadeIn 0.5s ease-in-out',
'slide-up': 'slideUp 0.3s ease-out',
'bounce-slow': 'bounce 2s infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
},

// 断点
screens: {
'xs': '475px',
'3xl': '1920px',
},

// 过渡时间
transitionDuration: {
'2000': '2000ms',
'3000': '3000ms',
},
},
},

// 插件
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
require('@tailwindcss/container-queries'),
],

// 黑暗模式
darkMode: 'class', // 或 'media'

// 未来警告
future: {
hoverOnlyWhenSupported: true,
},
};

基础样式

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/* src/styles/main.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

/* 自定义基础样式 */
@layer base {
html {
font-family: 'Inter', system-ui, sans-serif;
}

h1 {
@apply text-4xl font-bold text-gray-900 dark:text-white;
}

h2 {
@apply text-3xl font-semibold text-gray-800 dark:text-gray-100;
}

h3 {
@apply text-2xl font-medium text-gray-700 dark:text-gray-200;
}

a {
@apply text-primary-600 hover:text-primary-700 underline;
}

button {
@apply px-4 py-2 rounded-lg font-medium transition-colors;
}
}

/* 自定义组件 */
@layer components {
.btn {
@apply px-4 py-2 rounded-lg font-medium transition-colors;
}

.btn-primary {
@apply btn bg-primary-600 text-white hover:bg-primary-700;
}

.btn-secondary {
@apply btn bg-gray-200 text-gray-900 hover:bg-gray-300 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600;
}

.btn-outline {
@apply btn border-2 border-primary-600 text-primary-600 hover:bg-primary-600 hover:text-white;
}

.card {
@apply bg-white rounded-lg shadow-md p-6 dark:bg-gray-800;
}

.input {
@apply w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary-500 dark:bg-gray-700 dark:border-gray-600;
}

.container-custom {
@apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
}
}

/* 自定义工具类 */
@layer utilities {
.text-gradient {
@apply bg-gradient-to-r from-primary-500 to-secondary-500 bg-clip-text text-transparent;
}

.glass {
@apply bg-white/10 backdrop-blur-lg border border-white/20;
}

.hide-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}

.hide-scrollbar::-webkit-scrollbar {
display: none;
}
}

常用类名示例

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<!-- 布局 -->
<div class="flex items-center justify-between">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="container mx-auto px-4">
<div class="space-y-4">
<div class="divide-y divide-gray-200">

<!-- 间距 -->
<div class="m-4 p-4">
<div class="mx-auto my-4">
<div class="mt-4 mb-4 ml-4 mr-4">
<div class="pt-4 pb-4 pl-4 pr-4">
<div class="gap-4 space-x-4 space-y-4">

<!-- 尺寸 -->
<div class="w-full w-1/2 w-64 h-full h-screen h-96">
<div class="min-w-0 min-h-screen max-w-7xl max-h-96">

<!-- 颜色 -->
<div class="bg-red-500 text-white border-blue-300">
<div class="bg-gradient-to-r from-purple-500 to-pink-500">
<div class="text-gray-900 text-opacity-50">

<!-- 排版 -->
<div class="text-lg font-bold italic underline uppercase tracking-wide">
<div class="text-left text-center text-right">
<div class="leading-tight leading-normal leading-loose">

<!-- 边框 -->
<div class="border border-2 border-red-500 rounded-lg rounded-full">
<div class="border-t border-b border-l-0 border-r-0">
<div class="divide-y divide-gray-200">

<!-- 效果 -->
<div class="shadow-lg shadow-xl shadow-inner">
<div class="opacity-50 opacity-75">
<div class="transition-all duration-300 ease-in-out">
<div class="transform scale-110 rotate-45 translate-x-4">

<!-- 响应式 -->
<div class="w-full md:w-1/2 lg:w-1/3 xl:w-1/4">
<div class="text-sm md:text-base lg:text-lg">
<div class="hidden md:block lg:flex xl:grid">

<!-- 状态 -->
<div class="hover:bg-blue-700 focus:ring-2 active:bg-blue-800">
<div class="disabled:opacity-50 disabled:cursor-not-allowed">
<div class="group-hover:text-white">
<div class="peer-checked:bg-blue-500">

<!-- 黑暗模式 -->
<div class="bg-white dark:bg-gray-800">
<div class="text-black dark:text-white">

<!-- 交互 -->
<div class="cursor-pointer cursor-not-allowed">
<div class="select-none select-text">
<div class="resize-y resize-none">

响应式设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 移动优先设计 -->
<div class="
w-full
sm:w-1/2
md:w-1/3
lg:w-1/4
xl:w-1/5
">

<!-- 隐藏/显示 -->
<div class="hidden md:block">桌面端显示</div>
<div class="block md:hidden">移动端显示</div>

<!-- 响应式间距 -->
<div class="p-4 md:p-6 lg:p-8">
<div class="space-y-4 md:space-y-6 lg:space-y-8">

<!-- 响应式网格 -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">

与框架集成

1
2
3
4
5
6
7
8
9
10
11
12
// Vite + Tailwind CSS
// vite.config.ts
export default defineConfig({
css: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
});
1
2
3
4
5
6
// 使用 @tailwindcss/vite 插件(Tailwind v4+)
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
plugins: [tailwindcss()],
});

JIT 模式

Tailwind CSS v3+ 默认启用 JIT(Just-In-Time)模式,按需生成样式。

1
2
3
4
5
6
7
8
// tailwind.config.js
module.exports = {
// 内容文件(用于扫描使用的类)
content: [
'./src/**/*.{vue,js,ts,jsx,tsx}',
],
// ...
}

插件推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 表单样式
bun add -d @tailwindcss/forms

# 排版样式
bun add -d @tailwindcss/typography

# 宽高比
bun add -d @tailwindcss/aspect-ratio

# 容器查询
bun add -d @tailwindcss/container-queries

# 滚动条
bun add -d tailwind-scrollbar

# 动画
bun add -d tailwindcss-animate
1
2
3
4
5
6
7
8
9
10
// tailwind.config.js
module.exports = {
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
require('@tailwindcss/container-queries'),
require('tailwind-scrollbar'),
],
}

综合配置示例

Vue 3 项目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import vue from 'eslint-plugin-vue';
import prettier from 'eslint-plugin-prettier/recommended';
import eslintConfigPrettier from 'eslint-config-prettier';

export default [
js.configs.recommended,
...tseslint.configs.recommended,
...vue.configs['flat/recommended'],
prettier,
eslintConfigPrettier,
{
rules: {
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
},
},
];
1
2
3
4
5
6
7
8
9
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 100,
"vueIndentScriptAndStyle": true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// package.json
{
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"lint": "eslint . --fix",
"format": "prettier --write ."
},
"lint-staged": {
"*.{vue,js,ts}": ["eslint --fix", "prettier --write"]
}
}

React 项目

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
// eslint.config.js
import js from '@eslint/js';
import tseslint from 'typescript-eslint';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import prettier from 'eslint-plugin-prettier/recommended';
import eslintConfigPrettier from 'eslint-config-prettier';

export default [
js.configs.recommended,
...tseslint.configs.recommended,
{
files: ['**/*.{jsx,tsx}'],
...react.configs.flat.recommended,
plugins: {
'react-hooks': reactHooks,
},
rules: {
...reactHooks.configs.recommended.rules,
'react/react-in-jsx-scope': 'off',
},
},
prettier,
eslintConfigPrettier,
];

完整项目模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 创建项目
bun create vite my-app --template vue-ts
cd my-app

# 安装开发工具
bun add -d eslint @eslint/js typescript-eslint eslint-plugin-vue
bun add -d prettier eslint-plugin-prettier eslint-config-prettier
bun add -d tailwindcss postcss autoprefixer @tailwindcss/forms @tailwindcss/typography
bun add -d lint-staged husky

# 初始化配置
bunx tailwindcss init -p
bunx husky init

# 创建配置文件
touch eslint.config.js .prettierrc .prettierignore

# 配置 lint-staged
# 在 package.json 中添加 lint-staged 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// package.json
{
"scripts": {
"dev": "vite",
"build": "vue-tsc && vite build",
"lint": "eslint . --fix",
"format": "prettier --write .",
"prepare": "husky"
},
"lint-staged": {
"*.{vue,js,ts}": ["eslint --fix", "prettier --write"],
"*.{json,css,md}": ["prettier --write"]
}
}
1
2
# .husky/pre-commit
bunx lint-staged