前端学习笔记——Vite + Vue 3 + TypeScript + Vue Router 4 + Pinia + Element Plus + Axios 项目从 0 到 1 的环境搭建 - 实践
前端学习笔记——Vite + Vue 3 项目从 0 到 1 的环境搭建
技术栈:Vite + Vue 3 + TypeScript + Vue Router 4 + Pinia + Element Plus + Axios + Echarts + Vue-ECharts + Sass + Tailwind CSS + unplugin-auto-import + unplugin-vue-components + Pritter + ESLint + Commitlint + Husky + Stylelint
用于从零开始搭建初始化项目
在为毕设项目做准备,因为技术栈更多了,要从头从零完整搭一遍,就有了这篇笔记,刚好也可以为大家提供一个参考因为是一个一个依赖配置和验证,大家可以选择自己需要的即可
2025年11月4日 完成 Vite + Vue 3 + TypeScript + Vue Router 4 + Pinia
2025年11月6日 完成 Element Plus + Axios + Echarts + Vue-ECharts + Sass + Tailwind CSS + unplugin-auto-import + unplugin-vue-components
2025年11月7日 完成 Pritter + ESLint
2025年11月8日 完成 Husky + Commitlint
2025年11月9日 完成 Stylelint
零、前言
1. 常见问题汇总
1.1 @/* 报错
一、初始准备
1. 环境安装
1.1 安装 Node.js
安装:
安装教程略,后面再补
验证:
# 检查 Node.js 版本
node -v
- 成功:显示版本号
- 失败:其它情况
1.2 安装 pnpm
安装:
# 安装 pnpm
npm install -g pnpm
验证:
# 检查 pnpm 版本
pnpm -v
- 成功:显示版本号
- 失败:其它情况
2. 创建项目
安装:
# 使用 Vite 创建项目
pnpm create vite project-name --template vue-ts
配置:
Use rolldown-vite (Experimental)?
No
Install with pnpm and start now?
No
验证:
# 进入项目目录
cd project-name
# 安装基础依赖
pnpm install
# 启动项目
pnpm run dev
- 成功:项目启动,浏览器访问
http://localhost:5173,能看到 Vue 欢迎页面 - 失败:其它情况
二、核心依赖
1. 路由管理 (Vue Router 4)
安装:
# 安装 Vue Router 4
pnpm add vue-router@4
配置:
- 创建
src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: { title: '首页' },
},
{
path: '/test',
name: 'Test',
component: () => import('@/views/Test.vue'),
meta: { title: '测试页' },
},
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
})
export default router
- 修改
src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
// 导入路由
import router from './router'
const app = createApp(App)
// 使用路由
app.use(router)
app.mount('#app')
- 修改
src/App.vue
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
</script>
- 创建页面
- 创建
src/views/Home.vue
Home Page
- 创建
src/views/Test.vue
Test Page
- 解决报错
- 安装 @types/node
pnpm add -D @types/node
- 修改
vite.config.ts
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
// 配置 @ 指向 src 目录
'@': resolve(__dirname, './src'),
},
},
})
- 修改
tsconfig.json或tsconfig.app.json中的 compilerOptions
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
- 创建
src/vite-env.d.ts
declare module '@/*' {
const value: any
export default value
}
验证:
- 成功:访问
http://localhost:5173和http://localhost:5173/test能切换 Home 和 Test 页面 - 失败:其它情况
2. 状态管理 (Pinia)
安装:
# 安装 Pinia
pnpm add pinia
# 安装状态持久化插件
pnpm add pinia-plugin-persistedstate
配置:
- 创建
src/stores/index.ts
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(persist)
export default pinia
- 修改
src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
// 导入路由
import router from './router'
// 导入状态管理
import pinia from './store'
const app = createApp(App)
// 使用路由
app.use(router)
// 使用状态管理
app.use(pinia)
app.mount('#app')
- 创建
src/stores/user.ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null as { id: string; name: string } | null,
}),
getters: {
getUserInfo: state => state.userInfo,
},
actions: {
setUserInfo(userInfo: any) {
this.userInfo = userInfo
},
},
persist: true,
})
- 修改
src/views/Home.vue
<script setup lang="ts">
import router from '@/router/index'
import { useUserStore } from '@/stores'
const userStore = useUserStore()
// 测试设置用户信息
userStore.setUserInfo({ id: '1', name: '测试用户' })
console.log(userStore.getUserInfo)
</script>
验证:
- 成功:访问首页,F12 控制台能打印用户信息
- 失败:其它情况
3. 清除初始文件
配置:
- 删除文件
- 删除
public/vite.svg和public - 删除
src/assets/vue.svg和src/assets - 删除
src/components/HelloWorld.vue和src/components
- 修改文件
- 修改
src/App.vue
<script setup lang="ts"></script>
- 修改
src/style.css
h1 {
padding: 0;
margin: 0;
color: aqua;
}
#app {
max-width: 1280px;
margin: 0 auto;
padding: 0.75rem;
text-align: center;
}
- 修改
src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
// 导入路由
import router from './router'
// 导入状态管理
import pinia from './stores'
import './style.css'
const app = createApp(App)
// 使用路由
app.use(router)
// 使用状态管理
app.use(pinia)
// 挂载应用
app.mount('#app')
验证:
- 成功:访问首页,能显示居中天蓝色文字
- 失败:其它情况
4. UI组件库 (Element Plus)
安装:
# 安装 Element Plus
pnpm add element-plus
# 安装图标库
pnpm add @element-plus/icons-vue
配置:
- 修改
src/main.ts
// 导入 Element-plus
// 导入 Element-plus图标库
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
// 注册所有图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
// 使用 Element-plus
app.use(ElementPlus)
- 报错解决
- 重启 TypeScript 语言服务器:在 VSCode 中,按下 Ctrl+Shift+P(Windows) /
Cmd+Shift+P(Mac),输入 “TypeScript: Restart TS
Server” 并执行。这是非常关键的一步,能让 IDE 重新加载所有配置。
- 配置中文语言包(可选)
- 修改
src/main.ts
// 导入 Element-plus 中文语言包
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 使用element-plus
app.use(ElementPlus, {
locale: zhCn,
})
验证:
- 修改
src/views/Home.vue
测试按钮
<script setup lang="ts">
// 导入图标
import { Edit } from '@element-plus/icons-vue'
</script>
- 成功:访问首页,能显示 Element Plus 组件和图标
- 失败:其它情况
5. HTTP请求库 (Axios)
安装:
# 安装 Axios
pnpm add axios
配置:
- 创建
src/utils/request.ts
// 这只是示例,更多详细配置,需要自行配置
import axios from 'axios'
const request = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
timeout: 10000,
})
// 请求拦截器
request.interceptors.request.use(
config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
return Promise.reject(error)
}
)
export default request
验证:
- 验证 Axios
- 修改
src/main.ts
// 导入网络请求模块
import axios from 'axios'
console.log('Axios 版本:', axios.VERSION)
- 成功:访问首页,F12 控制台能打印 Axios 版本号
- 失败:其它情况
- 验证 request 模块
- 修改
src/views/Home.vue
<script setup lang="ts">
import { onMounted } from 'vue'
import request from '@/utils/request/request'
const axiosTest = async () => {
console.log('当前token:', localStorage.getItem('token'))
const token = 'token' + Date.now()
localStorage.setItem('token', token)
console.log('设置token:', localStorage.getItem('token'))
try {
// 使用 JSONPlaceholder 的 /posts/1 接口进行测试
const response = await request.get('https://jsonplaceholder.typicode.com/posts/1')
console.log('✅ 接口请求成功!返回数据:', response.data)
} catch (error) {
console.error('❌ 接口请求失败:', error)
}
}
onMounted(() => {
axiosTest()
})
</script>
- 成功:访问首页,F12 控制台能打印 token 和 接口请求信息,检查网络请求可以看到请求的 Authorization 为 Bearer
token1762411976755(token 加当前时间戳) - 失败:其它情况
6. 数据可视化 (ECharts 和 Vue-ECharts)
安装:
# 安装 ECharts 和 Vue-ECharts
pnpm add echarts vue-echarts
配置:
- 创建
src/plugins/echarts.ts
import type { App } from 'vue'
import * as echarts from 'echarts'
import VueECharts from 'vue-echarts'
export default {
install(app: App) {
app.component('v-chart', VueECharts)
app.config.globalProperties.$echarts = echarts
},
}
- 修改
src/main.ts
// 导入 Echarts插件
import echarts from '@/plugins/echarts'
// 使用 Echarts插件
app.use(echarts)
验证:
- 创建
src/components/ChartTest.vue
ECharts 集成测试
<script setup lang="ts">
import { ref } from 'vue'
// 定义一个简单的图表配置选项
const chartOption = ref({
title: {
text: '销量图表',
},
tooltip: {},
xAxis: {
data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子'],
},
yAxis: {},
series: [
{
name: '销量',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
},
],
})
// 定义一个方法来更新图表数据,验证响应式功能
const updateChartData = () => {
chartOption.value.series[0]!.data = [
Math.random() * 40,
Math.random() * 40,
Math.random() * 40,
Math.random() * 40,
Math.random() * 40,
Math.random() * 40,
]
}
</script>
- 修改
src/views/Home.vue
<script setup lang="ts">
// 导入测试组件
import TestChart from '@/components/ChartTest.vue'
</script>
- 成功:访问首页,能显示 ECharts 图表,点击按钮能更新数据
- 失败:其它情况
三、开发工具依赖
1. CSS预处理 (Sass) 和工具类框架 (Tailwind CSS)
安装:
# 安装 Sass 和 Tailwind CSS 相关 (开发依赖)
# sass: CSS 预处理器,支持变量、嵌套、混合等高级特性,增强 CSS 的可维护性
# tailwindcss: 工具类优先的 CSS 框架,用于快速构建自定义用户界面
# @tailwindcss/forms: Tailwind CSS 官方插件,用于为表单元素提供美观的基础样式
# @tailwindcss/typography: Tailwind CSS 官方插件,为不可编辑的 HTML 内容(如富文本)提供精美的 Typography 样式
# autoprefixer: PostCSS 插件,自动为 CSS 规则添加供应商前缀,确保浏览器兼容性
# postcss: CSS 转换工具,是 Autoprefixer 和 Tailwind CSS 运行的基础
pnpm add sass -D
pnpm add tailwindcss@3.4.17 @tailwindcss/forms @tailwindcss/typography -D
pnpm add autoprefixer postcss -D
配置:
- 初始化配置
# 初始化 Tailwind CSS 配置文件
npx tailwindcss init -p
- 配置
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
// 配置 Tailwind 需要扫描的文件路径
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
}
- 修改
src/style.css
@tailwind base;
@tailwind components;
@tailwind utilities;
验证:
- 修改
src/views/Home.vue
Home
- 成功:访问首页,能显示绿色背景、白色文字的标题
- 失败:其它情况
2. 自动导入工具 (unplugin-auto-import 和 unplugin-vue-components)
安装:
# 安装 Vue 生态自动导入插件 (开发依赖)
# unplugin-auto-import: 自动导入 Vue 及相关库的 API(如 ref、computed、useRouter 等),无需手动编写 import 语句,简化代码并提高开发效率
# unplugin-vue-components: 自动按需导入并注册 Vue 组件(包括第三方 UI 库和本地组件),避免手动导入和全局注册的繁琐操作
pnpm add -D unplugin-auto-import unplugin-vue-components
配置:
- 修改
vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
// ...
AutoImport({
imports: ['vue', 'vue-router', 'pinia'],
dts: 'src/auto-imports.d.ts',
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
dts: 'src/components.d.ts',
}),
],
})
验证:
- 修改
src/views/Home.vue
<script setup lang="ts">
// 删除手动导入
// import { onMounted } from "vue";
</script>
- 成功:访问首页,F12 控制台能正常打印
- 失败:其它情况
四、代码质量工具
1. 代码格式化(Prettier)
安装:
# 安装 Prettier 核心 (开发依赖)
# prettier: 代码格式化工具,支持多种语言,通过自动调整缩进、引号、换行等确保代码风格统一
pnpm add -D prettier
# 安装 Prettier 插件 (开发依赖)
# @trivago/prettier-plugin-sort-imports: Prettier 插件,用于自动对 import 语句进行排序和分组,美化导入结构
# prettier-plugin-tailwindcss: Prettier 插件,用于自动排序 Tailwind CSS 的类名,遵循 Tailwind 推荐的类顺序
pnpm add -D @trivago/prettier-plugin-sort-imports
pnpm add -D prettier-plugin-tailwindcss
配置:
- 创建
prettier.config.mjs
/** @type {import('prettier').Config} */
const config = {
// 单行代码的最大宽度,超过此长度将尝试换行
// 推荐值 80-100,适合现代显示器和并排代码查看
printWidth: 100,
// 每个缩进级别的空格数
// 2个空格是Vue/Web项目的常见标准
tabWidth: 2,
// 是否使用制表符(tab)代替空格进行缩进
// false表示使用空格,确保在不同环境下显示一致
useTabs: false,
// 语句末尾是否添加分号
// false表示不加分号,符合现代JavaScript/Vue社区的简洁风格
semi: false,
// 是否使用单引号代替双引号
// true表示使用单引号,在Vue生态中更受欢迎
singleQuote: true,
// 多行时是否在最后一项后添加逗号
// 'es5'表示在ES5允许的地方添加尾随逗号(对象、数组等)
// 这能使git差异更清晰,因为修改一行不会影响上一行
trailingComma: 'es5',
// 在对象字面量的括号之间添加空格
// true示例: { foo: bar },false示例: {foo:bar}
bracketSpacing: true,
// 将多行HTML/JSX元素的闭合括号 `>` 放在最后一行的末尾
// false表示闭合括号单独成行,通常更易读
bracketSameLine: false,
// 箭头函数参数的括号规则
// 'avoid'表示当只有一个参数时省略括号,如 x => x
arrowParens: 'avoid',
// 换行符设置
// 'auto'表示自动检测并维持现有换行符风格(LF或CRLF)
// 避免跨操作系统协作时的换行符问题
endOfLine: 'auto',
// 是否缩进Vue文件中的<script>和<style>标签内的代码
// true表示缩进,保持标签内代码的结构清晰
vueIndentScriptAndStyle: true,
// 引号使用规则
// 'as-needed'表示仅在需要时为对象的key添加引号
quoteProps: 'as-needed',
// JSX中使用单引号
// 与singleQuote设置保持一致
jsxSingleQuote: true,
// HTML空白敏感性设置
// 'css'表示遵循CSS的空白处理规则
htmlWhitespaceSensitivity: 'css',
// 是否对文件顶部有特定注释(@prettier/@format)的文件进行格式化
// false表示无需特殊注释即可格式化所有文件
requirePragma: false,
// 是否在已被Prettier格式化的文件顶部添加特殊标注
// false表示不添加,保持文件简洁
insertPragma: false,
// 文本换行方式
// 'preserve'表示保留原始的换行方式
proseWrap: 'preserve',
// 是否对嵌入的代码(如Markdown中的代码块)进行格式化
// 'auto'表示自动格式化
embeddedLanguageFormatting: 'auto',
// 使用的插件列表
// 注意:prettier-plugin-tailwindcss必须放在最后
plugins: [
'@trivago/prettier-plugin-sort-imports', // 导入语句排序插件
'prettier-plugin-tailwindcss', // Tailwind CSS类名排序插件(必须放在最后)
],
// 导入排序规则配置
importOrder: [
'^vue$', // Vue核心库
'^vue-router$', // Vue路由
'^pinia$', // Vue状态管理
'^@vue/(.*)$', // Vue相关包
'<THIRD_PARTY_MODULES>', // 第三方模块
'^@/(.*)$', // 路径别名@指向的模块
'^~/(.*)$', // 其他路径别名(如有)
'^[./]', // 相对路径导入
],
// 是否在导入分组之间添加空行
// true表示分组间有空行,视觉上更清晰
importOrderSeparation: true,
// 是否对每个导入语句中的命名导入按字母排序
// true表示自动排序,如将 {b, a} 排序为 {a, b}
importOrderSortSpecifiers: true,
// 导入排序时是否忽略大小写
// true表示不区分大小写
importOrderCaseInsensitive: true,
// 针对特定文件类型的覆盖配置
overrides: [
{
files: '*.vue', // Vue单文件组件
options: {
parser: 'vue', // 使用Vue解析器
},
},
{
files: '*.ts', // TypeScript文件
options: {
parser: 'typescript', // 使用TypeScript解析器
},
},
{
files: '*.json', // JSON文件
options: {
parser: 'json', // 使用JSON解析器
tabWidth: 2, // JSON文件缩进
singleQuote: false, // JSON必须使用双引号
},
},
{
files: '*.md', // Markdown文件
options: {
parser: 'markdown', // 使用Markdown解析器
proseWrap: 'always', // 自动换行,提高可读性
},
},
],
}
export default config
- 创建
.prettierignore
# 依赖目录
node_modules/
# 如果使用 pnpm
.pnpm-store/
# 如果使用 Turborepo
.turbo/
# 构建输出目录
dist/
build/
output/
*.min.*
*.bundle.*
# 缓存目录
.cache/
.temp/
tmp/
# 运行时的本地生成文件
# 测试相关输出
coverage/
.nyc_output/
# 日志文件
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# 运行时数据
pids
*.pid
*.seed
*.pid.lock
# 项目配置文件(可选,根据团队习惯决定)
# 有些团队希望配置文件也被格式化以保持风格一致,则可注释掉下面几行
# *.config.js
# *.config.ts
# vite.config.ts
# 自动生成的类型文件或声明文件(可选)
# 如果这些文件是自动生成的,通常不需要格式化
auto-imports.d.ts
components.d.ts
# 版本控制与IDE
.git/
.svn/
.hg/
.idea/
.vscode/
*.swp
*.swo
# 系统文件
.DS_Store
Thumbs.db
# 文档
CHANGELOG*.md
- 配置 VSCode
- 下载 Prettier 插件
- 打开 VSCode 设置
- 搜索 “Format On Save”,勾选 “Editor: Format On Save”
- 搜索 “Default Formatter”,选择 “Prettier - Code formatter”
- 添加插件到工作区建议
- 重启 VSCode 或 打开命令面板(Ctrl+Shift+P),输入 “Reload Window” 重新加载窗口
验证:
- 给
<script>模块添加结尾分号,按保存
- 成功:分号被去除
- 失败:其它情况
- 修改
<h1>标签的 Tailwind CSS 样式,按保存
- 成功:样式顺序被重排
- 失败:其它情况
2. 代码检查工具(ESLint)
安装:
# 安装 ESLint 相关插件和配置 (开发依赖)
# eslint-plugin-vue: Vue.js 官方 ESLint 插件,提供 Vue 单文件组件和模板的语法规则检查
# vue-eslint-parser: 专用于解析 Vue 单文件组件的 ESLint 解析器,确保正确分析 <template> 和 <script> 块
# eslint-config-prettier: 关闭 ESLint 中所有与 Prettier 代码格式化规则冲突的规则,避免两者之间的冲突
# eslint-plugin-prettier: 将 Prettier 作为 ESLint 规则来运行,使代码格式问题在 ESLint 中直接报错
pnpm add -D eslint-plugin-vue vue-eslint-parser eslint-config-prettier eslint-plugin-prettier
# 安装 ESLint 核心、TypeScript 解析与规则支持 (开发依赖)
# eslint: JavaScript 和 TypeScript 静态代码检查工具,用于识别代码中的错误、潜在问题并统一代码风格
# @typescript-eslint/eslint-plugin: 为 TypeScript 代码提供额外的 ESLint 规则集
# @typescript-eslint/parser: ESLint 的解析器,使其能够理解和检查 TypeScript 语法
pnpm add -D eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser
# 安装 ESLint 环境全局变量和基础配置 (开发依赖)
# globals: 提供一组预定义的全局变量(如 browser 的 window、node 的 process),供 ESLint 识别,避免 "no-undef" 错误
# @eslint/js: ESLint 官方提供的 JavaScript 配置文件,包含推荐的基本规则集
pnpm add -D globals @eslint/js
配置:
- 创建
eslint.config.mjs
// 引入 ESLint 推荐规则
import js from '@eslint/js'
// 引入 TypeScript 插件
import pluginTypeScript from '@typescript-eslint/eslint-plugin'
// 引入 TypeScript 解析器
import parserTypeScript from '@typescript-eslint/parser'
// 引入 Prettier 集成相关配置
import configPrettier from 'eslint-config-prettier'
import pluginPrettier from 'eslint-plugin-prettier'
// 引入 Vue.js 插件
import pluginVue from 'eslint-plugin-vue'
// 引入全局变量定义
import globals from 'globals'
// 引入 Vue 文件解析器
import parserVue from 'vue-eslint-parser'
/** @type {import('eslint').Linter.Config[]} */
export default [
// ========================
// 1. 基础忽略配置 (性能关键)
// ========================
{
ignores: [
// 构建产物和依赖
'**/node_modules/**',
'**/dist/**',
'**/build/**',
'**/coverage/**',
// 配置和缓存文件
'**/*.config.*',
'**/.vscode/**',
'**/.cache/**',
'**/.temp/**',
'**/tmp/**',
// 自动生成的类型文件
'**/auto-imports.d.ts',
'**/components.d.ts',
// 测试文件(可根据需要启用)
'**/__tests__/**',
'**/*.test.*',
'**/*.spec.*',
// 日志和文档
'**/*.log',
'**/CHANGELOG*.md',
],
},
// ========================
// 2. 全局JavaScript/TypeScript配置
// ========================
{
files: ['**/*.{js,mjs,cjs,ts,tsx,vue}'],
languageOptions: {
globals: {
// 浏览器全局变量,如 window, document
...globals.browser,
// Node.js 全局变量,如 process
...globals.node,
// Vue 3 组合式API全局变量
...Object.fromEntries(
[
// 生命周期
'onMounted',
'onUpdated',
'onUnmounted',
'onBeforeMount',
'onBeforeUpdate',
// 响应式
'ref',
'computed',
'reactive',
'watch',
'watchEffect',
// 组件
'defineProps',
'defineEmits',
'defineExpose',
// 其他
'nextTick',
'useAttrs',
'useSlots',
].map(key => [key, 'readonly'])
),
},
parserOptions: {
// 使用最新的 ECMAScript 标准
ecmaVersion: 'latest',
// 使用 ES 模块
sourceType: 'module',
// 优化解析性能
ecmaFeatures: {
jsx: true,
},
},
},
rules: {
// 应用 ESLint 推荐规则
...js.configs.recommended.rules,
// 环境感知的规则配置
// 生产环境警告 console
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// 生产环境禁止 debugger
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
// 关闭基础未使用变量规则,使用 @typescript-eslint 中的规则
'no-unused-vars': 'off',
// 性能优化:关闭高开销的通用规则
complexity: 'off',
},
},
// ========================
// 3. TypeScript配置(智能类型检查)
// ========================
{
// 针对 TypeScript 文件
files: ['**/*.{ts,tsx}'],
ignores: [
// 对测试文件使用宽松规则
'**/*.test.ts',
'**/*.spec.ts',
// 对配置文件使用宽松规则
'**/vite.config.ts',
],
languageOptions: {
// 使用 TypeScript 解析器
parser: parserTypeScript,
parserOptions: {
sourceType: 'module',
// 指向项目的 tsconfig.json,用于基于类型的规则
project: './tsconfig.app.json',
// 类型检查优化:仅对核心业务代码启用严格模式
tsconfigRootDir: process.cwd(),
},
},
plugins: {
// 启用 TypeScript 插件
'@typescript-eslint': pluginTypeScript,
},
rules: {
// 应用 TypeScript 推荐规则
// ...(pluginTypeScript.configs?.recommended?.rules ?? {}),
...pluginTypeScript.configs['recommended'].rules,
// 应用 TypeScript 风格规则
// ...(pluginTypeScript.configs?.stylistic?.rules ?? {}),
...pluginTypeScript.configs['stylistic'].rules,
// 核心TypeScript规则
'@typescript-eslint/no-unused-vars': 'warn',
// 警告使用 any 类型
'@typescript-eslint/no-explicit-any': 'warn',
// 不强制要求函数显式返回类型
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-inferrable-types': 'warn',
// '@typescript-eslint/prefer-const': 'error',
// 性能优化:关闭高开销的TypeScript规则
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
// 开发体验优化
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/consistent-type-definitions': ['error', 'interface'],
},
},
// ========================
// 4. Vue 3配置(优化版)
// ========================
{
// 针对 .vue 文件
files: ['**/*.vue'],
languageOptions: {
// 使用 vue-eslint-parser 来解析 .vue 文件
parser: parserVue,
parserOptions: {
// 使用 TypeScript 解析器来处理 `<script lang="ts">` 块
parser: parserTypeScript,
sourceType: 'module',
ecmaVersion: 'latest',
extraFileExtensions: ['.vue'],
// Vue特定解析配置
vueFeatures: {
filter: false, // Vue 3已废弃filter
interpolationAsNonHTML: false,
},
},
},
plugins: {
vue: pluginVue,
'@typescript-eslint': pluginTypeScript,
},
rules: {
// 应用 Vue 3 推荐规则
// ...pluginVue.configs['vue3-recommended'].rules,
// 使用正确的扁平配置
...pluginVue.configs['flat/recommended'].rules,
// Vue规则定制
// 关闭组件名必须多词的约束
'vue/multi-word-component-names': 'off',
// 推荐使用 `<script setup>` 语法
'vue/component-api-style': ['error', ['script-setup']],
// 关闭自闭合标签风格限制,由 Prettier 处理
'vue/html-self-closing': 'off',
// 关闭属性换行限制,由 Prettier 处理
'vue/max-attributes-per-line': 'off',
// 性能优化:关闭高开销的Vue规则
'vue/no-unused-vars': 'warn',
'vue/require-default-prop': 'off',
// Vue 3最佳实践
'vue/no-deprecated-v-on-native-modifier': 'error',
'vue/no-deprecated-filter': 'error',
},
},
// ========================
// 5. 测试文件专用配置(宽松规则)
// ========================
{
files: ['**/*.test.{js,ts,vue}', '**/*.spec.{js,ts,vue}'],
rules: {
// 测试环境宽松规则
'no-console': 'off',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'vue/require-component-is': 'off',
},
},
// ========================
// 6. 配置文件专用配置(宽松规则)
// ========================
{
files: ['**/*.config.{js,ts}', 'vite.config.ts'],
rules: {
// 配置文件宽松规则
'no-console': 'off',
'import/no-unresolved': 'off',
'@typescript-eslint/no-var-requires': 'off',
},
},
// ========================
// 7. Prettier集成(必须放在最后)
// ========================
// 关闭所有与 Prettier 冲突的 ESLint 规则
configPrettier,
{
files: ['**/*.{js,ts,tsx,vue}'],
plugins: {
prettier: pluginPrettier,
},
rules: {
// 应用 prettier 插件规则
// ...(pluginPrettier.configs?.recommended?.rules ?? {}),
...pluginPrettier.configs.recommended.rules,
// 将 Prettier 格式化问题报为错误
'prettier/prettier': 'error',
},
},
]
- 修改
package.json
"scripts": {
"dev": "vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview",
"lint": "eslint . --ext .js,.ts,.vue",
"lint:fix": "eslint . --ext .js,.ts,.vue --fix",
"lint:cache": "eslint . --ext .js,.ts,.vue --cache --cache-location node_modules/.cache/.eslintcache",
"lint:cache:fix": "eslint . --ext .js,.ts,.vue --fix --cache --cache-location node_modules/.cache/.eslintcache",
"lint:strict": "eslint . --ext .js,.ts,.vue --quiet",
"lint:strict:fix": "eslint . --ext .js,.ts,.vue --fix --quiet",
"lint:src": "eslint src --ext .js,.ts,.vue",
"lint:typescript": "eslint . --ext .ts",
"typecheck": "vue-tsc --noEmit"
}
- 配置 VSCode
- 安装 ESLint 插件
- 添加插件到工作区建议
- 重启 VSCode 或 打开命令面板(Ctrl+Shift+P),输入 “Reload Window” 重新加载窗口
验证:
- 运行
pnpm run lint命令
- 成功:能看到类似输出 ✖ 2 problems (0 errors, 2 warnings) 或 ✖ 8 problems (8 errors, 0 warnings)
- 失败:其他情况
- 在
<script setup lang="ts">中添加错误代码
const testError = someUndefinedVar?.unexpectedProperty
- 成功:能看到报错 ‘someUndefinedVar’ is not defined 或 找不到名称“someUndefinedVar”
- 失败:其他情况
3. Git 钩子(Husky + Commitlint)
安装:
# 安装 Git 钩子管理工具 (开发依赖)
# husky: Git 钩子管理工具,用于在 Git 操作的各个阶段(如提交前、推送前)自动运行指定脚本,确保代码质量和规范
# lint-staged: 针对暂存区(staged)文件运行 linter 工具,只检查即将提交的代码,提高检查效率
# @commitlint/cli: Commit message 校验工具的命令行接口,用于检查提交信息是否符合规范
# @commitlint/config-conventional: 基于 Angular 提交规范的配置文件,提供行业标准的提交信息格式
pnpm add -D husky lint-staged @commitlint/cli @commitlint/config-conventional
配置:
- 初始化配置
# 初始化 Husky,创建 .husky 目录并设置 Git 钩子
npx husky init
- 修改
.husky/pre-commit
#!/usr/bin/env sh
# 移除过时的 husky.sh 引入,使用现代方式
echo " Running pre-commit checks..."
# 运行 lint-staged
npx lint-staged
# 如果有 TypeScript 项目,可以添加类型检查(可选)
# echo " Running TypeScript type check..."
# npx tsc --noEmit
echo "✅ Pre-commit checks passed!"
- 创建
.husky/commit-msg
#!/usr/bin/env sh
npx --no -- commitlint --edit "$1"
- 修改
package.json
{
"scripts": {
"prepare": "husky install",
"lint:lint-staged": "lint-staged"
},
"lint-staged": {
"*.{js,ts,vue}": ["eslint --fix", "prettier --write"],
"*.{json,md,css,scss}": ["prettier --write"]
}
}
- 创建
commitlint.config.cjs
module.exports = {
// 继承的规则
extends: ['@commitlint/config-conventional'],
// 自定义规则
rules: {
// 提交类型必须小写,可选值: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test
'type-case': [2, 'always', 'lower-case'],
'type-empty': [2, 'never'],
'type-enum': [
2,
'always',
[
'build', // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
'chore', // 对构建过程或辅助工具和库的更改(其他不修改源代码或测试文件的更改)
'ci', // CI 配置文件和脚本的更改
'docs', // 仅文档更改
'feat', // 新功能
'fix', // 修复缺陷
'perf', // 性能优化
'refactor', // 代码重构(不包括 bug 修复、功能新增)
'revert', // 回滚提交
'style', // 不影响代码含义的更改(空格、格式、缺少分号等)
'test', // 添加缺失的测试或更正现有测试
],
],
// 提交主题(描述)不能为空,首字母小写,不以句号结尾
'subject-case': [2, 'always', 'lower-case'],
'subject-empty': [2, 'never'],
'subject-full-stop': [2, 'never', '.'],
// 提交主题最大长度 100 字符
'subject-max-length': [2, 'always', 100],
// 可选的 scope 必须小写
'scope-case': [2, 'always', 'lower-case'],
},
}
- 配置 Git
- 可以采用 Gitee/GitHub 仓库,具体配置略
- 创建
.gitignore
# 依赖目录 - 通过 npm、pnpm 或 yarn 安装
node_modules/
.pnpm-store/
# 构建输出目录 - 打包后生成的产物
dist/
build/
dist-ssr/
*.tsbuildinfo
# 本地开发环境文件 - 本地调试时的生成项
*.local
# 日志文件
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
# 编辑器与IDE目录
# Visual Studio Code
.vscode/*
!.vscode/extensions.json
# IntelliJ IDEA
.idea/
*.iml
*.iws
*.ipr
# 其他编辑器临时文件
*~
*.swp
*.swo
# 操作系统文件
# macOS
.DS_Store
.AppleDouble
# Windows
Thumbs.db
ehthumbs.db
Desktop.ini
# 代码覆盖率报告
coverage/
.nyc_output/
# 依赖缓存(如TurboRepo等)
.turbo/
.cache/
.temp/
tmp/
验证:
- 任意创建/修改文件并提交,提交信息设为 “invalid commit message”
- 成功:能看到报错 “subject may not be empty [subject-empty]” 和 “type may not be empty
[type-empty]” - 失败:其他情况
- 暂存任意更改,运行
pnpm run lint:lint-staged
- 成功:能看到 lint-staged 的输出,如 “Running tasks for staged files…”
- 失败:其他情况
4. CSS 代码检查工具(Stylelint)
安装:
# 安装 CSS/SCSS 代码质量检查工具链 (开发依赖)
# stylelint: 现代化的 CSS 代码检查工具,用于保持代码风格一致性并避免错误,支持 CSS 预处理器和现代 CSS 特性
# stylelint-config-recommended: Stylelint 官方推荐配置,包含基础规则集
# stylelint-config-standard: Stylelint 标准配置,基于 Google、Airbnb 等公司的 CSS 风格指南
# stylelint-config-standard-scss: 针对 SCSS 语法的标准配置扩展,支持 Sass 特有规则和语法检查
# stylelint-config-rational-order: 理性的 CSS 属性顺序配置,按照定位、盒模型、文字、视觉、动画等逻辑分组排序
# stylelint-config-html: HTML 和 Vue 文件样式检查配置,支持单文件组件中的样式检查
# stylelint-config-recess-order: 另一个属性排序配置,按照 Bootstrap 的 Recess 规范排序
# stylelint-scss: SCSS 语法检查插件,提供针对 Sass 特有功能(如 @extend、@mixin 等)的规则检查
# @stylistic/stylelint-plugin: Stylelint v16+ 必需的样式规则插件,提供被移除的内置规则(如缩进、引号等)
# stylelint-order: CSS 属性排序插件,用于规范样式属性的书写顺序
# stylelint-prettier: Prettier 集成插件,确保 Stylelint 与 Prettier 格式化规则兼容
# postcss-html: PostCSS 的 HTML 语法解析器,用于检查 Vue、HTML 文件中的样式代码
# postcss-scss: PostCSS 的 SCSS 语法解析器,使 Stylelint 能够正确解析 Sass 文件
pnpm add -D stylelint stylelint-config-recommended stylelint-config-standard stylelint-config-standard-scss
pnpm add -D stylelint-config-rational-order stylelint-config-html stylelint-config-recess-order stylelint-scss
pnpm add -D @stylistic/stylelint-plugin stylelint-order stylelint-prettier postcss-html postcss-scss
配置:
- 创建
stylelint.config.js
// stylelint.config.js
/** @type {import('stylelint').Config} */
export default {
extends: [
// 基础推荐配置
'stylelint-config-recommended',
// SCSS 标准配置
'stylelint-config-standard-scss',
// 属性排序配置
'stylelint-config-rational-order',
// HTML/Vue 配置
'stylelint-config-html/vue',
],
plugins: [
// SCSS 语法支持
'stylelint-scss',
// Stylelint v16 必需的样式规则插件
'@stylistic/stylelint-plugin',
// Prettier 集成
'stylelint-prettier',
],
overrides: [
{
files: ['**/*.{vue,html}'],
customSyntax: 'postcss-html',
},
{
files: ['**/*.{css,scss}'],
customSyntax: 'postcss-scss',
},
],
ignoreFiles: ['node_modules/**', 'dist/**', 'public/**', '**/*.js', '**/*.ts'],
rules: {
// Prettier 集成(必须放在第一位)
'prettier/prettier': true,
// 使用 @stylistic 插件提供的基础规则(替代被移除的内置规则)
'@stylistic/indentation': 2,
'@stylistic/string-quotes': 'single',
'@stylistic/color-hex-case': 'lower',
// 基础样式规则
'color-hex-length': 'short',
'max-nesting-depth': 4,
'selector-max-compound-selectors': 3,
'no-empty-source': null,
// 处理 Tailwind CSS 和 SCSS 指令
'at-rule-no-unknown': null,
'scss/at-rule-no-unknown': [
true,
{
ignoreAtRules: [
'tailwind',
'apply',
'variants',
'responsive',
'screen',
'layer',
'config',
'plugin',
'use',
'forward',
'mixin',
'include',
],
},
],
// Vue 深度选择器支持
'selector-pseudo-class-no-unknown': [
true,
{
ignorePseudoClasses: ['global', 'v-deep', 'deep', 'slotted'],
},
],
// 属性顺序规则
'order/properties-order': [
'position',
'top',
'right',
'bottom',
'left',
'display',
'float',
'clear',
'width',
'height',
'max-width',
'max-height',
'min-width',
'min-height',
'margin',
'margin-top',
'margin-right',
'margin-bottom',
'margin-left',
'padding',
'padding-top',
'padding-right',
'padding-bottom',
'padding-left',
'border',
'border-width',
'border-style',
'border-color',
'background',
'background-color',
'background-image',
'background-position',
'color',
'font-size',
'font-weight',
'line-height',
'text-align',
'transform',
'transition',
'animation',
],
},
}
- 创建
.stylelintignore
# 依赖目录
node_modules/
.npm/
.pnpm/
# 构建输出目录
dist/
build/
.output/
# 配置文件目录
.config/
# 静态资源目录
public/
assets/
# 日志文件
*.log
logs/
# 系统文件
.DS_Store
Thumbs.db
# 测试文件
**/__tests__/**
**/*.test.*
**/*.spec.*
# TypeScript 声明文件
**/*.d.ts
- 修改
package.json
"scripts": {
"lint:style": "stylelint \"src/**/*.{css,scss,vue,html}\"",
"lint:style:fix": "stylelint \"src/**/*.{css,scss,vue,html}\" --fix",
"lint:all": "pnpm run lint:style && pnpm run lint:js",
"lint:all:fix": "pnpm run lint:style:fix && pnpm run lint:js:fix"
},
"lint-staged": {
"*.{js,ts,vue}": [
"eslint --fix",
"prettier --write"
],
"*.{css,scss}": [
"stylelint --fix",
"prettier --write"
],
"*.{json,md}": [
"prettier --write"
]
}
- 创建
.vscode/settings.json
{
"stylelint.enable": true,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"css.validate": false,
"less.validate": false,
"scss.validate": false,
"stylelint.validate": ["css", "scss", "sass", "vue", "html"],
"[scss]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint",
"editor.formatOnSave": true
},
"[css]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint",
"editor.formatOnSave": true
},
"[vue]": {
"editor.defaultFormatter": "stylelint.vscode-stylelint",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
}
},
"stylelint.configFile": "./stylelint.config.js",
"stylelint.trace.server": "verbose"
}
验证:
- 创建
styles/test.scss,保存
// 错误的写法(用于测试检查功能)
.test-component {
color: #ffffff; // 颜色值应该小写且简写,#fff
margin: 10px 10px 10px 10px; // 冗余值,应该简写为 margin: 10px
// 嵌套过深(测试 max-nesting-depth 规则)
.child {
.grandchild {
.great-grandchild {
color: red; // 这会导致嵌套深度警告
}
}
}
}
- 成功:能看到自动修复更正错误
- 失败:其他情况
- 运行
pnpm run lint:style
- 成功:能看到报错,如 9:7 ✖ Expected “.great-grandchild” to have no more than 3 compound selectors
selector-max-compound-selectors - 失败:其他情况

浙公网安备 33010602011771号