项目背景
一个多角色的PC端项目,使用的技术栈是Vben-Admin,一个做了高度封装的管理平台系统。管理员角色几乎都是表格查询,用户角色需要做申请操作,而移动端的适配仅仅是使用了CSS修改了页面样式,导致用户体验非常差。本来想针对移动端专门建一个项目,但项目周期紧迫,没有时间把登录、授权等模块重写一遍。针对时间紧任务重的现状,我们不得不写一些“笨代码,在这个项目的基础上再度引用Vant组件库,额外针对用户角色开发一些移动端页面。
探索了以下几个问题后,我终于完成了一个初步的版本:
icon不展示
怀疑是内网开发环境下加载不了iconfont文件,但最新的vant已经解决了这个问题:
源码里已经转成base64了,不存在引用第三方文件的问题。
发现是原来的项目已经全局使用了字体,
.iconfont,[class*="icon-"] {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
修改方式:
.van-icon {
font-family: 'vant-icon' !important;
}
如何跳转到移动端的页面
// 登录页、找回密码页使用原来的页面
if (['Login', 'InitPassWord'].includes(to.name)) {
next();
return;
}
// 当前环境是移动端并且路由上面没有mobile标识,就跳转到移动端的首页
if (isMobile() && to.path.indexOf('mobile') < 0) {
next('/mobile/home')
return
}
// 当前环境是PC端并且路由上携带了mobile标识,就跳转到PC端的首页
if (!isMobile() && to.path.indexOf('mobile') >= 0) {
next('/home')
return
}
然后所有移动端特有的页面,我们在路由定义的时候都加了一个mobile。
公共的错误提示处理
在PC端,我们使用了ant-design-vue的错误提示,这里需要判断设备
if(isMobile()) {
showToast(alertMsg)
} else {
createMessage.error(alertMsg);
}
移动端适配
使用postcss-pxtorem插件对业务代码里文件路径包含mobile的,和vant组件库进行处理:
// postcss.config.js
module.exports = {
plugins: {
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*'],
include: [/mobile/, /node_modules\/vant/]
},
},
};
vant分包
我们从PC端进入页面,事实上是不希望加载移动端的代码的,我们在这里把vant组件单独抽离出来,只有进入移动端页面,才会去加载资源。
rollupOptions: {
output: {
manualChunks: {
vant: ['vant']
},
}
}
想法是好的,但实际上没有作用,如下图,是在PC端登录页渲染的时候就已经加载了vant,原因在于上面对公共的错误提示处理引用了vant组件,因此就随着公共模块加载了vant。
unplugin-vue-components 带来的问题
vant官网上有一个unplugin-vue-components插件,可以自动引用vant组件,尝试之后发现了诸多问题:
import vue from '@vitejs/plugin-vue';
import Components from 'unplugin-vue-components/vite';
import { VantResolver } from 'unplugin-vue-components/resolvers';
export default {
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
],
};
- PC端组件也被实时设置成了公共组件,原因是该插件会去遍历
src/components的vue文件,而我们的Vben-Admin项目正好有这个目录,并且存放了很多组件
这样导致我们本来不用处理的组件都被处理了。
- 每次项目启动,都会处理两遍,原因是该插件会去实时生成
components.d.ts。如下图所示,组件引用会在编译的过程中发生变化,因此每次运行项目都会重启一次,如果某个页面又引用了之前没用过的vant组件,又会触发两次编译。
综上,使用这个插件只是在引用vant组件的时候少写一行代码,但时间代价是巨大的。
处理了上面的问题之后,我们成功在PC端项目里造了一部分移动端页面,结构调用、权限等功能都可复用。虽说项目架构比较离谱,但在短期内交付这个项目,已经是比较合适的方案了。
优化空间
-
移动端和PC端一般是两个不同的项目,合二为一会在运行时产生造成大量的冗余逻辑判断,造成性能问题;
-
我们把两个项目合二为一的重要原因之一,就是希望可以复用一些通用的逻辑,例如权限控制、接口调用等等。如果我们把这些模块拿出来放到组件库中,那么另起一个项目做移动端的成本就会大大降低;
-
由前端控制路由跳转,不够灵活,一般是通过
Nginx配置跳转。