协作人:张婷 ,张燕燕
背景
由于在开发前端项目中,后台管理端和用户端存在多个模块和页面逻辑可以复用,管理模块和用户端渲染模块使用同一套状态管理机制,只是在管理端和用户端的入口和路由模块不同,为了能够在开发时同时修改管理端和用户端共用模块,不用多项目工程修改和发布,我们基于vite多页面的基础上实现了多端同构开发和部署。
多端同构实现流程
具体配置流程
1,多页面入口配置
首先我们可以在工程目录下创建多页面文件,不同页面配置的入口entry不同来建立多入口,
以下我们以管理端和用户端两个端为例来说明实现流程
比如:
管理端入口配置
admin/index.html
<body>
<div id="app"></div>
<script type="module" src="/src/admin.js"></script>
</body>
admin.js
import { createApp } from 'vue'
import App from './admin.vue'
import router from './adminRouter';
import store from './store'
const app = createApp(App)
app.use(store).use(router)
app.mount('#app')
用户端:public/index.html
<body>
<div id="app"></div>
<script type="module" src="/src/public.js"></script>
</body>
public.js
import { createApp } from 'vue'
import App from './public.vue'
import router from './publicRouter';
const app = createApp(App)
app.use(store).use(router)
app.mount('#app')
2,用户访问权限判断
不同的用户有不同的角色身份,我们需要根据用户登录后的角色来判断是否可以访问该入口,如果该用户不具备该入口的访问权限,我们需要在入口处拦截进行提示或者让页面重定向到拥有权限的入口处, 这块可以通过前端请求处理也可以,通过服务端配置角色和白名单类型处理。
下边以前端调用后端接口实现
以public.js为例
import { createApp } from 'vue'
import App from './public.vue'
import router from './publicRouter';
fetch(/xxx/).then((res)=> {
if(res) {
const app = createApp(App)
app.use(store).use(router)
app.mount('#app')
} else {
/** 跳转到其他有权限页面 或者进行无权限提示**/
}
})
3,路由模式匹配
每个端应用建议配置自己的路由,用于和其他端模块资源划分
常用的路由分为hash模式和history模式,不同模式下的配置路由略有差异,一般history模式需要通过服务端支持实现,否则会出现刷新页面出现404的情况。
hash模式实现
管理端:adminRouter
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory('/pageadmin/'),
routes:[{
path: '/page1',
name: 'page1',
component:() => import('@/page1.vue')
}]
});
export default router;
用户端:publicRouter
import { createRouter, createWebHashHistory } from 'vue-router';
const router = createRouter({
history: createWebHashHistory('/pagepublic/'),
routes:[{
path: '/page1',
name: 'page1',
component:() => import('@/page1.vue')
}],
});
export default router;
history模式实现
history模式的实现管理端和用户端同hash模式,将createWebHashHistory改为createWebHistory即可:
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory('/xxx/'),
routes:[{
path: '/page1',
name: 'page1',
component:() => import('@/page1.vue')
}],
});
export default router;
history本地开发刷新404解决
history模式,由于hash模式时url带的#号后面是哈希值不会作为url的一部分发送给服务器,而history模式下当刷新页面之后浏览器会直接去请求服务器,而服务器没有这个路由,于是就出现404, 为了解决该问题,我们可以采用如下方案
通过配置代理,将访问的路由指向我们本地开发服务器目录文件
proxy: {
'/pageadmin/': {
target: 'http://easy-page.local.jdl.com:8089',
changeOrigin: true,
rewrite: (path) =>'/admin/index.html'
},
'/pagepublic/': {
target: 'http://easy-page.local.jdl.com:8089/',
changeOrigin: true,
rewrite: (path) => '/public/index.html'
}
}
4,vite.config.js入口配置
build: {
rollupOptions: {
input: {
admin: resolve(__dirname, 'admin/index.html'),
public: resolve(__dirname, 'public/index.html'),
},
},
}
打包后的目录结构
打包后,我们可以看到生成了两个入口文件 admin/index.html 和 public/index.html
assets是两个入口共用的资源内容包括 js,css,png等等
生产配置
生产环境我们也需要根据url路由区分访问入口, 我们可以根据资源的访问路径,将其指定到不同的应用入口来实现不同端访问的资源内容不同,同时可以在服务端配置检测客户端的userAgent来现在各个端访问设备,可以给各个端配置白名单来限制用户访问
location /pageadmin {
add_header Cache-Control no-store;
try_files $uri $uri/ /admin/index.html;
}
location /pagepublic {
add_header Cache-Control no-store;
try_files $uri $uri/ /public/index.html;
}
总结
以上是我们基于vite多页面同构方案来实现多个端一套代码开发构建部署,实现工程模块中相同模块和资源的共享复用,减少多个应用的创建和多域名申请,以及多个应用之间相互关联交互,通过path来区分不同的用户访问。