基础框架项目从零搭建的过程
因公司需要搭建一个基础框架提供后续系统的开发,故使用了Vite和Vue3相关技术框架,记录此基础框架搭建过程。
项目初始化
- 创建
yarn create vite
- 安装依赖
cd my-vite-demo
yarn
- 运行
yarn dev
构建生产环境和预览环境
- 修改配置文件vite.config.ts
根据模式对环境做相关配置
export default defineConfig(({ mode }) => {
return {
plugins: [vue()],
};
});
-
新增环境文件.env
一份用于指定模式的文件(例如 .env.production)会比通用形式的优先级更高(例如 .env)
已经存在的环境变量有最高的优先级,不会被 .env 类文件覆盖
.env 类文件会在 Vite 启动一开始时被加载,而改动会在重启服务器后生效
-
添加Typescript提示
src目录下的 env.d.ts 文件
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
// 更多环境变量...
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
- 环境变量配置
配置端口、mock服务开关、基础路径等等
// .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
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
// package.json
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vue-tsc --noEmit && vite build --mode preview && vite preview --mode preview",
},
- 配置ts
{
"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
- 安装
npm i unplugin-auto-import unplugin-vue-components -D
# or
yarn add unplugin-auto-import unplugin-vue-components -D
- 配置
// 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({
}),
],
})
// .eslintrc.js
rules: {
'no-undef': 'off'
}
element-ui plus 自动导入参考官方文档
接入现代CSS工程化
集成sass
- 安装css预处理器
yarn add sass -D
- 新建css文件
// src/assets/style/main.scss
$test-color: blue;
- 配置
// vite.config.ts
export default defineConfig(({ mode }) => {
return {
css: {
preprocessorOptions: {
scss: {
additionalData: '@import "@/assets/style/main.scss";',
},
},
},
plugins: [vue()],
};
});
- 使用
color: $test-color
集成 WindiCSS
- 安装
yarn add windicss vite-plugin-windicss -D
- 配置
// vite.config.ts
import windi from "vite-plugin-windicss";
export default defineConfig(({ mode }) => {
return {
plugins: [vue(), windi()],
};
});
- 引入css
配置添加相关配置文件,查阅windicss官方文档
// main.ts
import 'virtual:windi.css';
import 'virtual:windi-devtools'; //开发时浏览器工具
- 使用
class="bg-red-200 p-2 border-10 border-yellow-500 text-blue-600 hover:bg-purple-400"
约束代码风格
Eslint
- 安装
yarn add eslint -D
- 初始化
yarn eslint --init
选中相应的配置进行安装
eslint-plugin-vue
规范等级:
base 基础
essential 预设
strongly-recommended 推荐
recommended 最严谨
vue3:
Vue 3.x 需要加上 vue3 前綴,'plugin:vue/vue3-essential'
Airbnb:
- 配置
安装完后自动生成 .eslintrc.js
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
修改:
// 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 环境下错误提示和额外的一些配置:
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需要忽略哪些文件或者文件夹
node_modules
dist
preview
Prettier
- 安装
yarn add prettier -D
- 配置
项目根目录创建 .prettierrc.js
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忽略文件或者文件夹
node_modules
dist
preview
集成Prettier到ESLint工具中
- 安装
yarn add eslint-config-prettier eslint-plugin-prettier -D
eslint-config-prettier用来覆盖 ESLint 本身的规则配置,而eslint-plugin-prettier则是用于让 Prettier 来接管eslint --fix即修复代码的能力
- 配置
// .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问题
// .eslintrc.js
globals: {
defineProps: 'readonly',
defineEmits: 'readonly',
defineExpose: 'readonly',
withDefaults: 'readonly'
},
- 配置相关脚本
//package.json
"scripts": {
"lint:script": "eslint --ext .js,.jsx,.ts,.tsx,.vue --fix ./",
},
- 安装插件
在VSCode中安装
ESLint和Prettier这两个插件,并且在设置区中开启Format On Save,保存自动格式化。
Stylelint
- 安装
yarn add stylelint stylelint-prettier stylelint-config-prettier stylelint-config-recess-order stylelint-config-standard stylelint-config-standard-scss -D
- 配置
// .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
}
};
- 配置脚本
// package.json
"scripts": {
"lint:style": "stylelint --fix \"src/**/*.{css,scss}\""
},
其他集成
路由
- 安装
yarn add vue-router@4
- 新建路由文件src/router/index.ts
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提示
import 'vue-router';
declare module 'vue-router' {
interface RouteMeta {
// 是可选的
isAdmin?: boolean;
// 每个路由都必须声明
requiresAuth: boolean;
}
}
官网:Vue Router
Pinia 状态管理
- 安装
yarn add pinia
# 或者使用 npm
npm install pinia
- 配置插件
//main.ts
import { createPinia } from 'pinia'
app.use(createPinia())
- 分模块建立独立文件
// user.ts
import { defineStore } from 'pinia';
const useUserStore = defineStore('user', {
state: () => {
return { count: 0 };
},
// 也可以定义为
// state: () => ({ count: 0 })
actions: {
increment() {
this.count++;
}
}
});
export default { useUserStore };
使用:Pinia 中文文档
Animate.css
- 安装
yarn add animate.css
- 引入
// main.ts
import 'animate.css';
- 使用
<transition
name="animate"
enter-active-class="animate__zoomIn"
leave-active-class="animate__zoomOut"
class="animate__animated"
>
<div></div>
</transition>
时间日期格式话工具moment.js 和 Axios + VueRequest
参考我的其他文章:
后记
搭建的这一个过程学到了非常多的东西,在此拥抱Vue3的大环境下,我感觉Vue3的写法已经接慢慢的向着react的方向靠近了,反正写起来很“爽”,更多的仍需要我们一步一步地去学习和体验,加油掘友们!