- 支持vue3
- 支持typescript
- 支持eslint、prettier和editorconfig
- git hooks
- 别名
- 样式
- 静态资源
- mock
- axios请求封装
- pinia状态管理
- 路由
- element-ui组件库
- 环境变量和模式
1. 安装vite
cnpm i vue @vitejs/plugin-vue @vue/compiler-sfc vite -D
1.1 配置文件
- vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()]
})
- package.json
{
"name": "vite-plugin",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint --ext .ts,.tsx,vue src/** --no-error-on-unmatched-pattern --quiet",
"lint:fix": "eslint --ext .ts,.tsx,vue src/** --no-error-on-unmatched-pattern --quiet --fix",
"prepare": "husky install"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"@vitejs/plugin-vue": "^5.0.5",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"eslint": "^9.6.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-vue": "^9.27.0",
"mrm": "^4.1.22",
"prettier": "^3.3.2",
"typescript": "^5.5.3",
"vite": "^5.3.3",
"vue": "^3.4.31",
"vue-tsc": "^2.0.26"
},
"dependencies": {
"husky": "^9.0.11",
"lint-staged": "^15.2.7"
},
"lint-staged": {
"*.{ts,vue}": "eslint --cache --fix"
}
}
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
- src\main.js
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App)
app.mount("#app");
- src\App.vue
<script setup lang="ts">
import HelloWorld from "@/components/HelloWorld.vue"
import { ref } from "vue";
const msg = ref('1111')
</script>
<template>
<HelloWorld :msg="msg" />
</template>
<style></style>
完整具体目录结构
2. 静态资源处理
2.1 模块导入
- Vite 支持通过 ES 模块的方式直接导入静态资源,例如图片、CSS 文件等。这使得开发者可以像导入 JavaScript 模块一样导入静态资源,不需要像传统的打包工具那样配置额外的 loader 或者处理器。
2.2. 内置的优化
- Vite 在开发模式下,通过使用原生 ES 模块的特性,能够实现快速的热更新和开发服务器响应。这意味着即使在大型项目中,对静态资源的修改也能够快速地反映在浏览器中,大大提高了开发效率。
2.3 按需编译
- 在生产模式下,Vite 可以根据需要对静态资源进行按需编译。这与传统的打包工具不同,后者往往将整个项目的静态资源打包成一个或多个文件,而 Vite 则可以根据实际使用情况,动态生成最优的输出文件。
2.4 自动优化路径
- Vite 能够根据导入的静态资源路径,自动优化处理。例如,对于在 CSS 中引入的背景图片,Vite 能够正确地处理路径,并生成对应的最终输出文件。
2.5插件扩张
- Vite 的插件系统允许开发者根据需要扩展静态资源处理的功能。开发者可以编写自定义的插件来处理特定类型的静态资源,或者优化输出结果。
2.6 模板中引入
- 静态资源处理
- 服务时引入一个静态资源会返回解析后的公共路径 src\App.vue
<template>
+ <img src="./assets/avatar.jpg" />
</template>
2.7 JS中引入
<template>
<img src="./assets/avatar.jpg" />
+ <img :src="imgUrl" />
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<script setup>
//https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
import HelloWorld from './components/HelloWorld.vue'
+import imgUrl from './assets/avatar.jpg'
</script>
2.8 CSS中引入
<template>
<img src="./assets/avatar.jpg" />
<img :src="imgUrl" />
+ <div class="avatar"></div>
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<script setup>
//https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
import HelloWorld from './components/HelloWorld.vue'
import imgUrl from './assets/avatar.jpg'
</script>
+<style scoped>
+.avatar{
+ width:200px;
+ height:200px;
+ background-image: url(./assets/avatar.jpg);
+ background-size: contain;
+}
+</style>
2.9 public目录
-
public目录
-
如果有以下需求
- 这些资源不会被源码引用(例如 robots.txt)
- 这些资源必须保持原有文件名(没有经过 hash)
-
那么你可以将该资源放在指定的
public目录中,它应位于你的项目根目录 -
该目录中的资
-
源在开发时能直接通过
/根路径访问到,并且打包时会被完整复制到目标目录的根目录下
public\avatar.jpg
3.配置别名
vite.config.js
import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import { resolve } from "path"
export default defineConfig({
resolve: {
alias: {
"@": resolve("src")
}
},
plugins: [vue()]
})
- src\App.vue
<template>
<img src="@/assets/avatar.jpg" />
<img :src="avatarUrl" />
<div class="avatar"></div>
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<script setup>
//https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
+import HelloWorld from "@/components/HelloWorld.vue";
+import avatarUrl from "@/assets/avatar.jpg";
</script>
<style scoped>
.avatar {
width: 200px;
height: 200px;
background-image: url(@/assets/avatar.jpg);
background-size: contain;
}
</style>
4. 样式处理
4.1 全局样式
- src\main.js
import { createApp } from 'vue'
import App from './App.vue'
import './global.css'
createApp(App).mount('#app')
- src\global.css
#app {
background-color: lightgrey;
}
4.2 局部样式
4.2.1 scoped
- 当
<style>标签有scoped属性时,它的 CSS 只作用于当前组件中的元素 - 它使用了
data-v-hash的方式来使css有了它对应模块的标识 - src\components\HelloWorld.vue
<template>
<h1>{{ msg }}</h1>
<a>超链接</a>
</template>
<style scoped>
a {
color: #42b983;
}
</style>
4.2.2 CSS Modeles
- CSS Modules
- 通过
module作用的style都被保存到$style对象中
4.2.2.1 内联
- src\components\HelloWorld.vue
<template>
<h1>{{ msg }}</h1>
<a :class="$style.link">超链接</a>
</template>
<style module>
.link {
color: #42b983;
}
</style>
4.2.2.2 外联
- 任何以 .module.css 为后缀名的 CSS 文件都被认为是一个 CSS modules 文件
- 导入这样的文件会返回一个相应的模块对象 src\components\HelloWorld.vue
<template>
<h1>{{ msg }}</h1>
+ <a :class="style.link">超链接</a>
</template>
<script setup>
+import style from './HelloWorld.module.css';
</script>
- src\components\HelloWorld.module.css
.link {
color: #42b983;
}
4.3 less和sass
- Vite 也同时提供了对 .scss, .sass, .less, .styl 和 .stylus 文件的内置支持。没有必要为它们安装特定的 Vite 插件,但必须安装相应的预处理器依赖
- 如果是用的是单文件组件,可以通过
style lang="sass"(或其他预处理器)自动开启
cnpm i less sass -S
<template>
<h1>{{ msg }}</h1>
<a :class="style.link">超链接</a>
<h2>less</h2>
<h3>sass</h3>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const msg = ref('111')
import style from './components/HelloWorld.module.css';
</script>
<style scoped lang="less">
@color: red;
h2 {
color: @color;
}
</style>
<style scoped lang="scss">
$color: green;
h3 {
color: $color;
}
</style>
5. typescript
5.1 安装
cnpm install typescript @babel/core @babel/preset-env @babel/preset-typescript --save-dev
5.2 .babelrc
.babelrc
{
"presets": [
["@babel/preset-env"],
"@babel/preset-typescript"
]
}
5.3 tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
5.4 HelloWorld.vue
src\components\HelloWorld.vue
<template>
<h1>{{ msg }}</h1>
<h2>less</h2>
<h3>sass</h3>
<div class="postcss"></div>
+ <button @click="handleClick">{{state.count}}</button>
</template>
<script setup lang="ts">
import { reactive,defineProps } from 'vue'
+defineProps({
+ msg:String
+})
+interface State {
+ count:number;
+}
+let state = reactive<State>({count:0});
+const handleClick = ()=>{
+ console.log(state.count);
+ state.count++;
+}
</script>
<style scoped lang="less">
@color:red;
h2{
color:@color;
}
</style>
<style scoped lang="scss">
$color:green;
h3{
color:$color;
}
</style>
<style scoped>
.postcss{
height:50px;
width:200px;
background-color: orange;
transform: rotate(90deg);
}
</style>
5.5 shims-vue.d.ts
- 让typescript识别支持
.vue文件
src\shims-vue.d.ts
declare module '*.vue' {
import { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
5.6 vite-env.d.ts
- 如果你的库依赖于某个全局库,使用/// 指令
- 三斜线指令仅可放在包含它的文件的最顶端
- 三斜线引用告诉编译器在编译过程中要引入的额外的文件
src\vite-env.d.ts
/// <reference types="vite/client" />
6. 配置代理
- server-proxy
- 为开发服务器配置自定义代理规则
- 期望接收一个 { key: options } 对象。如果 key 值以 ^ 开头,将会被解释为 RegExp。configure 可用于访问 proxy 实例。
6.1 vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path';
// https://vitejs.dev/config/
export default defineConfig({
resolve: {
alias: {
'@': resolve('src')
}
},
+ server: {
+ proxy: {
+ '/api': {
+ target: 'http://jsonplaceholder.typicode.com',
+ changeOrigin: true,
+ rewrite: (path) => path.replace(/^/api/, '')
+ }
+ }
+ },
plugins: [vue()]
})
6.2 src\App.vue
src\App.vue
<template>
<img src="@/assets/avatar.jpg" />
<img :src="avatarUrl" />
<div class="avatar"></div>
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<script setup>
//https://github.com/vuejs/rfcs/blob/master/active-rfcs/0040-script-setup.md
import HelloWorld from "@/components/HelloWorld.vue";
import avatarUrl from "@/assets/avatar.jpg";
+fetch('/api/todos/1')
+ .then(response => response.json())
+ .then(json => console.log(json))
</script>
<style scoped>
.avatar {
width: 200px;
height: 200px;
background-image: url(@/assets/avatar.jpg);
background-size: contain;
}
</style>
7. ESLint
-
ESLint是一个开源的 JavaScript 的 linting 工具
- 代码质量问题:使用方式有可能有问题
- 代码风格问题:风格不符合一定规则
npm install eslint eslint-plugin-vue @vue/eslint-config-typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
7.1 src\components\HelloWorld.vue
src\components\HelloWorld.vue
<template>
<h1>{{ msg }}</h1>
<h2>less</h2>
<h3>sass</h3>
<div class="postcss" />
<button @click="handleClick">
{{ state.count }}
</button>
</template>
<script setup lang="ts">
import { reactive,defineProps } from 'vue'
defineProps({
+ msg:{
+ type:String,
+ default:''
+ }
})
interface State {
count:number;
}
let state = reactive<State>({count:0});
const handleClick = ()=>{
console.log(state.count);
state.count++;
}
</script>
<style scoped lang="less">
@color:red;
h2{
color:@color;
}
</style>
<style scoped lang="scss">
$color:green;
h3{
color:$color;
}
</style>
<style scoped>
.postcss{
height:50px;
width:200px;
background-color: orange;
transform: rotate(90deg);
}
</style>
7.2 main.ts
src\main.ts
import { createApp } from 'vue'
import App from './App.vue'
import './global.css'
createApp(App).mount('#app')
7.3 .eslintrc.js
.eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true
},
extends: [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/typescript/recommended"
],
parserOptions: {
ecmaVersion: 2021
},
rules: {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
}
}
7.4 .eslintignore
.eslintignore
*.css
*.jpg
*.jpeg
*.png
*.gif
*.d.ts
Prettier
-
ESLint 主要解决的是代码质量问题
-
代码质量规则 (code-quality rules)
- no-unused-vars
- no-extra-bind
- no-implicit-globals
- prefer-promise-reject-errors
-
代码风格规则 (code-formatting rules)
- max-len
- no-mixed-spaces-and-tabs
- keyword-spacing
- comma-style
-
代码风格问题需要使用
Prettier -
Prettier 声称自己是一个有主见的代码格式化工具 (opinionated code formatter)
8. 安装
npm install prettier eslint-plugin-prettier @vue/eslint-config-prettier --save-dev
8.1 .eslintrc.js
.eslintrc.js
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"plugin:vue/vue3-recommended",
"eslint:recommended",
"@vue/typescript/recommended",
+ "@vue/prettier",
+ "@vue/prettier/@typescript-eslint",
],
parserOptions: {
ecmaVersion: 2021,
},
rules: {
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "off",
+ "prettier/prettier": ["error", { endOfLine: "auto" }],
},
};
9. git hook
- 可以在
git commit之前检查代码,保证所有提交到版本库中的代码都是符合规范的 - 可以在
git push之前执行单元测试,保证所有的提交的代码经过的单元测试 - husky可以让我们向项目中方便添加git hooks
- lint-staged用于实现每次提交只检查本次提交所修改的文件
- lint-staged#configuration
- Commitlint可以规范
git commit -m ""中的描述信息
9.1 注释规范
-
commitlint 推荐我们使用 config-conventional 配置去写 commit
-
提交格式
git commit -m <type>[optional scope]: <description>- type :用于表明我们这次提交的改动类型,是新增了功能?还是修改了测试代码?又或者是更新了文档?
- optional scope:一个可选的修改范围。用于标识此次提交主要涉及到代码中哪个模块
- description:一句话描述此次提交的主要内容,做到言简意赅
9.1.1 type类型
| 类型 | 描述 |
|---|---|
| build | 编译相关的修改,例如发布版本、对项目构建或者依赖的改动 |
| chore | 其他修改, 比如改变构建流程、或者增加依赖库、工具等 |
| ci | 持续集成修改 |
| docs | 文档修改 |
| feature | 新特性、新功能 |
| fix | 修改bug |
| perf | 优化相关,比如提升性能、体验 |
| refactor | 代码重构 |
| revert | 回滚到上一个版本 |
| style | 代码格式修改 |
| test | 测试用例修改 |
9.2 安装
cnpm i husky lint-staged @commitlint/cli @commitlint/config-conventional --save-dev
9.3 配置脚本
prepare脚本会在npm install(不带参数)之后自动执行- 当我们执行npm install安装完项目依赖后会执行
husky install命令,该命令会创建.husky/目录并指定该目录为git hooks所在的目录
npm set-script prepare "husky install"
npm run prepare
9.4 创建hooks
npx husky add .husky/pre-commit "lint-staged"
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
npx husky add .husky/pre-push "npm run test"
9.5 commitlint.config.js
commitlint.config.js
module.exports = {
extends: ["@commitlint/config-conventional"],
rules: {
"type-enum": [
2,
"always",
[
"feature",
"update",
"fixbug",
"refactor",
"optimize",
"style",
"docs",
"chore",
],
],
"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", 72],
},
};