最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 可能是多端适配性最好的微前端框架

    正文概述 掘金(valleykid)   2020-12-29   532

    引子

    对微前端方向有了解的同学可能都看过 qiankun 的文档,深入的同学估计也去翻过其代码和 single-spa 的源码。一年前我也是受微前端思想的影响,当时刚好面临的业务是变化频繁,需要支持线上功能的热插拔和独立部署。充分调研了微前端和 qiankun 之后,发现很适合当前业务,才开始开始实践微前端的。由于 single-spa 太过于简陋,就采用 qiankun@1.x 作为微前端驱动,今天想把这段时间以来遇到的问题和解决之道跟大家分享一下。

    可能面临的业务场景

    假设你现在维护或新开发这样一个项目,业务变化频繁,页面功能有重复,但风格是一致的,暂时只有 pc 端。你拿到设计稿后发现,可以把业务分拆成多套 layout,由基座(主应用)提供。功能独立的模块集成在子应用,每个子应用有特殊的 routerBase。

    咔咔咔,两三下你做完了所有任务,子应用也能在线配置,支持热插拔和独立部署。爽歪歪~

    几天后突然有了以下几个新业务场景,你陷入了沉思。。。

    场景一:随着业务的变化,需要支持移动端。

    你新建了个子应用,routerBase 设置为 h5。当判断是移动端时自动跳转 /h5/xxx。如果 pc 端访问 /h5/xxx 时,自动重定向到 /xxx,能勉强应付该场景,不过因为基座太重导致移动端渲染很慢,在移动端使用“前进/后退”按钮也会因为重定向太多导致混乱,有时候页面渲染成 pc 页面或无法渲染。

    场景二:页面是响应式的,移动端点击登录后,也能共享登录态。

    响应式页面是活动页,有活动报名,就要求登录态共享。当用户在移动端点击登录时,理应跳转到移动端的登录页面,登录完重定向到活动页面 需要是登录成功的状态。如果是每个子应用都有 routerBase,来回跳转好几次,而且还要想办法共享登录。

    场景三:老板要求 pc 端和移动端 URL 一致。。。

    routerBase 天然断绝了这种可能性,根本无法做到!

    场景四:老板要求一个四年前的项目聚合到门户站点中。。。

    该项目的很多依赖特别是脚手架都已经严重过时,锁定一级依赖的版本但锁不了二级以上的版本,导致构建发布失败。根本无法往项目代码中加入 bootstrap/mount/unmount...!

    qiankun 的“kun”(困)境

    qiankun 的定位可能是中后台项目的聚合。这类项目彼此间很少依赖,登录态的控制可以在基座中完成,属于一个基座下的多个串联。但面临上述场景时,就显得力不从心。

    另外上述场景也暴露了 qiankun 的诸多问题:

    • 基座一般由真实的业务应用承载,提供登录等功能,也提供多套 layout;
    • 基座很容易耦合很多 pc 端的 UI 库和功能代码;
    • 基座很容易沦为通用数据和逻辑的聚集地,虽然这些不是基座应用的职责;
    • 严重依赖 routerBase,框架判断便利但牺牲了灵活性;
    • 多实例共存支持不足,目前仅支持 microApp 形式,且这种应用不建议有路由系统;
    • 严重依赖生命周期 bootstrap/mount/unmount;

    破局之道

    @icatjs/micro 是我这四个月来实现并在实际项目中实践的新一代微前端框架,不但能轻松应付上述“困境”,还具备其他良好的特性。目前仅有两个方法 registerSubapps 和 start ,其他需要注意的就是子应用的配置了。TA 是如何应对上述困境的呢?听我一一分享下:

    端应用(或称 layout 应用)

    大家看到这个新名词,不要以为对子应用做了强制的分类。只要某个子应用 a 提供了 layout 或一些路径被用作了 layout,又被其他子应用 b 依赖了,那么该应用 a 就可以看做是“端应用”。a 是不是端应用,自己根本不知道,它会按子应用正常的加载。而 b 会在 a 提供了挂载点后再渲染到页面上。看个例子吧~

    这是端应用的配置

    {
        "name": "a",
        "entry": "aaa",
        "history": "browser",
        "props": {},
        "rules": [
          {
            "rule": "/",
            "container": "#mountNode",
            "endType": "pc"
          }
        ]
      }
    

    解析下:a 作为 pc 端的应用,路径规则配置的是通配符 / ,这样所有的路由都会被这个应用匹配到。当然会通过 endType 优先判断是哪个端,然后再去处理应用的“依赖链”。目前由于场景比较简单,每个路由下只支持一条依赖链。理论上讲可支持多条依赖链,也就是 多链多实例同时并存。

    这是子应用的配置

    {
        "name": "b",
        "entry": "bbb",
        "history": "browser",
        "props": {},
        "rootVars": {
          "externals": {
            "@react": "React",
            "@react-dom": "ReactDOM",
            "userInfo": "userInfo"
          }
        },
        "rules": [
          {
            "rule": "/b/activities/1520",
            "layout": "a > /layout/headless",
            "endType": "none"
          },
          {
            "rule": "/b/tec-support",
            "container": "#mountNode",
            "endType": "none"
          },
          {
            "rule": "/development",
            "layout": "a > /layout/basic",
            "endType": "pc"
          }
        ]
      }
    

    也解析下:可以看 rules 中配置了三个典型的规则,第一条依赖了端应用 a 的 /layout/headless,第二条不依赖任何端应用,第三条依赖了 a 的 /layout/basic。

    不配置 container 的路径,如果是子应用默认是 #subappMountNodeWrapper ,如果是端应用不依赖任何 layout 则默认是 #appMountNodeAndDoNotCover 。这样如果页面中有这些节点出现时,子应用就会渲染到该节点上。

    大家也可以看到,一个子应用的激活与否只和路径规则有关,这些规则遵守 single-spa 的 activeWhen 规则,可以是字符串、函数或数组。而每条路径规则都有自己的 container,也有属于自己的端 endType 和 layout。这样一个子应用既可以作为依赖链上的一个端应用,又可以作为独立的子应用。按路径规则灵活组合,适应多种场景需要。

    注意!端应用也可以依赖其他端应用,只需要在其路径规则上配置需要依赖的路径即可。

    entry

    可以是一个 html 文件路径,也可以是一个数组,包含多个 js、css 和 html。初始化挂载点时,以最后一个 html 的内容填充进去。

    全局路由系统

    内置处理了 react/vue 多个子应用同时被激活,多个路由系统冲突的问题。无需再像使用 qiankun 那样,还要把子应用的路由配置到主应用中,以防冲突。全局路由会拦截路由变化,把真实路径和 layout 路径分发到各个子应用,使其能正常渲染。 并且,所有子应用都可以有自己独立的 404 页面。可以把子应用完全看成是独立的应用,无需顾虑路由的默认匹配,无需担心路由不匹配时直接进入应用的 404 页面。

    沙箱

    内置了 iframe 沙箱,子应用的代码运行是在 iframe 中。这样代码的状态都会保存在 iframe 中,不用麻烦提供快照,天然具备快照能力。也内置了垃圾回收队列,当一个子应用 5 分钟内不被激活,会被释放掉 iframe。 注意!这些 iframe 都是空白 iframe,耗费的渲染资源很少。但框架在 iframe 中提供了虚拟 BOM,使这些字应用运行完的结果能够正确渲染到 iframe 外的真实渲染层中。 注意2!子应用的所有对 dom 的操作都被限制在挂载点中,换言之,document.body 指向的是挂载点而不是渲染层的真实 body。这种严密的控制也体现在 getElementById 等方法中。 可能是多端适配性最好的微前端框架

    当然还有其他一些特性如第三方库共享全局数据共享组件&方法&状态流共享缓存机制等,初次介绍就先不深入了。后续会筹备官网,全面介绍这些特性的。

    到此,我们梳理一下困境的解决之道:

    • 场景一,需要支持移动端。由于去掉了 routerBase 的依赖,又支持端应用,天然解决了基座重造成的渲染问题,反复重定向造成的跳转问题。
    • 场景二,页面是响应式的需要共享登录态。由于支持 layout 依赖链,某个端应用可以集中处理登录逻辑,其他端应用依赖其提供的功能即可。逻辑可以通过流共享模式或者全局数据共享,分发到多个子应用。响应式的页面属于依赖链的某个节点,自然能及时获得登录态。
    • 场景三,URL 一致性。由于去掉了 routerBase 的依赖,框架会在初始化时判断所处的终端,进而激活不同端应用。而端应用的路径规则都可以配置成通配符 / ,这样很容易保证 URL 一致。
    • 场景四,四年前的老项目集成。框架支持无生命周期的项目,可以无缝渲染到门户站点中来。这是我测试的截图,大家有兴趣可以看下:

    这是集成的 2018 年的 seeconf 官网: 可能是多端适配性最好的微前端框架

    这是集成的口碑官网: 可能是多端适配性最好的微前端框架

    是否解决了 qiankun 的困境呢?

    由于通用逻辑和 layout 被分摊到一层层的“端应用”中,基座只需要做好对框架的引用和对规则的获取与解析,就能驱动起整体的站点运行起来。子应用的路由也不用顾虑冲突,而考虑在主应用中 copy 一份。 基座可以做到很薄,每个端只需加载其需要的 UI 库或组件。比如 pc 端使用了 antd,移动端可以使用 antd-mobile,框架不会把 antd 加载到移动端去。

    还有哪些不足?

    • 不建议基座具有路由系统,目前还没去实验基座路由和子应用路由冲突的场景。
    • 多路由系统冲突方案,暂时没有支持 angular,对 vue 的支持可能存在一点儿 bug。
    • 多条依赖链场景暂未支持,目前只处理了第一条依赖链。
    • 子应用中一些 js 灵活写法,如 eval 中的全局变量 var 去定义,包括本身的 var 定义的全局变量,还无法正确挂载到虚拟 window 上。可能存在某些项目加载报错的情况。
    • 梳理了 21 种路由冲突的场景,可能存在例外的情况。

    浏览器兼容

    主流浏览器 chrome, safari, edge, firefox 等都兼容,国内小众浏览器 360、qq 浏览器等也兼容。优先使用 Proxy,不支持则退化为 Object.defineProperty。

    谁在使用

    目前平头哥 IoT 团队在做芯片开放社区(OCC),这个框架的诞生也是为了满足其不断变化的业务需求。大家可以看下 pc 端和移动端的 URL 是相同的,但激活的子应用是不同的。

    也希望看到本文的同学,在未来某个时刻使用 @icatjs/micro 框架,做出精彩纷呈的作品来!

    应一些同学的反馈,随手搞了个 demo,请大家初步了解下该框架的使用。


    起源地下载网 » 可能是多端适配性最好的微前端框架

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元