npm init vite@latest
// 使用 vue-ts 模板,vite提供多种模板,react、react-ts 等。
npm init vite@latest vue3-ts-template -- --template vue-ts
// 安装依赖
npm i
// 运行
npm run dev
定义目录结构
├─ .husky
│ ├─ pre-commit # husky commit 钩子配置文件
│ ├─ commit-msg # husky commit 钩子配置文件
├─ .vscode
│ ├─ settings.json # vscode 项目配置文件
├─ mock # mock 模拟数据配置
├─ public
│ ├─ favicon.ico
├─ src
│ ├─ @types # ts 接口定义
│ ├─ api # api 接口
│ ├─ assets # 静态资源
│ ├─ components # 全局组件
│ ├─ layout # 布局
│ ├─ plugins # 插件
│ ├─ router # 路由
│ ├─ store # vuex store
│ ├─ styles # 全局样式
│ ├─ utils # 全局公共方法
│ └─ views # 所有页面
│ ├─ App.vue # 入口页面
│ ├─ main.ts # 入口文件
│ └─ shims-vue.d.ts # ts 适配定义文件
│ └─ auto-import.d.ts # unplugin-auto-import 插件生成全局类型定义文件
│ └─ components.d.ts # unplugin-vue-components 插件生成全局组件定义文件
├─ .env.development # 开发环境
├─ .env.production # 生产环境
├─ .env.test # 测试环境
├─ .eslintignore # eslint 忽略配置文件
├─ .eslintrc-auto-import.json # unplugin-auto-import/vite 插件解决eslint报错问题的配置项文件
├─ .eslintrc.js # eslintrc 配置
├─ .gitignore # git 忽略配置文件
├─ .prettierignore # prettier 忽略配置文件
├─ .prettierrc.json # prettierrc 配置文件
├─ .stylelintignore # stylelint 忽略配置文件
├─ .stylelintrc.js # stylelintrc 配置文件
├─ tsconfig.json # ts 编译配置
└─ vite.config.js # vite 配置
└─ package.json
└─ README.md
└─ index.html
3 vite.config.ts配置
3.1 配置别名
如果require('path') ts报红提示 npm i @types/node
执行 npm i -D @vue/cli-plugin-typescript(ts相关的工具集成起来的插件)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
const { resolve } = require('path')
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
3.2 配置代理
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
open: true,
proxy: {
'/api': {
target: 'http://xxx.xx.x.xx:8099/',
rewrite: (path) => path.replace(/^\/api/, ''),
changeOrigin: true
3.3 配置全局sass文件
安装 sass
npm i -D sass node-sass sass-loader
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "src/styles/var.scss" as *;'
3.4 自动按需引入 element-plus 组件和自定义 compontent 组件
自动引入后,再也不用引入和注册组件,和全局引用一样,可以直接在模板中使用,再也不用手动注册组件了,nice!
安装UI库 element-plus
npm i element-plus
安装按需引入样式插件
npm i -D vite-plugin-style-import
自动按需导入组件、vue3等插件 hooks,省去大量的import操作
npm i -D unplugin-vue-components unplugin-auto-import
如果运行报错提示 Cannot find module 'consola'
npm i -D consola
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
createStyleImportPlugin({
resolves: [ElementPlusResolve()],
libs: [
libraryName: 'element-plus',
esModule: true,
resolveStyle: (name) => {
return `element-plus/theme-chalk/${name}.css`
AutoImport({
resolvers: [ElementPlusResolver()]
Components({
dirs: ['src/components'],
deep: true,
extensions: ['vue'],
directoryAsNamespace: false,
dts: 'src/components.d.ts',
resolvers: [ElementPlusResolver({ importStyle: 'sass' })]
3.5 配置 element-icon
npm i @element-plus/icons-vue
import { createApp } from 'vue'
import App from './App.vue'
import { loadAllPlugins } from './plugins'
const app = createApp(App)
loadAllPlugins(app)
app.use(store).use(router).mount('#app')
import { createApp } from 'vue'
export function loadAllPlugins(app: ReturnType<typeof createApp>) {
const files = import.meta.globEager('./*.ts')
for (const path in files) {
if (typeof files[path].default === 'function') {
files[path].default(app)
import * as ElIconModules from '@element-plus/icons-vue'
export default function loadElementIcon(app: any) {
for (const iconName in ElIconModules) {
if (Reflect.has(ElIconModules, iconName)) {
app.component(iconName, ElIconModules[iconName])
3.6 配置 vue3 hook自动引入
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: ['vue', 'vue-router', 'vue-i18n', '@vueuse/head','@vueuse/core'],
dts: 'src/auto-import.d.ts',
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true
3.7 自动导入生成 svg 雪碧图组件
svg-icon 在日常项目中经常会用到 ,如何在vite中使用?
1、安装svg雪碧图插件
2、配置vite.config文件
3、注册雪碧图
4、新建SvgIcon.vue组件
npm i path-browserify vite-plugin-svg-icons
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path-browserify'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
vue(),
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
symbolId: 'icon-[dir]-[name]',
inject: 'body-last',
customDomId: '__svg__icons__dom__'
import { createApp } from 'vue'
import App from './App.vue'
import 'virtual:svg-icons-register'
createApp(App).mount('#app')
// 3、在 compontent 中新建 SvgIcon.vue 组件(由于配置了按需导入,此组件无需import导入)
<template>
<div class="svg-box">
<svg :class="svgClass" aria-hidden="true" :style="style">
<use :xlink:href="iconName" :fill="color" />
</template>
<script lang="ts" setup>
defineOptions({
name: 'SvgIcon'
interface Style {
width?: string
height?: string
[index: string]: any
const props = defineProps({
name: {
type: String,
required: true
width: {
type: String,
default: ''
height: {
type: String,
default: ''
className: {
type: String,
default: ''
color: {
type: String,
default: 'red'
const style: Style = computed(() => {
const style: Style = {}
if (props.width) {
style.width = props.width + 'px'
style.height = (props.height || props.width) + 'px'
return style
const iconName = computed(() => `#icon-${props.name}`)
const svgClass = computed(() => {
if (props.className) {
return `svg-icon ${props.className}`
return 'svg-icon'
</script>
<style lang="scss" scoped>
.svg-box {
display: inline-block;
.svg-icon {
position: relative;
width: 14px;
min-width: 1em;
height: 14px;
vertical-align: -2px;
</style>
// 4、使用 name 为 svg 图片名称
<SvgIcon width="444" height="342" name="errorPage404" />
3.8 开启gzip、压缩代码
npm i -D vite-plugin-compression rollup-plugin-terser
import { defineConfig } from 'vite'
import vue from
'@vitejs/plugin-vue'
import compressPlugin from 'vite-plugin-compression'
import { terser } from 'rollup-plugin-terser'
export default defineConfig({
plugins: [
vue(),
terser(),
compressPlugin({
ext: '.gz',
algorithm: 'gzip',
deleteOriginFile: false
3.9 rollupOptions 打包优化
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
sourcemap: false,
outDir: 'dist',
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
const arr = id.toString().split('node_modules/')[1].split('/')
switch (arr[0]) {
case '@vue':
case 'axios':
case 'element-plus':
case '@element-plus':
return '_' + arr[0]
default:
return '__vendor'
chunkFileNames: 'static/js1/[name]-[hash].js',
entryFileNames: 'static/js2/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
3.10 配置 mock 模拟数据
npm i -D vite-plugin-mock
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteMockServe } from 'vite-plugin-mock'
export default defineConfig({
plugins: [
vue(),
viteMockServe({
mockPath: '/mock'
export default [
url: '/mock/user/sysUser/login',
method: 'post',
timeout: 500,
statusCode: 200,
response: {
code: 0,
data: {
orgName: 'xxx',
mobile: 'xxx',
userId: 'xxx',
token: 'xxx',
password: '',
id: 'xxx',
username: 'xxx'
const baseURL = import.meta.env.DEV === 'development' ? 'mock' : import.meta.env.VITE_APP_BASEURL
如果ts报红提示,可在 .d.ts 声明文件中加入
interface ImportMeta {
env: Record<string, unknown>
3.11 配置实时检测typescript插件
npm i -D vite-plugin-checker
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import checker from 'vite-plugin-checker'
export default defineConfig({
plugins: [
vue(),
checker({ vueTsc: true })
vite.config.ts
import vue from '@vitejs/plugin-vue'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import compressPlugin from 'vite-plugin-compression'
import { terser } from 'rollup-plugin-terser'
import { createStyleImportPlugin, ElementPlusResolve } from 'vite-plugin-style-import'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { viteMockServe } from 'vite-plugin-mock'
import checker from 'vite-plugin-checker'
import DefineOptions from 'unplugin-vue-define-options/vite'
import path from 'path-browserify'
import { defineConfig } from 'vite'
const { resolve } = require('path')
export default defineConfig({
build: {
sourcemap: false,
outDir: 'dist',
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules')) {
const arr = id.toString().split('node_modules/')[1].split('/')
switch (arr[0]) {
case '@vue':
case 'axios':
case 'element-plus':
case '@element-plus':
return '_' + arr[0]
default:
return '__vendor'
chunkFileNames: 'static/js1/[name]-[hash].js',
entryFileNames: 'static/js2/[name]-[hash].js',
assetFileNames: 'static/[ext]/[name]-[hash].[ext]'
plugins: [
DefineOptions(),
checker({ vueTsc: true }),
terser(),
compressPlugin({
ext: '.gz',
algorithm: 'gzip',
deleteOriginFile: false
viteMockServe({
mockPath: '/mock'
createStyleImportPlugin({
resolves: [ElementPlusResolve()],
libs: [
libraryName: 'element-plus',
esModule: true,
resolveStyle: (name) => {
return `element-plus/theme-chalk/${name}.css`
createSvgIconsPlugin({
iconDirs: [path.resolve(process.cwd(), 'src/assets/svg')],
symbolId: 'icon-[dir]-[name]',
inject: 'body-last',
customDomId: '__svg__icons__dom__'
vue(),
AutoImport({
imports: ['vue', 'vue-router', 'vue-i18n', '@vueuse/head', '@vueuse/core'],
resolvers: [ElementPlusResolver()],
dts: 'src/auto-import.d.ts',
eslintrc: {
enabled: true,
filepath: './.eslintrc-auto-import.json',
globalsPropValue: true
Components({
dirs: ['src/components'],
deep: true,
extensions: ['vue'],
directoryAsNamespace: false,
dts: 'src/components.d.ts',
resolvers: [ElementPlusResolver({ importStyle: 'sass' })]
resolve: {
alias: {
'@': resolve(__dirname, 'src')
css: {
postcss: {
plugins: [
postcssPlugin: 'internal:charset-removal',
AtRule: {
charset: (atRule) => {
if (atRule.name === 'charset') {
atRule.remove()
preprocessorOptions: {
scss: {
additionalData: '@use "src/styles/var.scss" as *;'
server: {
open: true,
proxy: {
'/api': {
target: 'http://xxx/',
rewrite: (path) => path.replace(/^\/api/, ''),
changeOrigin: true
4 集成 eslint
ESLint 是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具,配置 typescript-eslint 代码规范
相关依赖介绍
@typescript-eslint/eslint-plugin ( eslint 插件,包含了各类定义好的检测 TS 代码的规范 )
@typescript-eslint/parser ( eslint 的解析器,用于解析 TS, 从而检查和规范 TS )
@vue/eslint-config-standard ( vue 标准的esLint规则集 )
@vue/eslint-config-typescript ( ts 校验工具 )
eslint ( eslint 核心代码库, js代码检测工具 )
eslint-import-resolver-typescript ( 解决eslint-plugin-import不能识别目录别名问题 )
eslint-plugin-import ( eslint检测import/export语法插件 )
eslint-plugin-node ( 添加对node的eslint支持,也就是 npm run lint )
eslint-plugin-promise ( eslint检测promise语法 )
eslint-plugin-vue ( 解析 Vue 的 eslint 插件 )
npm i -D @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/eslint-config-standard @vue/eslint-config-typescript eslint eslint-import-resolver-typescript eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-vue
.eslintrc.js 配置
module.exports = {
root: true,
env: {
browser: true,
node: true,
es6: true
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly'
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
typescript: {
alwaysTryTypes: true
'import/core-modules': ['virtual:svg-icons-register', 'unplugin-auto-import/vite', 'unplugin-vue-components/vite', 'unplugin-vue-components/resolvers'],
'import/ignore': ['vue-router', 'vue']
extends: [
'plugin:vue/vue3-recommended',
'plugin:vue/vue3-strongly-recommended',
'plugin:@typescript-eslint/recommended',
'@vue/standard',
'@vue/typescript/recommended',
'./.eslintrc-auto-import.json'
rules: {
'vue/comment-directive': 'off',
'no-console': 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/member-delimiter-style': [
'error',
multiline: {
delimiter: 'none'
singleline: {
delimiter: 'comma'
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/no-var-requires': 'off',
'prefer-regex-literals': 'off',
'space-before-function-paren': 0,
'vue/array-bracket-spacing': 'error',
'vue/arrow-spacing': 'error',
'vue/block-spacing': 'error',
'vue/brace-style': 'error',
'vue/camelcase': 'error',
'vue/comma-dangle': 'error',
'vue/component-name-in-template-casing': 'error',
'vue/eqeqeq': 'error',
'vue/key-spacing': 'error',
'vue/match-component-file-name': 'error',
'vue/object-curly-spacing': 'off',
'vue/max-attributes-per-line': 'off',
'vue/html-closing-bracket-newline': 'off',
'no-useless-escape': 'off',
'@typescript-eslint/no-this-alias': [
'error',
allowDestructuring: true,
allowedNames: ['self']
'vue/attribute-hyphenation': 'off',
'vue/custom-event-name-casing': 'off',
'dot-notation': 'off',
'vue/html-self-closing': [
'error',
html: {
void: 'always',
normal: 'always',
component: 'always'
svg: 'always',
math: 'always'
'vue/singleline-html-element-content-newline': 'off',
'import/no-unresolved': [2, { commonjs: true, amd: true }],
'import/named': 2,
'import/namespace': 2,
'import/default': 2,
'import/export': 2,
'promise/always-return': 'error',
'promise/no-return-wrap': 'error',
'promise/param-names': 'error',
'promise/catch-or-return': 'off',
'promise/no-native': 'off',
'promise/no-nesting': 'warn',
'promise/no-promise-in-callback': 'warn',
'promise/no-callback-in-promise': 'warn',
'promise/avoid-new': 'warn',
'promise/no-return-in-finally': 'warn'
5 集成 prettier 格式化代码规范
prettier是一个固定的代码格式化程序,通过解析项目代码库,强制使用统一的风格的代码
相关依赖介绍
eslint-config-prettier (禁用与prettier样式规范有冲突的esLint规则)
eslint-plugin-prettier (将prettier作为esLint的规则来运行)
npm i -D eslint-config-prettier eslint-plugin-prettier
对比于 eslint而言,prettier 没有太多的配置项,在根目录上新建配置文件 .prettierrc.json
"tabWidth": 2,
"jsxSingleQuote": true,
"jsxBracketSameLine": true,
"printWidth": 180,
"singleQuote": true,
"semi": false,
"bracketSpacing": true,
"trailingComma": "none",
"arrowParens": "always"
有些目录或者文件不需配置prettier,在根目录上新建忽略文件.prettierignore
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
在 package.json 中添加脚本
"scripts":{
"prettier": "prettier --write .",
配合 vscode 代码格式化插件使用,完成自动保存格式化,vscode 编辑器 安装 Prettier - Code formatter,vscode编辑器配置文件 settings.json 增加以下配置
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[css]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[scss]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
"prettier.enable": true,
"prettier.semi": false,
"prettier.singleQuote": true,
"prettier.tabWidth": 2,
"prettier.printWidth": 160,
"prettier.useTabs": false,
"prettier.bracketSpacing": true,
"prettier.jsxBracketSameLine": true,
"prettier.arrowParens": "always",
"prettier.trailingComma": "none"
prettierrc 配置参数介绍
"tabWidth": 2,
"useTabs": false,
"jsxSingleQuote": true,
"quoteProps": "as-needed",
"printWidth": 800,
"singleQuote": true,
"semi": false,
"trailingComma": "none",
"arrowParens": "always",
"bracketSpacing": true,
"bracketSameLine": false,
"prettier.disableLanguages": ["vue"],
"prettier.endOfLine": "auto",
"prettier.tslintIntegration": false,
"prettier.stylelintIntegration": false,
"prettier.eslintIntegration": false,
"prettier.ignorePath": ".prettierignore"
需要注意,vue项目往往会配合 Vetur插件使用,主要是vue的语法高亮,其次是代码格式化,支持 prettier 等格式化器。
虽然有各种内置的格式化器,但是检测到本地有格式化插件,会优先使用本地格式化插件,
vscode编辑器配置文件 settings.json 增加以下配置
"vetur.format.options.tabSize": 2,
"vetur.validation.script": false,
"vetur.validation.interpolation": false,
"vetur.validation.template": false,
"vetur.ignoreProjectWarning": true,
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"javascript.format.semicolons": "remove",
"vetur.format.defaultFormatter.html": "prettier",
"vetur.format.defaultFormatter.js": "prettier-eslint",
"vetur.format.defaultFormatter.ts": "prettier",
"vetur.format.defaultFormatter.css": "prettier",
"vetur.format.defaultFormatter.sass": "sass-formatter",
"vetur.format.defaultFormatter.postcss": "prettier",
"vetur.format.defaultFormatter.scss": "prettier",
"vetur.format.defaultFormatter.less": "prettier",
"vetur.format.defaultFormatter.stylus": "stylus-supremacy",
"vetur.format.defaultFormatterOptions": {
"prettier": {
"printWidth": 160,
"singleQuote": true,
"semi": false,
"tabWidth": 2,
"arrowParens": "always",
"bracketSpacing": true,
"proseWrap": "preserve"
6 集成 stylelint 样式规范
stylelint 是一个强大、先进的 CSS 代码检查器,通过内置规则自动修复大多数样式代码格式问题。
相关依赖介绍
stylelint ( stylelint 核心库 )
stylelint-config-prettier ( 解决stylelint与prettier冲突 )
stylelint-config-recommended-scss( css属性顺序的规则, 配合stylelint-order使用 )
stylelint-config-recommended-vue
stylelint-config-standard ( stylelint官方共享的标准规则集成 )
stylelint-config-standard-scss
stylelint-order ( 格式化css文件时对代码的属性进行排序 )
npm i -D stylelint stylelint-config-prettier stylelint-config-recommended-scss stylelint-config-recommended-vue stylelint-config-standard stylelint-config-standard-scss stylelint-orde
在根目录上新建配置文件.stylelintrc.js 文件
module.exports = {
extends: [
'stylelint-config-standard',
'stylelint-config-html/vue',
'stylelint-config-recommended-vue',
'stylelint-config-standard-scss',
'stylelint-config-recommended-vue/scss',
'stylelint-config-prettier'
plugins: ['stylelint-order', 'stylelint-config-rational-order/plugin'],
rules: {
'order/properties-order': [],
'selector-class-pattern': [
'^([a-z][a-z0-9]*)(-[a-z0-9]+)*$',
message: 'Expected class selector to be kebab-case'
'at-rule-no-unknown': [true, { ignoreAtRules: ['mixin', 'extend', 'content', 'include', 'forward', 'if'] }],
'comment-empty-line-before': [
'always',
except: ['first-nested'],
ignore: ['stylelint-commands']
'rule-empty-line-before': [
'always-multi-line',
except: ['first-nested'],
ignore: ['after-comment']
'at-rule-empty-line-before': ['always', { ignore: ['after-comment', 'inside-block', 'blockless-after-same-name-blockless'] }],
'selector-pseudo-element-no-unknown': [
true,
ignorePseudoElements: ['/./', 'v-deep', '-webkit-']
'alpha-value-notation': 'number',
'color-function-notation': 'legacy',
'declaration-empty-line-before': 'never',
'scss/dollar-variable-pattern': [/./, { ignore: 'global' }],
'scss/at-mixin-pattern': /.+/,
'color-hex-length': 'long',
'string-quotes': 'single',
'at-rule-name-case': 'lower',
'length-zero-no-unit': true,
'shorthand-property-no-redundant-values': true,
'block-no-empty': true,
'comment-no-empty': true,
'function-url-quotes': 'always',
'number-leading-zero': 'always',
'declaration-block-no-duplicate-properties': true,
'declaration-block-no-redundant-longhand-properties': true,
'no-descending-specificity': true,
'selector-max-id': 0,
'max-nesting-depth': 5,
'scss/at-import-partial-extension': 'always',
indentation: 2
在根目录上新建忽略配置文件.stylelintignore文件
src/styles/element.scss
src/styles/index.scss
node_modules
7 自动化 husky + lint-staged 对代码进行校验
在代码提交前,一般都需使用 eslint、 prettier 、 stylelint 等工具,对当前的代码仓库进行一次格式化,然后在提交时,校验一下 commit 是否符合规范。主要需要使用到以下工具:husky、lint-staged、commit-msg
husky
husky 继承了 git 下所有的钩子, 对 git 的 commit 操作进行校验,当我们进行 commit 操作时,会触发 husky 的 hook
lint-staged
对暂存的 git 文件运行 lint
commit-msg
对 git commit 格式进行校验
在 package.json 添加 prepare,prepare 会在 npm i 之后触发,首次使用可手动触发一下prepare
"scripts": { "prepare": "husky install" }
生成 hook 相关文件,并注入钩子命令,执行命令
npx husky add .husky/pre-commit "npm run lint-staged"
或通过 npm i husky-init 执行初始化页面
如果commit没触发钩子,原因是hook文件权限不足,需添加文件操作权限 chmod +x .husky/pre-commit
安装 npm i lint-staged, 并在 package.json 填写脚本
"lint-staged": {
"**/*.{vue,js,jsx,tsx,ts,less,md,json}": "npm run prettier"
配置 package.json
"script":{
"prepare": "husky install"
"lint-staged": {
"**/*.{vue,js,jsx,tsx,ts,less,md,json}": "npm run prettier"
安装 @commitlint/cli 和 @commitlint/config-conventional,执行以下命令
npm i @commitlint/cli @commitlint/config-conventional -D
添加 commit-msg 文件,执行以下命令
npx husky add .husky/
commit-msg 'yarn --no-install commitlint --edit "$1"'
新建 commitlint.config.js 配置文件
module.exports = { extends: ['@commitlint/config-conventional'] }
"editor.tabSize": 2,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
"source.fixAll.stylelint": true
"eslint.validate": ["vue", "html", "javascript", "typescript", "javascriptreact", "typescriptreact"],
"eslint.codeAction.showDocumentation": {
"enable": true
"eslint.format.enable": true,
"prettier.enable": true,
"prettier.semi": false,
"prettier.singleQuote": true,
"prettier.tabWidth": 2,
"prettier.printWidth": 800,
"prettier.useTabs": false,
"prettier.bracketSpacing": true,
"prettier.jsxBracketSameLine": true,
"prettier.arrowParens": "always",
"prettier.trailingComma": "none",
"vetur.format.options.tabSize": 2,
"vetur.validation.script": false,
"vetur.validation.interpolation": false,
"vetur.validation.template": false,
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"javascript.format.semicolons": "remove",
"vetur.format.defaultFormatter.html": "prettier",
"vetur.format.defaultFormatter.js": "prettier-eslint",
"vetur.format.defaultFormatter.ts": "prettier",
"vetur.format.defaultFormatter.css": "prettier",
"vetur.format.defaultFormatter.sass": "sass-formatter",
"vetur.format.defaultFormatter.postcss": "prettier",
"vetur.format.defaultFormatter.scss": "prettier",
"vetur.format.defaultFormatter.less": "prettier",
"vetur.format.defaultFormatter.stylus": "stylus-supremacy",
"stylelint.enable": true,
"stylelint.validate": ["css", "less", "postcss", "scss", "vue", "sass"]
复制代码
- 131
-
用户4070601636071
Vue.js