当前位置: 首页 > 科技观察

微前端qiankun项目实践

时间:2023-03-22 12:23:15 科技观察

介绍最近在做一个微前端项目,过程中踩了不少坑。在有限的资料中不断尝试,不断犯错,默默流泪。哈哈。把这次踩到的坑记录下来,让更多的人少走弯路,本项目使用蚂蚁金服qiankun作为开发基础。废话不多说!!!那么什么是乾坤呢?qiankun是一个基于single-spa的微前端实现库,旨在帮助大家更轻松无痛地搭建一个生产就绪的微前端架构系统。什么是微前端微前端架构具有以下核心价值:技术栈无关主框架不限制应用程序技术栈的访问,微应用具有完全的自主权和独立开发、独立部署微-应用仓库独立,前后端可独立开发。部署完成后,主框架自动完成同步更新和增量升级。当面对各种复杂的场景时,我们通常很难升级或重构现有系统的整个技术栈,而微前端就是一个很好的实现渐进重构的手段和策略。独立运行时,各个微应用之间的状态是隔离的,运行时不共享状态。摘自乾坤官方文档。注册微应用//导入乾坤函数import{registerMicroApps,setDefaultMountApp,start}from"qiankun";封装render方法该方法一开始需要在main.js中调用一次,主要用来挂载主应用,然后子应用之间互相调用,所以假装判断。传入的参数是子应用的html和loading状态的content字段。我们将它们存储在vuex中,方便使用letapp=null;functionrender({appContent,loading}){if(!app){app=newVue({router,store,render:h=>h(App),}).$mount('#app');}else{store.commit('microApp/changeCenter',appContent);store.commit('microApp/changeLoading',loading);}}微应用注册以下应用均可获取数据。本文中注册小程序的案例比较简单,大家也容易理解。自注册的参数**container和render**踩了很多坑,下面重点讲解。functiongenActiveRule(routerPrefix){returnlocation=>location.pathname.startsWith(routerPrefix);}//传递给子应用的数据letmsg={![](https://user-gold-cdn.xitu.io/2020/4/27/171bbc5de042ec98?w=1811&h=959&f=gif&s=4951066)data:'践行爱的苦涩,学会放下曾经的欲念'}letapps=[{name:'linjunjie',entry:'//localhost:215',//改成自己的子应用容器的端口号:'#subView',//nodeid//沙盒模式//render:render,//普通模式activeRule:genActiveRule('/star'),props:msg}]//注册的子应用参数是一个数组registerMicroApps(apps,{beforeLoad:[app=>{console.log(app)console.log('[LifeCycle]beforeload%c%s','color:green;',app.name);},],beforeMount:[app=>{console.log('[LifeCycle]beforemount%c%s','color:green;',app.name);},]afterUnmount:[app=>{console.log('[LifeCycle]afterunmount%c%s','color:green;',app.name);},],});setDefaultMountApp('/star/linjunjie')//启用沙盒模式会自动触发qiankun匹配逻辑,所有micr匹配activeRule规则的o-app会被插入到指定的容器中,同时顺序调用微应用暴露的生命周期钩子主应用为子应用准备的显示元素Sub-应用配置子应用的配置比较简单,不需要另外下载qiankun主要是导出lifehook导出相应的lifehook导出bootstrap、mount、unmount三个生命周期钩子供主应用在合适的时候调用。注意在实例化路由时,判断在qiankun环境下运行时,路由要加前缀。前缀与主应用注册子应用函数genActiveRule("/subdemo")中的参数一致。“star”的值需要对应于主应用程序的值。genActiveRule("/star")中的值需要主应用和微应用都同意使用。如果main.js中没有配置新的VueRouter,请将此配置移到main.js中,方便管理importroutesfrom'./router'//方便导出路由信息letrouter=null;letinstance=null;functionrender(props={}){const{container}=props;router=newVueRouter({base:window.__POWERED_BY_QIANKUN__?'/star':'/',mode:'history',routes,});instance=newVue({router,store,render:h=>h(App),}).$mount(container?container.querySelector('#app'):'#app');}if(!window.__POWERED_BY_QIANKUN__){render();}exportasyncfunctionbootstrap(){console.log('[vue]vueappbootstraped');}exportasyncfunctionmount(props){//props包含了主应用传递的参数,也包含了为子应用创建的节点信息console.log(props)render(props);}exportasyncfunctionunmount(){instance.$destroy();instance=null;router=null;}配置微应用的打包工具除了在暴露的代码中,除了对应的生命周期钩子外,在order为了让主应用能够正确识别微应用暴露的一些信息,微应用打包工具需要在vue.config.js中添加如下配置:constpackageName=require('./package.json').name;module.exports={output:{library:`${packageName}-[name]`,libraryTarget:'umd',jsonpFunction:`webpackJsonp_${packageName}`,},};子应用判断.js中新增publicPath在main.js中引入if(window.__POWERED_BY_QIANKUN__){//处理资源__webpack_public_path__=window.__INJECTED_PUBLIC_PATH_BY_QIANKUN__;}处理资源加载配置vue.config.jsmodule.exports={publicPath:`//localhost:${port}`,}vue.config.js完成配置constpath=require('path');constpackageName=require('./package').name;functionresolve(dir){returnpath.join(__dirname,dir);}constport=7101;//devportmodule.exports={publicPath:`//localhost:${port}`,outputDir:'dist',assetsDir:'static',filenameHashing:true,devServer:{//host:'0.0.0.0',hot:true,historyApiFallback:true,//添加关键端口,overlay:{warnings:false,errors:true,},headers:{'Access-Control-Allow-Origin':'*',},},configureWebpack:{resolve:{alias:{'@':resolve('src'),},},output:{library:`${packageName}-[name]`,libraryTarget:'umd',jsonpFunction:`webpackJsonp_${packageName}`,},},};当当前页面为子应用时踩坑记录,刷新页面404以下方法为主要应用配置方法1删除mode配置项mode:'history',//删除该配置代码方法2配置404页面如果不注释掉mode:'history'该参数将404页面重定向到首页{path:'*',name:'indexNotFound',component:resolve=>require(['@/components/home'],resolve),children:HomeChild,},子应用样式隔离开启沙盒模式遇到问题主应用配置sandbox:{strictStyleIsolation:true}渲染模式由rendermode改为containercontainer:'#subView',此时子应用挂载的dom为

记住上面提到的主容器:#+id子应用配置拦截主代码instance=newVue({router,store,render:h=>h(App),}).$mount(container?container.querySelector('#app'):'#app');//遇到的关键问题:开启沙盒模式,如果使用渲染模式,报错r会报错,所以这里选择容器模式效果图来写,项目已经搭建好了,来看看效果这里是完整的代码,供大家学习代码github地址:https://github.com/zxh1307/qiankun-vue项目问题为什么项目启动后看不到子应用的效果?在主应用中注册mastermain.js,子应用的端口号可以改成自己项目的端口号。结语开发中还有其他坑忘记记录了。请记住,项目跨域部署子应用资源。Nginx需要配置跨域问题。