前端学习笔记——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 @/* 报错

2.1.5 解决报错

一、初始准备

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

配置:

  1. 创建 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
  1. 修改 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')
  1. 修改 src/App.vue
<script setup lang="ts">
  import HelloWorld from './components/HelloWorld.vue'
</script>

  1. 创建页面
  • 创建 src/views/Home.vue
  • 创建 src/views/Test.vue
  1. 解决报错
  • 安装 @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.jsontsconfig.app.json 中的 compilerOptions
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}
  • 创建 src/vite-env.d.ts
declare module '@/*' {
const value: any
export default value
}

验证:

  • 成功:访问 http://localhost:5173http://localhost:5173/test 能切换 Home 和 Test 页面
  • 失败:其它情况

2. 状态管理 (Pinia)

安装:

# 安装 Pinia
pnpm add pinia
# 安装状态持久化插件
pnpm add pinia-plugin-persistedstate

配置:

  1. 创建 src/stores/index.ts
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(persist)
export default pinia
  1. 修改 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')
  1. 创建 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,
})
  1. 修改 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. 清除初始文件

配置:

  1. 删除文件
  • 删除 public/vite.svgpublic
  • 删除 src/assets/vue.svgsrc/assets
  • 删除 src/components/HelloWorld.vuesrc/components
  1. 修改文件
  • 修改 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

配置:

  1. 修改 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)
  1. 报错解决
  • 重启 TypeScript 语言服务器​​:在 VSCode 中,按下 Ctrl+Shift+P(Windows) /
    Cmd+Shift+P(Mac),输入 “TypeScript: Restart TS
    Server” 并执行。这是非常关键的一步,能让 IDE 重新加载所有配置。
  1. 配置中文语言包(可选)
  • 修改 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

验证:

  1. 验证 Axios
  • 修改 src/main.ts
// 导入网络请求模块
import axios from 'axios'
console.log('Axios 版本:', axios.VERSION)
  • 成功:访问首页,F12 控制台能打印 Axios 版本号
  • 失败:其它情况
  1. 验证 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

配置:

  1. 创建 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
},
}
  1. 修改 src/main.ts
// 导入 Echarts插件
import echarts from '@/plugins/echarts'
// 使用 Echarts插件
app.use(echarts)

验证:

  • 创建 src/components/ChartTest.vue

<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

配置:

  1. 初始化配置
# 初始化 Tailwind CSS 配置文件
npx tailwindcss init -p
  1. 配置 tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
// 配置 Tailwind 需要扫描的文件路径
content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
theme: {
extend: {},
},
plugins: [],
}
  1. 修改 src/style.css
@tailwind base;
@tailwind components;
@tailwind utilities;

验证:

  • 修改 src/views/Home.vue
  • 成功:访问首页,能显示绿色背景、白色文字的标题
  • 失败:其它情况

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

配置:

  1. 创建 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
  1. 创建 .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
  1. 配置 VSCode
  • 下载 Prettier 插件
  • 打开 VSCode 设置
  • 搜索 “Format On Save”,勾选 “Editor: Format On Save”
  • 搜索 “Default Formatter”,选择 “Prettier - Code formatter”
  • 添加插件到工作区建议
  • 重启 VSCode 或 打开命令面板(Ctrl+Shift+P),输入 “Reload Window” 重新加载窗口

验证:

  1. <script> 模块添加结尾分号,按保存
  • 成功:分号被去除
  • 失败:其它情况
  1. 修改 <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

配置:

  1. 创建 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',
    },
    },
    ]
  1. 修改 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"
}
  1. 配置 VSCode
  • 安装 ESLint 插件
  • 添加插件到工作区建议
  • 重启 VSCode 或 打开命令面板(Ctrl+Shift+P),输入 “Reload Window” 重新加载窗口

验证:

  1. 运行 pnpm run lint 命令
  • 成功:能看到类似输出 ✖ 2 problems (0 errors, 2 warnings) 或 ✖ 8 problems (8 errors, 0 warnings)
  • 失败:其他情况
  1. <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

配置:

  1. 初始化配置
# 初始化 Husky,创建 .husky 目录并设置 Git 钩子
npx husky init
  1. 修改 .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!"
  1. 创建 .husky/commit-msg
#!/usr/bin/env sh
npx --no -- commitlint --edit "$1"
  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"]
}
}
  1. 创建 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'],
},
}
  1. 配置 Git
  • 可以采用 Gitee/GitHub 仓库,具体配置略
  1. 创建 .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/

验证:

  1. 任意创建/修改文件并提交,提交信息设为 “invalid commit message”
  • 成功:能看到报错 “subject may not be empty [subject-empty]” 和 “type may not be empty
    [type-empty]”
  • 失败:其他情况
  1. 暂存任意更改,运行 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

配置:

  1. 创建 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',
],
},
}
  1. 创建 .stylelintignore
# 依赖目录
node_modules/
.npm/
.pnpm/
# 构建输出目录
dist/
build/
.output/
# 配置文件目录
.config/
# 静态资源目录
public/
assets/
# 日志文件
*.log
logs/
# 系统文件
.DS_Store
Thumbs.db
# 测试文件
**/__tests__/**
**/*.test.*
**/*.spec.*
# TypeScript 声明文件
**/*.d.ts
  1. 修改 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"
]
}
  1. 创建 .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"
}

验证:

  1. 创建 styles/test.scss,保存
// 错误的写法(用于测试检查功能)
.test-component {
  color: #ffffff; // 颜色值应该小写且简写,#fff
  margin: 10px 10px 10px 10px; // 冗余值,应该简写为 margin: 10px
  // 嵌套过深(测试 max-nesting-depth 规则)
  .child {
    .grandchild {
      .great-grandchild {
        color: red; // 这会导致嵌套深度警告
      }
    }
  }
}
  • 成功:能看到自动修复更正错误
  • 失败:其他情况
  1. 运行 pnpm run lint:style
  • 成功:能看到报错,如 9:7 ✖ Expected “.great-grandchild” to have no more than 3 compound selectors
    selector-max-compound-selectors
  • 失败:其他情况
posted @ 2025-12-17 09:49  gccbuaa  阅读(1)  评论(0)    收藏  举报