基于Vue-cli3.0的qiankun(乾坤)前端微服务说明
官方文档地址:qiankun.umijs.org/zh
主服务
1.安装乾坤依赖(子服务不需要安装,只需要暴露生命周期方法)
2.在入口文件js中添加如下代码
import {registerMicroApps, start} from "qiankun";
let microProject = [
{
//项目名称,应当与子服务中的package.json项目名称一致
name: 'wdcsLogin app',
//子服务的入口(可以是js入口,但是这里我们统一使用html入口 也就是项目前端地址)
entry: 'http://192.XXX.XXX.XXX:8086',
//子服务的容器dom,实际上是主服务中的某个dom的id,用来装载子服务
container: '#micro_container',
//传递给子服务的的子服务ip,用于识别public文件
//props属性可以用来传递给子服务数据,比如传入公共的vuex实例
props: {microProjectPath: 'http://192.XXX.XXX.XXX:8086'},
//子服务的载入路由,实际上在主服务中,qiankun会识别该路由,从而激活子服务
activeRule: '/loginWdcsFrame'
},
{
name: 'wdcs',
entry: 'http://192.XXX.XXX.XXX:8086/wdcs.html',
container: '#micro_container',
props: {microProjectPath: 'http://192.XXX.XXX.XXX:8086'},
activeRule: '/wdcsFrame'
},]
//注册微服务
registerMicroApps(microProject)
//启动!!
start()
微服务
1.需要在入口文件js中添加乾坤生命周期方法
export async function bootstrap() {
console.log('[vue] vue app bootstraped');
}
export async function mount(props) {
console.log('[vue] props from main framework', props);
//storeTest(props);
// 接收父项目传递过来的public文件路径
// 因为父项目加载子项目后,public路径会指向父项目
// 这里父项目加载时,把子项目地址传递过来,似的子项目加载指向自己的public路径
render(props.microProjectPath + '/json/config.json',props);
}
export async function unmount() {
//销毁实例
window.Wdapp.$destroy();
window.Wdapp.$el.innerHTML = '';
router = null
}
2.设置publicPath
新建脚本public-path.js
脚本并在main.js
中引入,这段代码配合vue.config.js的chainWebpack使用,
来解决主服务加载js.css 图片等资源路径404问题。
而在子服务中我们可以使用变量window.__POWERED_BY_QIANKUN__
来判断是否处于qiankun框架中
if(window.__POWERED_BY_QIANKUN__){
__webpack_public_path__ = window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;
}
3.改写vue实例初始化代码为方法
let router = null;
//读取config.json中的配置修改为参数传递,并且挂载的dom也要根据主服务传递的参数判断动态改变
function render(configPath = 'json/config.json',props = {}) {
console.log(configPath)
const { container } = props;
//实例化路由
router = new Router(routerConfig)
axios.get(configPath).then(res => {
store.state.config = res.data;
axios.defaults.baseURL = res.data.baseUrlsByZhwd;
//读取token和user信息
let userInfo = JSON.parse(localStorage.getItem("WdUserInfo"))
if(!userInfo){
window.location.href = window.__POWERED_BY_QIANKUN__ ? '/loginWdcsFrame':res.data.redirectWdLoginUrl;
}
let token = JSON.parse(localStorage.getItem("WdUserInfo")).token;
window.userId = JSON.parse(localStorage.getItem("WdUserInfo")).userId;
if (token) {
axios.defaults.headers.common['token'] = token;
}
let app = new Vue({
router,
store,
render: h => h(App)
//挂载的dom也要根据主服务传递的参数判断动态改变
}).$mount(container ? container.querySelector('#wdcsApp') :'#wdcsApp')
window.app = app
})
}
4.改写路由暴露方式
原先路由对象实在router.js
中进行实例化并暴露的,
export default new Router({
// activeRule: '/yourActiveRule', 这个必须和主服务的路由一致
base: window.__POWERED_BY_QIANKUN__ ? '/yourActiveRule' : '/',
'routes': routers
})
现在修改为只暴露出配置对象
export default {
// activeRule: '/yourActiveRule', 这个必须和主服务的路由一致
base: window.__POWERED_BY_QIANKUN__ ? '/yourActiveRule' : '/',
'routes': routers
}
路由实例在第3点改写的render()
方法中进行实例化
这样做的目的是为了能够让路由在qiankun的生命周期方法unmount中进行销毁.
注:路由需要设置base
属性,处于qiankun中,设置为与主服务路由一直的前缀,否则将无法正确路由
5.修改 window.location.href代码
子服务项目中所有与 window.location.href
跳转有关的代码必须加入乾坤状态判断,否则跳转404
而主服务中也必须设置相应activeRule
属性
//子服务
window.location.href = window.__POWERED_BY_QIANKUN__ ? '/wdcsFrame' :_this.$config.redirectWdcsUrl;
//主服务相应设置
{
name: 'wdcs',
entry: 'http://192.XXX.XXX.XXX:8086/wdcs.html',//子服务的入口
container: '#micro_container',//子服务的容器dom,实际上是主服务中的某个dom的id,用来装载子服务
props: {microProjectPath: 'http://192.XXX.XXX.XXX:8086'},
activeRule: '/wdcsFrame'//子服务的载入路由,实际上在主服务中,qiankun会识别该路由,从而激活子服务
}
6.修改子服务配置文件vue.config.js
(1)子服务允许跨域,否则主服务无法访问
devServer: {
https: false, //设置前端https进行访问
port: 8084,
headers: {
'Access-Control-Allow-Origin': '*',
},
},
(2)修改子服务输出格式name
读取自package.json
的项目名称,应当与主服务配置的name
属性统一
这么做的目的是为了项目打包后能够暴露出qiankun的生命周期函数给主服务识别
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: 'umd',
jsonpFunction: `webpackJsonp_${name}`,
},
}
(3)配置静态文件解析loader,否则主服务加载子服务后,字体、图片等会404
/*链式配置,解决qiankun框架加载子服务图标显示方块问题*/
chainWebpack: config => {
const imagesRule = config.module.rule('images');
imagesRule.uses.clear()
imagesRule.test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
imagesRule.use('file-loader')
.loader('url-loader')
.options({
//limit:10000,
fallback:{
loader:'file-loader',
options:{
name:'img/[name].[hash:8].[ext]'
}
}
})
const fontsRule = config.module.rule('fonts');
fontsRule.uses.clear()
fontsRule. test(/\.(eot|svg|ttf|TTF|woff|woff2?)$/)
fontsRule.use('file-loader')
.loader('url-loader')
.options({
fallback:{
loader:'file-loader',
options:'fonts/[name].[hash:8].[ext]'
}
})
},
2021/2/26 踩坑记录------子应用多页面时,主应用无法正常路由跳转至其他页面或子应用
这里就不贴代码了
基于webpack构建的多页面应用(以vue-cli3.0为例)
项目基于vue-cli3.0构建的多页面应用,我们通常需要在vue.config.js 之中去配置pages属性来实现多页面,其中有一个filename属性,配置后会改变项目路由的pathname,也就是hash前面的路由。
比如单页面使用hash路由时,我们的地址可能是http://192.168.XX.XX:8080/#/home,而我们配置了多页面后,假设我们的filename为‘index.html’,那么url访问地址就是http://192.168.XX.XX:8080/index.html#/home
以上是配置的多页面时的基本情况-------------
此时对应到qiankun中,假设我们的 activeRule: ‘/wdcsFrame’,那么qiankun中的url地址为http://192.18.XX.XX:8080/wdcsFrame#/home
才能成功激活并匹配路由,在这中情况下如果主服务是单页面,那么如果你想做其他的路由切换跳转,通过 ‘$router.push
’ 修改路由,路由地址则是 http://192.168.XX.XX:8080/wdcsFrame#/XXXX
,而由于主服务是单页面,默认的pathname是空 即 /#/,此时页面无法正常匹配路由。
解决方案:先使用$router.push
跳转路由后,立即使用window.location.pathname = “”
将其清空,主服务才能匹配路由;另外如果切换时,子服务没有被销毁(虽然我也没弄清楚咋销毁,路由切换时子服务的unmont也没进),且子服务存在路径 ‘/’ 的重定向设置。如果先清空pathname,路由会被重定向,而后面的$router.push不会运行(不知道为什么,debgger也没进去),此时路由同样无法匹配激活