前言
即将来到的新的一年,注定是Vue3崛起的一年,也将是以Vite为代表进入构建加速时代的一年。
我在之前的《2022年哪些前端技术会火?》提过,我们早在2020年就已经使用vue3框架,并开发了数个商业级项目,已验证其框架的稳定性。
最近,尤大发布了Vue3成为默认版本的消息,意味着vue3将成为社区维护的主要方向。 为了让更多的小伙伴快速进入vue3,我在Github发起了一个开源模板fast-vue3,以提供开箱即用的脚手架,快速渡过一档起步(各种配置),直接体验加速阶段(实际项目)。配置本身并没有什么难度,后面用到再阅读文档即可。
FastVue3
fast-vue3
,是Vue3+Vite2.7+TypeScript+Pinia
等Vue的开发工具链。整理了当前比较主流的工具链,可以直接开箱使用,方便小伙伴学习,最好的学习方式——边用边学边学边用
~
不是轮子,是模板工具哦~
特点
-
💕
fast-vue3
就不赘述了,框架基座支持Vue3+Vite2.7+TypeScript+Pinia
常规的就不多说了,这里主要分享一些前沿高效,大厂常用的高阶插件。 -
🔌 支持husky和 lint-staged,大厂团队代码规范协作必备
-
🖼️ 支持
svg
图标,已封装一个简单的SvgIcon
组件,可以直接读取文件下的svg
-
⚙️ 支持
Plop
,代码文件自动生成,提供三种预设模板pages
,components
,store
等可自定义 -
📦 支持
axios(ts版)
,已封装了主流的拦截器,请求调用等方法 -
👽 支持
router,store
模块化,内置生成路由钩子 -
🐳 支持
env
,环境变量和区分打包环境 -
🍡支持
unplugin-vue-components
组件自动引入 -
🏗 支持
vw/vh
移动端布局兼容,也可以使用plop
自己配置生成文件 -
📱 支持
vite-plugin-md
markdown渲染 -
🥘 支持
vite-plugin-pages
根据文件自动生成路由的插件 -
🤖 支持
vite-plugin-restart
,监听vite.config或env文件改动而自动重启 -
🎉 目前正在收集更多提效工具,持续添加中....
使用
一键三连: Star 或 Fork 或 可视化仓库
# 拉取仓库代码
git clone https://github.com/MaleWeb/fast-vue3.git
# 进入项目文件夹
cd fast-vue3
# 安装项目依赖
pnpm install
# 运行
pnpm run dev
如果不报错,恭喜你点火成功。否则,请看下面常见问题。
如果你已经了解本模板,建议你拉取 template
分支进行项目开发,该分支不含任何示例代码。
# clone template 分支
git clone -b template https://github.com/MaleWeb/fast-vue3.git
功能亮点
这里简单介绍一些核心部分,安装部分不再细讲,建议大家直接阅读官方文档或可视化仓库
🪂大厂协作-代码规范
🪁 目前多数大厂团队一般使用husky和 lint-staged 来约束代码规范
- 通过
pre-commit
实现lint检查、单元测试、代码格式化等。 - 结合VsCode编辑器(保存时自动执行格式化:editor.formatOnSave: true)
- 配合Git hooks钩子(commit前或提交前执行:pre-commit => npm run lint:lint-staged)
- IDE 配置(
.editorconfig
)、ESLint 配置(.eslintrc.js
和.eslintignore
)、StyleLint 配置(.stylelintrc
和.stylelintignore
),详细请看对应的配置文件。
🔌关闭代码规范
将 src/
目录分别加入 .eslintignore
和 .stylelintignore
进行忽略即可。
💕支持JSX语法
{
...
"@vitejs/plugin-vue-jsx": "^1.3.3"
...
}
🎸UI组件按需加载,自动导入
//模块化写法
import Components from 'unplugin-vue-components/vite'
export const AutoRegistryComponents = () => {
return Components({
extensions: ['vue', 'md'],
deep: true,
dts: 'src/components.d.ts',
directoryAsNamespace: false,
globalNamespaces: [],
directives: true,
include: [/\.vue$/, /\.vue\?vue/, /\.md$/],
exclude: [/[\\/]node_modules[\\/]/, /[\\/]\.git[\\/]/, /[\\/]\.nuxt[\\/]/],
resolvers: [
IconsResolver({
componentPrefix: '',
}),
ArcoResolver({ importStyle: 'less' }),//根据你需要增加UI框架
VueUseComponentsResolver(),//默认使用VueUse组件
],
})
}
🧩Vite插件模块化
为了方便管理插件,将所有的config
统一放入config/vite/plugins
里面,未来还会有更多插件直接分文件夹管理十分干净。
值得一提的是,Fast-Vue3
增加了统一环境变量管理,来区分动态开启某些插件。
// vite/plugins/index.ts
/**
* @name createVitePlugins
* @description 封装plugins数组统一调用
*/
import type { Plugin } from 'vite';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import { ConfigSvgIconsPlugin } from './svgIcons';
import { AutoRegistryComponents } from './component';
import { AutoImportDeps } from './autoImport';
import { ConfigMockPlugin } from './mock';
import { ConfigVisualizerConfig } from './visualizer';
import { ConfigCompressPlugin } from './compress';
import { ConfigPagesPlugin } from './pages'
import { ConfigMarkDownPlugin } from './markdown'
import { ConfigRestartPlugin } from './restart'
export function createVitePlugins(isBuild: boolean) {
const vitePlugins: (Plugin | Plugin[])[] = [
// vue支持
vue(),
// JSX支持
vueJsx(),
// 自动按需引入组件
AutoRegistryComponents(),
// 自动按需引入依赖
AutoImportDeps(),
// 自动生成路由
ConfigPagesPlugin(),
// 开启.gz压缩 rollup-plugin-gzip
ConfigCompressPlugin(),
//支持markdown
ConfigMarkDownPlugin(),
// 监听配置文件改动重启
ConfigRestartPlugin(),
];
// vite-plugin-svg-icons
vitePlugins.push(ConfigSvgIconsPlugin(isBuild));
// vite-plugin-mock
vitePlugins.push(ConfigMockPlugin(isBuild));
// rollup-plugin-visualizer
vitePlugins.push(ConfigVisualizerConfig());
return vitePlugins;
}
而vite.config.ts
便干净多了
import { createVitePlugins } from './config/vite/plugins'
...
return {
resolve: {
alias: {
"@": path.resolve(__dirname, './src'),
'@config': path.resolve(__dirname, './config'),
"@components": path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils'),
'@api': path.resolve(__dirname, './src/api'),
}
},
// plugins
plugins: createVitePlugins(isBuild)
}
...
📱支持Pinia
,下一代Vuex5
创建文件src/store/index.ts
// 支持模块化,配合plop可以通过命令行一键生成
import { createPinia } from 'pinia';
import { useAppStore } from './modules/app';
import { useUserStore } from './modules/user';
const pinia = createPinia();
export { useAppStore, useUserStore };
export default pinia;
创建文件src/store/modules/user/index.ts
import { defineStore } from 'pinia'
import piniaStore from '@/store'
export const useUserStore = defineStore(
// 唯一ID
'user',
{
state: () => ({}),
getters: {},
actions: {}
}
)
🤖 支持Plop
自动生成文件
⚙️ 代码文件自动生成,提供三种预设模板pages
,components
,store
,也可以根据自己需要设计更多自动生成脚本。一般后端同学惯用此形式,十分高效。
# 安装plop
pnpm add plop
根目录创建plopfile.ts
import { NodePlopAPI } from 'plop';
export default function (plop: NodePlopAPI) {
plop.setWelcomeMessage('请选择需要创建的模式:')
plop.setGenerator('page', require('./plop-tpls/page/prompt'))
plop.setGenerator('component', require('./plop-tpls/component/prompt'))
plop.setGenerator('store', require('./plop-tpls/store/prompt'))
}
# 启动命令
pnpm run plop
🖼️ 支持SVG
图标
随着浏览器兼容性的提升,SVG的性能逐渐凸显,很多大厂团队都在创建自己的SVG管理库,后面工具库会有推荐。
# 安装svg依赖
pnpm add vite-plugin-svg-icons
配置vite.config.ts
import viteSvgIcons from 'vite-plugin-svg-icons';
export default defineConfig({
plugins:[
...
viteSvgIcons({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]',
}),
]
...
})
已封装一个简单的SvgIcon
组件,可以直接读取文件下的svg
,可以根据文件夹目录自动查找文件。
<template>
<svg aria-hidden="true" class="svg-icon-spin" :class="calsses">
<use :xlink:href="symbolId" :fill="color" />
</svg>
</template>
<script lang="ts" setup>
const props = defineProps({
prefix: {
type: String,
default: 'icon',
},
name: {
type: String,
required: true,
},
color: {
type: String,
default: '#333',
},
size: {
type: String,
default: 'default',
},
})
const symbolId = computed(() => `#${props.prefix}-${props.name}`)
const calsses = computed(() => {
return {
[`sdms-size-${props.size}`]: props.size,
}
})
const fontSize = reactive({ default: '32px', small: '20px', large: '48px' })
</script>
📦支持axios(ts版)
已封装了主流的拦截器,请求调用等方法,区分了模块index.ts
/status.ts
/type.ts
//封装src/api/user/index.ts
import request from '@utils/http/axios'
import { IResponse } from '@utils/http/axios/type'
import { ReqAuth, ReqParams, ResResult } from './type';
enum URL {
login = '/v1/user/login',
permission = '/v1/user/permission',
userProfile = 'mock/api/userProfile'
}
const getUserProfile = async () => request<ReqAuth>({ url: URL.userProfile });
const login = async (data: ReqParams) => request({ url: URL.login, data });
const permission = async () => request<ReqAuth>({ url: URL.permission });
export default { getUserProfile, login, permission };
//调用
import userApi from "@api/user"
// setup模式下组件可以直接引用
const res = await userApi.profile()
👽 自动生成router
,过滤components
组件
支持vue-router4.0
的模块化,通过检索pages文件夹可自动生成路由,并支持动态路由
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import routes from 'virtual:generated-pages'
console.log(routes,'打印生成自动生成的路由')
//导入生成的路由数据
const router = createRouter({
history: createWebHashHistory(),
routes,
})
export default router
🧬支持Mock数据
使用vite-plugin-mock
插件,支持自动区分和启停的环境配置
// vite config
viteMockServe({
ignore: /^\_/,
mockPath: 'mock',
localEnabled: !isBuild,
prodEnabled: false,
// https://github.com/anncwb/vite-plugin-mock/issues/9
injectCode: `
import { setupProdMockServer } from '../mock/_createProdMockServer';
setupProdMockServer();
`
})
根目录下创建 _createProductionServer.ts
文件,非_
开头文件会被自动加载成mock文件
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer';
// 批量加载
const modules = import.meta.globEager('./mock/*.ts');
const mockModules: Array<string> = [];
Object.keys(modules).forEach((key) => {
if (key.includes('/_')) {
return;
}
mockModules.push(...modules[key].default);
});
export function setupProdMockServer() {
createProdMockServer(mockModules);
}
🎎Proxy代理
// vite config
import proxy from '@config/vite/proxy';
export default defineConfig({
...
server: {
hmr: { overlay: false }, // 禁用或配置 HMR 连接 设置 server.hmr.overlay 为 false 可以禁用服务器错误遮罩层
// 服务配置
port: VITE_PORT, // 类型: number 指定服务器端口;
open: false, // 类型: boolean | string在服务器启动时自动在浏览器中打开应用程序;
cors: false, // 类型: boolean | CorsOptions 为开发服务器配置 CORS。默认启用并允许任何源
host: '0.0.0.0', // IP配置,支持从IP启动
proxy,
}
...
})
// proxy.ts
import {
API_BASE_URL,
API_TARGET_URL,
MOCK_API_BASE_URL,
MOCK_API_TARGET_URL,
} from '@config/constant';
import { ProxyOptions } from 'vite';
type ProxyTargetList = Record<string, ProxyOptions>;
const init: ProxyTargetList = {
// test
[API_BASE_URL]: {
target: API_TARGET_URL,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${API_BASE_URL}`), ''),
},
// mock
[MOCK_API_BASE_URL]: {
target: MOCK_API_TARGET_URL,
changeOrigin: true,
rewrite: (path) => path.replace(new RegExp(`^${MOCK_API_BASE_URL}`), '/api'),
},
};
export default init;
🎉 其他
- 🏗 支持
vw/vh
移动端布局兼容,也可以使用plop
自己配置生成文件 - 还有更多新功能增在
commiting
,如果你有更好的方案欢迎PR
工具库
学会使用适当的工具库,让coding
事半功倍。尤其是开源的工具库,值得每个人学习,因为这本身就是你应该达到的层次。这里推荐一些大厂常用的类库,因为我喜新...,以下工具均可直接引入。
JS库
- pnpm,一个依赖包全局管理的工具,老板再也不用担心我的C盘不够用。Vite官方推荐,字节官方前端团队大规模项目考验
- mitt 全局事件监听库,Vue3官方推荐
- Hammer,可以识别由触摸、鼠标和指针事件做出的手势,只有 7.34kb
- outils,开发中常用的函数集,也可以使用
lodash
day.js、TailWindcss、vue-cookies
等大家见太多就不列举了
UI库
- arco-design,字节团队新出的UI框架,配置层面更为灵活,
fast-vue3
使用的就是这个,不喜欢的小伙伴可以移除 - semi-design,抖音前端出的框架,面向经常撕逼UI和FE,可以尝鲜玩玩
- nutui,京东前端团队出的UI框架,已升级到3.X,个人认为颜值最高并接受反驳
- naive-ui,尤大推荐,TypeScript语法,主题可调,这家公司挺厉害
- 暂时就这些吧,困了,回头再补
资料
- 官方配置文档入口vite、pinia、vue-router4、plop...
- vu3写组件实践案例:juejin.cn/post/705271…
- 一些特殊配置:juejin.cn/post/705431…