Vite + Vue3 + TS前端企业级项目搭建
想了解项目的最新动态,以及更多知识? 👉 mood-blog-front
文章目录
Vite脚手架构建项目
开发环境
- 开发编辑器:vscode-v1.84.2
- 包管理工具:pnpm -v8.10.5、npm-v10.2.3
- 脚手架:vite-v5.0.2
- Nodejs:node-v18.18.2
- 预编译样式:sass-v1.69.5
- 组件库:Element Plus-v2.4.2
- 浏览器:版本 119.0.6045.106(正式版本) (64 位)
- 状态管理:pinia-v2.1.7
- 国际化:vue-i18n-v9.4.1
- 路由管理:vue-router-v4.2.5
- Ajax请求:axios-v1.6.2、@types/axios-v0.14.0
- 生成注释插件:koroFileHeader-v4.9.3 (文件快捷键:ctrl + win + i,函数快捷键:ctrl + win + t,随机搞笑图:ctrl + win + j)
- 构建项目
pnpm create vite my-vue-app --template vue-ts
- 安装依赖
pnpm install
-
完整的
package.json
文件{ "name": "mood-blog-front", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite --host", "build": "vue-tsc && vite build", "build:pre": "vue-tsc --noEmit && vite build --mode staging", "build:pro": "vue-tsc --noEmit && vite build --mode production", "preview": "vite preview", "prepare": "husky install", "lint:create": "eslint --init", "lint:css": "stylelint **/*.{vue,css,sass,scss} --fix", "lint": "eslint \"src/**/*.{js,vue,ts,jsx,tsx}\" --fix", "format": "prettier --config .prettierrc.cjs \"src/**/*.{vue,js,ts,jsx,tsx}\" --write" }, "dependencies": { "axios": "^1.6.2", "dayjs": "^1.11.10", "element-plus": "^2.4.2", "normalize.css": "^8.0.1", "nprogress": "^0.2.0", "pinia": "^2.1.7", "qs": "^6.11.2", "vue": "^3.3.8", "vue-i18n": "^9.4.1", "vue-router": "^4.2.5" }, "lint-staged": { "*.{js,jsx,vue,ts,tsx}": [ "npm run lint", "npm run format" ], "*.{vue,sass,scss,css}": [ "npm run lint:css" ] }, "devDependencies": { "@commitlint/cli": "^18.4.3", "@commitlint/config-conventional": "^18.4.3", "@types/axios": "^0.14.0", "@types/eslint": "^8.44.7", "@types/node": "^20.10.0", "@types/nprogress": "^0.2.3", "@types/qs": "^6.9.10", "@typescript-eslint/eslint-plugin": "^6.12.0", "@typescript-eslint/parser": "^6.12.0", "@vitejs/plugin-vue": "^4.5.0", "eslint": "^8.54.0", "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-import": "^2.29.0", "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-vue": "^9.18.1", "husky": "^8.0.3", "lint-staged": "^15.1.0", "postcss": "^8.4.31", "postcss-html": "^1.5.0", "prettier": "^3.1.0", "sass": "^1.69.5", "stylelint": "^15.11.0", "stylelint-config-recommended-vue": "^1.5.0", "stylelint-config-standard": "^34.0.0", "stylelint-config-standard-scss": "^11.1.0", "typescript": "^5.3.2", "unplugin-auto-import": "^0.17.1", "unplugin-vue-components": "^0.25.2", "vite": "^5.0.0", "vite-plugin-eslint": "^1.8.1", "vite-plugin-stylelint": "^5.2.1", "vue-tsc": "^1.8.22", "pinia-plugin-persistedstate": "^3.2.0", "unplugin-vue-setup-extend-plus": "^1.0.0" } }
目录结构
mood-blog-front
├─ .env
├─ .env.development
├─ .env.production
├─ .env.staging
├─ .eslintrc.cjs
├─ .eslintrcignore
├─ .husky
│ ├─ commit-msg
│ ├─ pre-commit
│ └─ _
│ ├─ .gitignore
│ └─ husky.sh
├─ .prettierignore
├─ .prettierrc.cjs
├─ .stylelintcache
├─ .stylelintignore
├─ .stylelintrc.cjs
├─ auto-imports.d.ts
├─ commitlint.config.js
├─ components.d.ts
├─ index.html
├─ package.json
├─ pnpm-lock.yaml
├─ public
│ └─ vite.svg
├─ README.md
├─ src
│ ├─ api
│ │ └─ rest.ts
│ ├─ App.vue
│ ├─ assets
│ │ ├─ styles
│ │ │ ├─ base.scss
│ │ │ ├─ bem.scss
│ │ │ └─ index.scss
│ │ └─ vue.svg
│ ├─ components
│ │ └─ Layout
│ │ ├─ Foot
│ │ │ └─ index.vue
│ │ ├─ Head
│ │ │ └─ index.vue
│ │ ├─ index.vue
│ │ ├─ Main
│ │ │ └─ index.vue
│ │ └─ Sider
│ │ └─ index.vue
│ ├─ global
│ │ └─ index.ts
│ ├─ lang
│ │ ├─ en
│ │ │ └─ index.ts
│ │ ├─ index.ts
│ │ └─ zh
│ │ └─ index.ts
│ ├─ main.ts
│ ├─ plugins
│ │ └─ nprogress
│ │ └─ index.ts
│ ├─ router
│ │ ├─ dynamicRoutes.ts
│ │ ├─ index.ts
│ │ └─ promission.ts
│ ├─ store
│ │ ├─ mainStore.ts
│ │ └─ namespace.ts
│ ├─ types
│ │ ├─ Api
│ │ │ ├─ index.ts
│ │ │ ├─ rest.ts
│ │ │ └─ user.ts
│ │ └─ core
│ │ └─ index.ts
│ ├─ utils
│ │ ├─ dayjs.ts
│ │ ├─ request.ts
│ │ └─ types
│ ├─ views
│ │ └─ Home.vue
│ └─ vite-env.d.ts
├─ tsconfig.json
├─ tsconfig.node.json
└─ vite.config.ts
TypeScript
依赖安装
pnpm install typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-import-resolver-alias @types/eslint @types/node -D
配置文件
// tsconfig.json
{
"compilerOptions": {
// 编译成es最新的版本代码
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
// 编译过程中需要引入的库文件的列表
"lib": [
"ESNext",
"DOM",
"DOM.Iterable"
],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "Node",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
// "isolatedModules": true,
"noEmit": true,
"jsx": "preserve",
/* Linting */
"strict": true,
"strictNullChecks": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"esModuleInterop": true,
"skipDefaultLibCheck": true,
// 默认所有可见的"@type"包惠在编译过程中被包含进来
"types": [
"vite/client"
],
// 解析非相对模块名的基准目录
"baseUrl": ".",
// 模块名到基于baseUrl的路径映射
"paths": {
"@/*": [
"src/*"
],
"*.ts": [
"*"
]
}
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"src/**/*.d.ts"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}
ESlint
依赖安装
这里顺带将
prettier
的相关依赖也引入了
pnpm install eslint eslint-plugin-vue eslint-config-prettier prettier eslint-plugin-import eslint-plugin-prettier eslint-config-airbnb-base -D
初始化
将该命令粘贴到
package.json
文件的scripts
中,在终端使用npm run lint:create
。
ESlint
配置好后在终端使用第二行命令进行语法检查,npm run lint
"lint:create": "eslint --init",
"lint": "eslint \"src/**/*.{js,vue,ts,jsx,tsx}\" --fix"
配置文件
.eslintrc.cjs
module.exports = {
"env": {
"browser": true,
"es2021": true,
"node": true,
"vue/setup-compiler-macros": true,
},
"extends": [
"plugin:vue/vue3-strongly-recommended",
"airbnb-base",
"prettier"
],
// ESlint会对代码校验,parser的作用是将代码转换成ESTree(AST语法树)进行代码校验
"parser": "vue-eslint-parser",
"parserOptions": {
// es版本号或年份
"ecmaVersion": 13,
"parser": "@typescript-eslint/parser",
// 源码类型 默认是script, es模块使用module
"sourceType": "module",
// 额外的语言类型
"ecmaFeatures": {
"tsc": true,
"jsx": true
}
},
// 全局自定义的宏,这样在源文件中使用全局变量不会报错或警告
"globals": {
"defireProps": "readonly",
"defineEmits": "readonly",
"defineExpose": "readonly",
"withDefaults": "readonly",
},
// 前缀eslint-plugin- 可以省略
// vue官方提供了一个ESlint插件————eslint-plugin-vue,它提供了parser和rules。
// parse:vue-eslint-parser放在上面的parsers里,rules放在extends字段里,选择合适的规则
"plugins": [
"vue",
"@typescript-eslint"
],
"settings": {
// 项目内别名
"import/resolver": {
"alias": {
map: [
["@", "./src"]
]
}
},
// 允许的拓展名
"import/extensions": [".js", ".jsx", ".ts", ".tsx", ".mjs"]
},
// 自定义规则, 覆盖上面extends继承的第三方库的规则,根据组内成员灵活定义
"rules": {
"import/no-extraneous-dependencies": 0,
"no-param-reassign": 0,
"vue/multi-word-component-names": 0,
"vue/attribute-hyphenation": 0,
"vue/v-on-event-hyphenation": 0,
'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
'vue/no-v-for-template-key': 'off', // vue3 v-for 中template 可以设置key
'@typescript-eslint/no-explicit-any': 'off', // 表示禁用此规则,允许使用 any 类型
'@typescript-eslint/no-var-requires': 'off', // 禁止使用 require() 导入。off 表示禁用此规则,允许使用 require()。
"eqeqeq": ['error', 'always'], // 要求使用恒等(===)而不是等于(==)进行比较,否则报错。
'vue/no-multiple-template-root': 'off', // vue3 模板可以有多个根结点
'vue/custom-event-name-casing': 'off', // 自定义 Vue.js 事件名称的大小写规则。off 表示禁用此规则。
'no-use-before-define': 'error', // 禁止在定义之前使用变量。error 表示将此视为错误
'guard-for-in': 'error', // 要求在 for-in 循环中使用 hasOwnProperty 方法进行条件过滤,否则报错。
'consistent-this': ['error', '_this', 'that', 'self'], // 要求在代码中使用指定的别名代替 this(_this、that、self),否则报错。
}
}
.eslintrcignore
*.sh
node_modules
*.nd
*.woff
*.ttf
.vscode
.idea
dist
/pub1ic
/docs
.husky
/bin
.es7intrc.js
prettier.config.js
/src/mock/*
# Logs
lags
*.log
npm-debug.1og*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
.DS_Store
dist-ssr
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode
!.vscode/extendsions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
components.d.ts
Prettier
将这行命令粘贴到
package.json
文件的scripts
中,终端运行npm run format
,进行代码格式的校验。
"format": "prettier --config .prettierrc.cjs \"src/**/*.{vue,js,ts,jsx,tsx}\" --write"
配置文件
.prettierrc.cjs
module.exports = {
// 超过最大值换行
"printWidth": 120,
// 缩进字节数
"tabWidth": 2,
// 缩进不使用tab,使用空格
"useTabs": false,
// 句尾添加分号
"semi": false,
// 使用单引号代替双引号
"singleQuote": true,
// 默认值。因为使用了一些折行敏感型的渲染器(如GitHub comment)而按照markdown文本样式进行折行
"proseWrap": "preserve",
// (x) => {} 箭头函数参数只有一个时是否要有小括号。avoid:省略括号
"arrowParens": "always",
// 在对象,数组括号与文字之间加空格 "{ foo: bar }"
"bracketSpacing": true,
// 不格式化vue文件,vue文件的格式化单独设置
// "disableLanguages": ["vue"],
// 结尾是 \n \r \n\r auto
"endOfLine": "auto",
// 不让prettier使用eslint的代码格式进行校验
// "eslintIntegration": false,
"htmlWhitespaceSensitivity": "ignore",
// 不使用prettier格式化的文件填写在项目的.prettierignore文件中
// "ignorePath": ".prettierignore",
// 在jsx中把'>' 是否单独放一行
// "jsxBracketSameLine": false,
// 在jsx中使用单引号代替双引号
"jsxSingleQuote": false,
// 格式化的解析器,默认是babylon
// "parser": "babylon",
// Require a 'prettierconfig' to format prettier
// "requireConfig": false,
//不让prettier使用stylelint的代码格式进行校验
// "stylelintIntegration": false,
// 在对象或数组最后一个元素后面是否加逗号(在ES5中加尾逗号)
"trailingComma": "es5",
// 不让prettier使用tslint的代码格式进行校验
// "tslintIntegration": false,
// 每个文件格式化的范围是文件的全部内容
"rangeStart": 0,
"rangeEnd": Infinity,
// 不需要自动在文件开头插入@prettier
"insertPragma": false,
// 使用默认的这行标准
"proseWrap": "always",
// 对象的key仅在必要时使用引号
"quoteProps": "as-needed"
}
.prettierignore
/dist/*
.local
.output.js
/node_modules/**
src/.DS_Store
**/*.svg
**/*.sh
/public/*
components.d.ts
Husky、Lint-staged
依赖安装
pnpm install husky lint-staged -D
相关配置
-
添加命令到
package.json
的scripts
中,npm run prepare
安装husky。"prepare":"husky install"
-
添加
lint-staged
到package.json
文件中。"lint-staged": { "*.{js,jsx,vue,ts,tsx}": [ "npm run lint", "npm run format" ] },
-
添加git hooks的
pre-commit
,在终端执行以下命令。此步骤完成后,再commit
时,会先执行lint
和format
,代码的语法和格式校验,
npx husky add .husky/pre-commit "npx lint-staged"
Commitlint
commitlint
用于规范代码提交
依赖安装
pnpm i @commitlint/config-conventional @commitlint/cli -D
添加到husky
npx husky add .husky/commit-msg "npx --no -- commitlint --edit ${1}"
配置文件
这里使用的es module, 所以导出使用的是export default, 如果用的command module,使用module.exports
// commitlint.config.js
// more:https://github.com/angular/angular/blob/main/CONTRIBUTING.md
export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
[
'build', // 编译相关的修改,如发布版本,对项目构建或依赖的改动
'ci', // 对CI 配置文件和脚本的更改
'chore', // 构建过程或辅助工具的变动,比如增加依赖库等
'update', // 更新功能
'docs', // 文档变动 documentation
'feat', // 新增功能 feature
'fix', // 修复bug
'perf', // 性能优化 performance
'refactor', // 重构
'revert', // 撤回commit,回滚上一个版本
'style', // 格式(不影响代码运行的变动)
'test', // 测试(单元/集成测试)
],
],
'type-case': [0],
'type-empty': [0],
'scope-empty': [0],
'scope-case': [0],
'subject-full-stop': [0, 'never'],
'subject-case': [0, 'never'],
'header-max-length': [0, 'always', 100],
},
}
测试
可以尝试在
commit
时不使用规范的提交消息,看是否报错。如果不想按照以下规范提交,可以使用git commit -m "your commit message" --no-verify
git add .
git commit -m "chore: init"
Stylelint
依赖安装
vite-plugin-stylelint
是一个插件,需要在vite.config.ts
文件中的plugins中使用
pnpm i postcss-html stylelint-config-standard-scss stylelint-config-recommended-vue vite-plugin-stylelint postcss -D
添加命令
使用
npm run lint:css
,或尝试commit
提交代码,看是否会在提交之前进行样式文件的语法检查。
"lint:css": "stylelint **/*.{vue,css,sass,scss} --fix"
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"npm run lint",
"npm run format"
],
// 新增
"*.{vue,sass,scss,css}": [
"npm run lint:css"
]
},
配置文件
我这里使用的是
scss
的语法检查,可自行集成pnpm install sass -D
.stylelintrc.cjs
module.exports = {
extends: [
"stylelint-config-standard-scss",
"stylelint-config-recommended-vue/scss"
]
}
.stylelintignore
/dist/*
.local
.output.js
/node_modules/**
/public/*
测试
- 新建分支
git branch release/v1.0.0
- 切换分支
git checkout release/v1.0.0
- 编写代码后,提交分支上的代码
git add . git commit -m "chore: XXXXX"
- 切回主分支
git checkout <主分支名称>
- 合并分支
git merge release/v1.0.0
- 提交代码
git commit -m "chore: XXXXX"
- 添加遥控仓库,推送代码
git remote add <名称> <仓库地址> git push -u <名称> <主分支名称>
- 发布版本,打上标签
npm run release git push --follow-tags <名称> <主分支名称> // npm publish 发布到npm