• 微前端实际应用


    目录

    1、iframe

    1-1 iframe基本理解

    1-2 无界方案

    1-3 使用无界

    1-4 实现细节

    1-5 无界微前端框架总结

    2、qiankun

    2-1 微前端知识温故

    2-2 qiankun


    在上面的基础中了解到,目前常用的微前端实现方案有多种,其中目前常见使用的是qiankun,以前常用的框架是iframe的微前端方案,下面我们先来学习一下之前的框架iframe实现微前端方案

    1、iframe

    1-1 iframe基本理解

    • 在之前使用iframe的时候,是在页面的使用中引入另外一个页面进行渲染,所以它的基本功能是:在一个web应用中独立的运行另一个web应用
    • iframe的使用优点
      • 简单:使用简单
      • 隔离完美:js,css,dom完全隔离
      • 多应用激活:可以在页面上使用多个iframe来组合业务
    • iframe的使用缺点
      • 路由状态丢失:刷新一下之后,iframe的url状态会丢失
      • dom割裂严重:弹窗只能在iframe内部展示,无法覆盖全局
      • 通信困难:通过postmessage传递序列化的信息
      • 白屏时间长:加载时间长导致页面白屏,对于SPA应用来说此弊端太大

    1-2 无界方案

    • 综合上面的优缺点,我们一般会想保留优点去掉缺点,无界方案正好是此方案的解法

    a、例子:假设有A应用,想加载B应用

    • 在应用A中构造一个shadow和iframe,之后将应用B的html写入shadow中,js运行在iframe中。iframe的url:iframe保持和主应用同域且保留子应用的路径信息,这样可以使应用的js运行在iframe的location和history中来保证路由的正确性
    • 在iframe中拦截document对象,统一将dom指向shadowRoot,此时新建的元素、弹窗等组件就可以正常的约束在shadowRoot的内部

    b、解决iframe的三个缺点:

    • dom割裂严重问题:主应用提供一个容器到shadowRoot插拔,shadowRoot内部的弹窗就可以覆盖到整个应用A上
    • 路由状态丢失问题:浏览器的前进后退可以作用到iframe上,此时来监听iframe的路由变化并同步到主应用上,如果刷新浏览器,就可以从url读回保存的路由
    • 通信非常困难问题:iframe和主应用是同域的,共享内存通信,且无界框架提供了一个去中心化事件机制

    c、将上面的机制封装进wujie框架:

    • 首次白屏问题,wujie实例可以提前实例化,包括shadowRoot、iframe的创建、js的执行,可以加快子应用第一次打开的时间
    • 切换白屏问题:当wujie实例可以缓存下来,子应用的切换成本变的极低,如果采用保活模式,相当于shadowRoot的插拔

    子应用完全独立的运行在iframe内,路由依赖iframe的location和history,可以在一张页面上同时激活多个子应用。因为iframe和主应用处于同一个top-level browsing context(顶级浏览上下文),所以浏览器前进、后退都可以作用到子应用

    d、通过上面的方法实现无界方案

    • 非常简单,使用没有任何心智负担
    • 隔离完美,无论是js、css、dom都完全隔离开来
    • 多应用激活,页面上可以摆放多个iframe来组合业务
    • 通信
    • 无白屏情况
    • 路由不会丢失

    1-3 使用无界

    a、无界框架的基本使用步骤

    使用例子,主应用为vue框架,使用的步骤为:

    1. 安装:
      npm i @tencent/wujie-vue -S
    2. 在主应用中引入:
      import WujieVue from “@tencent/wujie-vue”; Vue.use(WujieVue);
    3. 使用:
      <WujieVue width="100%" height="100%" name="xxx" url="xxx" :sync="true" :fetch="fetch" :props="props" @xxx="handleXXX" >WujieVue>

    b、主子应用中无界的使用区别

    • 在主应用中不需要做任何改造
    • 在子应用中:
      • 开放跨域配置,因为子应用是在主应用域内请求和运行的
      • 对webpack应用,修改动态加载路径
      • 当子应用保活模式无需进一步的修改,非保活模式需要将实例挂载到无界声明周期内
    1. if (window.__POWERED_BY_WUJIE__) {
    2. let instance;
    3. window.__WUJIE_MOUNT = () => {
    4. instance = new Vue({ router, render: (h) => h(App) }).$mount("#app");
    5. };
    6. window.__WUJIE_UNMOUNT = () => {
    7. instance.$destroy();
    8. };
    9. } else {
    10. new Vue({ router, render: (h) => h(App) }).$mount("#app");
    11. }

    1-4 实现细节

    实现细节部分看链接:基于 iframe 的全新微前端方案 - 腾讯云开发者社区-腾讯云

    1-5 无界微前端框架总结

    无界框架的优点:

    • 多应用同时激活在线框架具备同时激活多应用,并保持这些应用路由同步能力
    • 组件式的使用方式无需注册,无需路由适配,在组件内使用,跟随组件装卸,卸载
    • 应用级别的keep-alive子应用开启保活模式,应用发生切换时整个子应用的状态可以先保存下来不丢失,结合预执行模式可以获得类似ssr的打开模式
    • 纯净无污染
      • 利用iframe和ShadowRoot搭建js隔离沙箱和css隔离沙箱
      • 利用iframe的history和主应用的history在同一个top-level browsing context来搭建天然的路由同步机制
    • 性能和体积兼具
    • 开箱即用,样式的兼容、路由的处理、弹窗的处理、热更新的加载,子应用完成接入即可开箱即用无需额外处理,使得应用接入成本降低

    无界框架的缺点:

    • 内存占用高,在使用时我们为了降低子应用白屏时间,将未激活应用的shadowRoot和iframe常驻内存并且保活模式下每张页面都需要独占一个wujie实例,内存开销较大
    • 兼容性一般,目前使用的浏览器shadowRoot和proxy能力,但是没有做降级方案
    • 某些第三方库无法兼容导致穿透,iframe劫持document到shadowRoot时,某些第三方库可能无法兼容导致穿透

    2、qiankun

    下面我们来学习qiankun的微前端框架,学习链接

    2-1 微前端知识温故

    • 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化web应用的技术手段及方法策略
    • 微前端的诞生主要为了解决如下两个问题
      • 复用(嵌入)别人的项目页面,且别人的项目运行在他自己的环境上
      • 将原先一个巨无霸应用拆分一个个的小项目,这些小项目既可以独立开发部署,又可以自由组合
    • 微前端的好处
      • 技术无关
      • 快速打包,独立部署,互不影响
      • 可以很方便的复用已有的功能模块,避免重复开发
    • 微前端的主要解决方案
      • iframe方案
        • 特点是提供了浏览器原生硬隔离方案,解决了样式隔离,js隔离的问题
        • 问题:隔离性无法被突破,导致应用间上下文无法被共享(本地存储/全局变量/公共插件),两个项目不同源(跨域)情况下数据传输需要依赖postMessage,导致一系列的开发体验问题
      • single-spa方案
        • 此框架上手不简单,开发部署需要修改大量的webpack的配置,且对子项目的改造也很多
        • 此框架让父子项目属于同一个document,好处:数据、文件和公共插件可以共享;缺点js/css污染
        • 将多个单页面应用聚合为一个整体应用的JS微前端框架,即:将子项目的内容插入到主项目中呈现子项目的内容

    2-2 qiankun

    a、基础知识

    • qiankun是一个基于single-spa的微前端实现库,在此基础上实现开箱即用,使得子项目只需要很少的改动,就可以接入
    • qiankun主要特征
      • 基础single-spa封装,提供了更加开箱即用的API
      • 技术栈无关,任何技术栈均可使用
      • HTML Entry接入方式,使得接入微应用和iframe简单度相似
      • 样式隔离,确保微应用之间样式互不干扰
      • JS沙箱,确保微应用之间全局变量/事件 不冲突(JS沙箱代表:一块完全独立的区域,使用的都是自己独立的属性和方法)
      • 资源预加载,在浏览器空闲时间预加载未打开的微应用资源,加速微应用打开速度
      • umi插件,提供了 @umijs/plugin-qiankunumi 应用一键切换成微前端架构系统

    b、快速开发使用步骤

    主应用中:

    主应用不限技术栈,只需要提供一个容器DOM,然后注册微应用再start即可

    • 安装:npm i qiankun -S 或 yarn add qiankun

    主应用中注册微应用

    方法1:微前端与路由关联

    1. import { registerMicroApps, start } from 'qiankun';
    2. registerMicroApps([
    3. {
    4. name: 'react app', // app name registered
    5. entry: '//localhost:7100',
    6. container: '#yourContainer',
    7. activeRule: '/yourActiveRule',
    8. },
    9. {
    10. name: 'vue app',
    11. entry: { scripts: ['//localhost:7100/main.js'] },
    12. container: '#yourContainer2',
    13. activeRule: '/yourActiveRule2',
    14. },
    15. ]);
    16. start();

    微应用信息注册完之后,浏览器的url发生变化,便会自动触发qiankun的匹配逻辑,所有activeRule规则匹配的微应用就会被插到指定的container中,同时依次调用微前端暴露出的生命周期钩子

    方法2:微前端与路由无关联

    微前端不直接与路由关联时,可以手动加载微前端

    1. import { loadMicroApp } from 'qiankun';
    2. loadMicroApp({
    3. name: 'app',
    4. entry: '//localhost:7100',
    5. container: '#yourContainer',
    6. });

    微应用中:

    微应用不需要额外安装任何其他依赖即可接入qiankun主应用

    a、导出相应的生命周期钩子

    微应用需要在自己的入口js(即:配置的webpack的entry.js)导出bootstrap、mount、unmount三个生命周期钩子,来供主应用在适当的时机调用

    1. /**
    2. * bootstrap 只会在微应用初始化的时候调用一次,下次微应用重新进入时会直接调用 mount 钩子,不会再重复触发 bootstrap。
    3. * 通常我们可以在这里做一些全局变量的初始化,比如不会在 unmount 阶段被销毁的应用级别的缓存等。
    4. */
    5. export async function bootstrap() {
    6. console.log('react app bootstraped');
    7. }
    8. /**
    9. * 应用每次进入都会调用 mount 方法,通常我们在这里触发应用的渲染方法
    10. */
    11. export async function mount(props) {
    12. ReactDOM.render(<App />, props.container ? props.container.querySelector('#root') : document.getElementById('root'));
    13. }
    14. /**
    15. * 应用每次 切出/卸载 会调用的方法,通常在这里我们会卸载微应用的应用实例
    16. */
    17. export async function unmount(props) {
    18. ReactDOM.unmountComponentAtNode(
    19. props.container ? props.container.querySelector('#root') : document.getElementById('root'),
    20. );
    21. }
    22. /**
    23. * 可选生命周期钩子,仅使用 loadMicroApp 方式加载微应用时生效
    24. */
    25. export async function update(props) {
    26. console.log('update props', props);
    27. }

    b、配置微应用的打包工具

    代码暴露出相应的声明周期钩子之外,为了让主应用可以正确的识别微应用暴露出来的一些信息,微前端的打包工具webpack增加如下配置

    1. const packageName = require('./package.json').name;
    2. module.exports = {
    3. output: {
    4. library: `${packageName}-[name]`,
    5. libraryTarget: 'umd',
    6. jsonpFunction: `webpackJsonp_${packageName}`,
    7. },
    8. };

    c、项目实战

    此为学习总结,有错误的地方请指正 ~

  • 相关阅读:
    Linux网络-MAC协议
    Python将list中的所有元素转为字符串
    Android入门第16天-Android里的SwitchButton的使用
    正则表达式
    Android应用内设置多语言
    Json数据格式
    ES 8.14 向量搜索优化
    前端(react)上传到阿里云OSS存储 实例
    LQ0143 砍竹子【序列处理】
    星际争霸之小霸王之小蜜蜂(十四)--资本家的眼泪
  • 原文地址:https://blog.csdn.net/qq_45829293/article/details/126360466