项目搭建的过程

项目初始化

  • 创建
1
yarn create vite

截图
  • 安装依赖
1
2
cd my-vite-demo
yarn

截图
  • 运行
1
yarn dev

截图

构建生产环境和预览环境

  • 修改配置文件vite.config.ts

    根据模式对环境做相关配置

1
2
3
4
5
export default defineConfig(({ mode }) => {
return {
plugins: [vue()],
};
});

  • 新增环境文件.env

    一份用于指定模式的文件(例如 .env.production)会比通用形式的优先级更高(例如 .env)

    已经存在的环境变量有最高的优先级,不会被 .env 类文件覆盖

    .env 类文件会在 Vite 启动一开始时被加载,而改动会在重启服务器后生效


截图
  • 添加Typescript提示

    src目录下的 env.d.ts 文件

1
2
3
4
5
6
7
8
9
10
/// <reference types="vite/client" />

interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
// 更多环境变量...
}

interface ImportMeta {
readonly env: ImportMetaEnv
}

  • 环境变量配置

    配置端口、mock服务开关、基础路径等等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// .env

# port
VITE_PORT = 3000

VITE_USE_MOCK = true
VITE_MOCK_URL = http://127.0.0.1:8888/mock/8888
#---------------------------------------------------------
//.env.development
NODE_ENV=development

VITE_PUBLIC_PATH = /
VITE_BASE_URL = http://192.168.1.123:2323/demo/api
#---------------------------------------------------------
// .env.production
NODE_ENV=production
VITE_OUTPUT_DIR = dist

VITE_DROP_CONSOLE = true //删除console
VITE_DROP_DEBBUGER = true //删除debug

VITE_PUBLIC_PATH = /
VITE_BASE_URL = /demo/api
#---------------------------------------------------------
// .env.preview
NODE_ENV=preview
VITE_OUTPUT_DIR = preview

VITE_DROP_CONSOLE = false
VITE_DROP_DEBBUGER = false


VITE_PUBLIC_PATH = /
VITE_BASE_URL = http://192.168.1.123:2323/demo/api


  • vite配置

    安装 yarn add @types/node -D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import { defineConfig, loadEnv } from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
const root = process.cwd();//获取环境根路径
// 根据当前工作目录中的 `mode` 加载 .env 文件
// 设置第三个参数为 '' 来加载所有环境变量,而不管是否有 `VITE_` 前缀。
const env = loadEnv(mode, root);

const dropConsole: boolean = env.VITE_DROP_CONSOLE !== 'false'; //删除console
const dropDebugger: boolean = env.VITE_DROP_DEBBUGER !== 'false';//删除debug

return {
base: env.VITE_PUBLIC_PATH, //基础路径
resolve: {
alias: [
{
find: '@/', //配置别名
replacement: `${resolve(root, './src')}/`
}
]
},
server: { //dev
host: true, //配置host
port: Number(env.VITE_PORT), //配置端口
open: true //运行时打开
},
build: { //生产环境
target: 'es2015',
outDir: env.VITE_OUTPUT_DIR, //输出路径
minify: 'terser',
terserOptions: {
compress: {
keep_infinity: true,
drop_console: dropConsole, //删除console
drop_debugger: dropDebugger //删除debugger
}
},
chunkSizeWarningLimit: 2000
},
preview: { //本地预览环境
host: true,
open: true
},
plugins: [
vue(),
]
};
});


  • 配置脚本

    制定相应环境模式 –mode

1
2
3
4
5
6
7
// package.json

"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "npm run build && vite build --mode preview && vite preview --mode preview",
},

  • 配置ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"skipLibCheck": true,
"baseUrl": "./",
"paths": {
"@/*": ["src/*"] // 别名路径
},
"types": ["vite/client"]
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
],
"exclude": ["node_modules", "dist", "preview"],
"references": [{ "path": "./tsconfig.node.json" }]
}


添加自动导入Vue Api

  • 安装
1
2
3
npm i unplugin-auto-import unplugin-vue-components -D
# or
yarn add unplugin-auto-import unplugin-vue-components -D
  • 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite';
import Components from 'unplugin-vue-components/vite';

export default defineConfig({
plugins: [
vue(),
AutoImport({
imports: ['vue']
// dts: 'src/auto-imports.d.ts'
}),
Components({

}),
],
})

1
2
3
4
5
// .eslintrc.js

rules: {
'no-undef': 'off'
}

element-ui plus 自动导入参考官方文档

来源:unplugin-vue-components


接入现代CSS工程化

集成sass

  • 安装css预处理器
1
yarn add sass -D
  • 新建css文件
1
2
3
4
// src/assets/style/main.scss

$test-color: blue;

  • 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
// vite.config.ts
export default defineConfig(({ mode }) => {
return {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/style/main.scss";',
},
},
},
plugins: [vue()],
};
});
  • 使用
1
color: $test-color

集成 WindiCSS

  • 安装
1
yarn add windicss vite-plugin-windicss -D
  • 配置
1
2
3
4
5
6
7
8
9
// vite.config.ts
import windi from "vite-plugin-windicss";

export default defineConfig(({ mode }) => {
return {
plugins: [vue(), windi()],
};
});

  • 引入css

    配置添加相关配置文件,查阅windicss官方文档

1
2
3
// main.ts
import 'virtual:windi.css';
import 'virtual:windi-devtools'; //开发时浏览器工具
  • 使用
1
2
3

class="bg-red-200 p-2 border-10 border-yellow-500 text-blue-600 hover:bg-purple-400"


约束代码风格

Eslint

  • 安装
1
yarn add eslint -D
  • 初始化
1
yarn eslint --init

截图

选中相应的配置进行安装

eslint-plugin-vue

规范等级:

base 基础
essential 预设
strongly-recommended 推荐
recommended 最严谨

vue3:

Vue 3.x 需要加上 vue3 前綴,’plugin:vue/vue3-essential’

Airbnb:

Airbnb JavaScript编码规范指南(ES6)中文版


  • 配置

    安装完后自动生成 .eslintrc.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
'plugin:vue/essential',
'airbnb-base',
],
parserOptions: {
ecmaVersion: 'latest',
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
plugins: [
'vue',
'@typescript-eslint',
],
rules: {
},
};

安装yarn add eslint-define-config -D

修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// eslint-define-config可以帮助我们做语法提示
import defineConfig from "eslint-define-config";

module.exports = defineConfig({
env: {
browser: true,
es2021: true,
node: true,
},
extends: ["plugin:vue/essential", "airbnb-base"],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint"],
rules: {},
});


新增 ESLint 規則,避免 Vite2 环境下错误提示和额外的一些配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rules: {
// 单引号
quotes: ['error', 'single'],
// 行末分号
semi: ['error', 'always'],

// 配置规则避免 Vite2 环境下错误
'import/no-unresolved': 'off',
'import/no-extraneous-dependencies': 'off',
'import/extensions': 'off',
'global-require': 'off',
// 'vue/script-setup-uses-vars': 'off' // 如果使用 script-setup 可开启
// 关掉其他一些规则
'no-plusplus': 'off',
'no-undef': 'off',
'vue/multi-word-component-names': 'off'
}


创建 .eslintignore 来配置eslint需要忽略哪些文件或者文件夹

1
2
3
node_modules
dist
preview

Prettier

  • 安装
1
yarn add prettier -D
  • 配置

    项目根目录创建 .prettierrc.js

1
2
3
4
5
6
7
8
9
module.exports = {
printWidth: 80, //一行的字符数,如果超过会进行换行,默认为80
tabWidth: 2, // 一个 tab 代表几个空格数,默认为 2 个
useTabs: false, //是否使用 tab 进行缩进,默认为false,表示用空格进行缩减
singleQuote: true, // 字符串是否使用单引号,默认为 false,使用双引号
semi: true, // 行尾是否使用分号,默认为true
trailingComma: 'none', // 是否使用尾逗号
bracketSpacing: true // 对象大括号直接是否有空格,默认为 true,效果:{ a: 1 }
};

配置项


创建 .prettierignore来配置prettire忽略文件或者文件夹

1
2
3
node_modules
dist
preview

集成Prettier到ESLint工具中

  • 安装
1
yarn add eslint-config-prettier eslint-plugin-prettier -D

eslint-config-prettier用来覆盖 ESLint 本身的规则配置,而eslint-plugin-prettier则是用于让 Prettier 来接管eslint –fix即修复代码的能力

  • 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
// .eslintrc.js

parser: 'vue-eslint-parser' /* 解析.vue文件,需要制定解析vue文件解析器,否则报错*/,
extends: [
// 继承ts规则,extends 字段即可自动开启插件中的推荐规则
'plugin:@typescript-eslint/recommended',
'prettier', // 接入 prettier 的规则
'plugin:prettier/recommended', // eslint-config-prettier 的缩写
],
rules: {
// 开启 prettier 自动修复的功能
'prettier/prettier': 'error',
}
  • 解决vue3 defineProps' is not defined问题
1
2
3
4
5
6
7
8
// .eslintrc.js

globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly'
},
  • 配置相关脚本
1
2
3
4
//package.json
"scripts": {
"lint:script": "eslint --ext .js,.jsx,.ts,.tsx,.vue --fix ./",
},
  • 安装插件

    在VSCode中安装ESLintPrettier这两个插件,并且在设置区中开启Format On Save,保存自动格式化。


Stylelint

  • 安装
1
yarn add stylelint stylelint-prettier stylelint-config-prettier stylelint-config-recess-order stylelint-config-standard stylelint-config-standard-scss -D
  • 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// .stylelintrc.js
module.exports = {
// 注册 stylelint 的 prettier 插件
plugins: ['stylelint-scss', 'stylelint-prettier'],
// 继承一系列规则集合
extends: [
// standard 规则集合
'stylelint-config-standard',
// standard 规则集合的 scss 版本
'stylelint-config-standard-scss',
// 样式属性顺序规则
'stylelint-config-recess-order',
// 接入 Prettier 规则
'stylelint-config-prettier',
'stylelint-prettier/recommended'
],
// 配置 rules
rules: {
// 开启 Prettier 自动格式化功能
'prettier/prettier': true,
'at-rule-no-unknown': null,
'scss/at-rule-no-unknown': true
}
};

  • 配置脚本
1
2
3
4
// package.json
"scripts": {
"lint:style": "stylelint --fix \"src/**/*.{css,scss}\""
},

其他集成

路由

  • 安装
1
yarn add vue-router@4
  • 新建路由文件src/router/index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';

const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: { requiresAuth: true }
},
];

const router = createRouter({
history: createWebHashHistory(),
routes,
});

export default router;

  • 添加ts类型支持自定义meta提示
1
2
3
4
5
6
7
8
9
10
import 'vue-router';

declare module 'vue-router' {
interface RouteMeta {
// 是可选的
isAdmin?: boolean;
// 每个路由都必须声明
requiresAuth: boolean;
}
}

官网:Vue Router


Pinia 状态管理

  • 安装
1
2
3
yarn add pinia
# 或者使用 npm
npm install pinia
  • 配置插件
1
2
3
4
//main.ts
import { createPinia } from 'pinia'

app.use(createPinia())
  • 分模块建立独立文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// user.ts
import { defineStore } from 'pinia';

const useUserStore = defineStore('user', {
state: () => {
return { count: 0 };
},
// 也可以定义为
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++;
}
}
});

export default { useUserStore };

Animate.css

  • 安装
1
yarn add animate.css
  • 引入
1
2
// main.ts
import 'animate.css';
  • 使用
1
2
3
4
5
6
7
8
 <transition
name="animate"
enter-active-class="animate__zoomIn"
leave-active-class="animate__zoomOut"
class="animate__animated"
>
<div></div>
</transition>

时间日期格式话工具moment.js

见其他短文

Axios + VueRequest

见其他短文

UI库 Element Plus

官网:Element Plus


参考来源:

详解从零搭建企业级 vue3 + vite2+ ts4 框架全过程

Vite2 + Vue3 + TypeScript + Pinia 搭建一套企业级的开发脚手架

vue3中加入eslint和prettier

Vite2 + Vue 3 + TypeScript + WindiCSS