当前位置: 首页 > news >正文

微前端-monorepo-无界

文章目录

  • 前言
  • 一、微前端
  • 二 、monorepo
  • 三 、pnpm
    • 硬链接
    • 软链接(符号链接)
    • 幽灵依赖
    • 依赖安装耗时长
    • monorepo项目搭建
    • 子模块复用
  • 四、无界
    • 接入无界
    • 无界预加载
    • 无界传参
  • 总结


前言

本文主要记录微前端框架 无界 的使用与理解以及monorepo代码管理方式。


一、微前端

如今项目体积越来越大,导致维护成本增加,后端以微服务形式将项目拆成不同的服务,前端也需要对项目进行拆解,以达到长久发展的可能性。
在我理解中,微前端就是将前端以某种规则进行隔离,在隔离中也能进行远程访问其他小应用,不受技术栈的影响,带来更多的可能性与可维护性。


二 、monorepo

  • monorepo是一个单仓库多应用的代码管理方式,多个项目集成到一个仓库下,共享工程配置,同时又快捷地共享模块代码。
  • 中大型项目,多模块项目monorepo更适合管理代码,对调试、开发都有很大的帮助。

注:在使用monorepo方式管理项目时,会产生诸多问题,如幽灵依赖、依赖安装耗时的问题,需要使用pnpm进行解决这类问题。


三 、pnpm

  • 项目依赖在基于npm时,每个项目都有自己的项目依赖,都需要保存在本地,而pnpm则时将相同依赖项目的依赖包放在同一个位置,让不同项目共享同一个个依赖包,节约硬盘空间,提升了安装速度。
  • 针对不同版本的依赖,则只会保存不同的文件,不会将所有文件都保存

硬链接

共享了同一个硬盘地址
pnpm通过硬链接直接指向 pnpm仓库 依赖包在硬盘的地址

软链接(符号链接)

只会记录路径,不占用资源
如果依赖包之间有相互依赖,则会通过软连接指向该依赖路径,不会指向硬盘地址。

pnpm

幽灵依赖

npm/yarn 安装依赖时,存在依赖提升,某个项目使用的依赖,并没有在其 package.json 中声明,也可以直接使用,这种现象称之为 “幽灵依赖”;随着项目迭代,这个依赖不再被其他项目使用,不再被安装,使用幽灵依赖的项目,会因为无法找到依赖而报错。

使用pnpm可以解决此类问题

依赖安装耗时长

MonoRepo 中每个项目都有自己的 package.json 依赖列表,随着 MonoRepo 中依赖总数的增长,每次 install 时,耗时会较长。

MonoRepo 中每个项目都有自己的 package.json 依赖列表,随着 MonoRepo 中依赖总数的增长,每次 install 时,耗时会较长。

monorepo项目搭建

项目构建需要一个注应用来搭载各个子应用,在安装依赖时需要在最外层创建 pnpm-workspace.yaml 配置文件,通过配置就可以轻松的下载所有项目的依赖。这样会将子项目中公共的依赖提取到外层modules中
项目结构

packages:# all packages in direct subdirs of packages/- 'main'# all packages in subdirs of components/- 'web/**'
  • 在外层目录下可以通过 pnpm -F <子项目文件名> <命令> 的形式执行子项目中的命令

子模块复用

  • 在外层创建common文件,将应用公共的模块提取到该文件夹下,比如axios等。
  • 在主项目main目录下,执行 pnpm -F <项目名称> add common

commob依赖

这样就可以直接在项目中使用common中的东西

import {a} from 'common'

四、无界

对于一些常见的微前端框架(qiankun、micro-app、EMP),对vite都不太友好,所以这里采用无界来搭建微前端框架

特点

  • 接入简单只需要四五行代码
  • 不需要针对vite额外处理
  • 预加载
  • 应用保活机制

不足

  • 隔离js使用一个空的iframe进行隔离
  • 子应用axios需要自行适配
  • iframe沙箱的src设置了主应用的host,初始化iframe的时候需要等待iframe的location.orign从’about:blank’初始化为主应用的host,这个采- - 用的计时器去等待的不是很优雅。
  • 底层原理 使用shadowDom 隔离css,js使用空的iframe隔离,通讯使用的是proxy

接入无界

  • 在主项目main目录下安装wujie
pnpm i wujie
  • 在主项目main目录下安装对应类型项目的封装插件,该插件是对wujie的封装,从而使wujie的使用更快捷
pnpm i wujie-vue3
  • 在主应用main.ts中引入对应的wujie框架,并注册
import Wujie from 'wujie-vue3'
app.use(router).use(Wujie)
  • 子应用的使用,在主应用中使用WujieVue标签进行使用,在url中传入应用启动地址
  <WujieVue url="http://localhost:5174/" name="vue3"></WujieVue> <WujieVue url="http://localhost:5175/" name="react"></WujieVue> 

界面效果

注:官网只对vue和react进行了封装其他框架需要自行封装

无界预加载

预加载能力可以极大的提升子应用打开的首屏时间

只需要在preloadApp中将 exec 设置为true即可

在主项目下main.ts文件中配置exec

preloadApp({url:"http://localhost:5174/", name:"vue3",exec: true})
preloadApp({url:"http://localhost:5175/", name:"react",exec: true})

由于子应用提前渲染可能会导致阻塞主应用的线程,所以无界提供了类似 react-fiber 方式来防止阻塞线程
react-fiber模拟了requestIdleCallback API ,预加载都被requestIdleCallback包裹,在浏览器空闲的时候提前预加载一些内容
requestIdleCallback API会有两种情况:

  • 浏览器在每一帧执行一系列任务,如果有剩余时间就执行 requestIdleCallback
    • 处理用户事件
    • 执行定时器任务
    • 执行requestAnimationFrame动画
    • 执行dom的回流与重绘
    • 计算更新图层的绘制指令
    • 绘制指令合并主线程
  • 浏览器没有任务执行,会有50ms空余时间去执行 requestIdleCallback

无界传参

无界的通讯系统又三种方式进行通讯分别是:

  • props通讯

主应用可以通过props注入数据和方法:

<WujieVue name="xxx" url="xxx" :props="{ data: xxx, methods: xxx }"></WujieVue>

子应用可以通过$wujie来获取:

const props = window.$wujie?.props; // {data: xxx, methods: xxx}

props通讯

  • window通讯
    主应用调用子应用的全局数据
window.document.querySelector("iframe[name=子应用id]").contentWindow.xxx;

子应用调用主应用的全局数据

window.parent.xxx;

window通讯

  • eventBus通讯
    发布订阅模式的通讯
    主应用使用方式:
// 如果使用wujie
import { bus } from "wujie";// 如果使用wujie-vue
import WujieVue from "wujie-vue";
const { bus } = WujieVue;// 如果使用wujie-react
import WujieReact from "wujie-react";
const { bus } = WujieReact;// 主应用监听事件
bus.$on("事件名字", function (arg1, arg2, ...) {});
// 主应用发送事件
bus.$emit("事件名字", arg1, arg2, ...);
// 主应用取消事件监听
bus.$off("事件名字", function (arg1, arg2, ...) {});

子应用使用方式:

// 子应用监听事件
window.$wujie?.bus.$on("事件名字", function (arg1, arg2, ...) {});
// 子应用发送事件
window.$wujie?.bus.$emit("事件名字", arg1, arg2, ...);
// 子应用取消事件监听
window.$wujie?.bus.$off("事件名字", function (arg1, arg2, ...) {});

总结

本文主要记录了微前端无界的使用与理解。

http://www.lryc.cn/news/146851.html

相关文章:

  • 阿里云矢量图标透明背景转换/展示时变为黑色解决方法
  • Linux之Shell(二)
  • 以太网POE供电浪涌静电防护推荐TVS二极管
  • 如何在 JavaScript 中查看结构体数组?
  • 【SpringBoot学习笔记】02.静态资源与首页订制
  • kotlin 转 Java
  • 【Harmony】在Harmony上面可以使用的Android常用的开源库
  • 数学建模:灰色关联分析
  • nodepad++ 插件的安装
  • 学习分享:Ubuntu 下使用 Qt 打开串口报错 Permission denied
  • Javaweb入门
  • 后端开发基础概念
  • ELK原理和介绍
  • FBX SDK 开发环境配置 visual studio 2022
  • vue面试题_vue2和vue3的区别
  • Shiro整合SpringBoot,实战下的应用场景
  • C语言——全局变量和局部变量重名了会怎么样
  • linux下vi或vim操作Found a swap file by the name的原因及解决方法--九五小庞
  • 通过RD Client远程连接windows电脑踩坑点
  • 学习node之——如何在项目中使用MySQL、前后端的身份认证
  • AUTOSAR从入门到精通-【应用篇】参照AUTOSAR架构的柴油车后处理集成电控系统软件设计与研究(续)
  • Linux 内核动态打印调试(dev_info、 dev_dbg )
  • 深入浅出AXI协议(3)——握手过程
  • Ansible学习笔记5
  • LeetCode 面试题 02.06. 回文链表
  • linux环境没有curl或者telnet命令解决方法与区分linux环境类型
  • golang channel
  • 高等职业学校物联网实训室建设方案
  • Python基础学习第四天:Python注释
  • Puppeteer中使用Stealth.min.js库