无界
使用iframe有三个难以解决的问题,
- 路由状态丢失,刷新一下,iframe的url状态就丢失了
- dom割裂严重,弹窗只能在iframe内部展示,无法覆盖全局
- 通信非常困难,只能通过postmessage传递序列化的消息
无界微前端框架通过继承iframe的优点,解决iframe的缺点,打造一个接近完美的iframe方案
在应用A中构造一个shadow和iframe,然后将应用B的html写入shadow中,js运行在iframe中,注意iframe的url,iframe保持和主应用同域但是保留子应用的路径信息,这样子应用的js可以运行在iframe的location和history中保持路由正确。
在iframe中拦截document对象,统一将dom指向shadowRoot,此时比如新建元素、弹窗或者冒泡组件就可以正常约束在shadowRoot内部。
- dom割裂严重的问题,主应用提供一个容器给到shadowRoot插拔,shadowRoot内部的弹窗也就可以覆盖到整个应用A
- 路由状态丢失的问题,浏览器的前进后退可以天然的作用到iframe上,此时监听iframe的路由变化并同步到主应用,如果刷新浏览器,就可以从url读回保存的路由
- 通信非常困难的问题,iframe和主应用是同域的,天然的共享内存通信,而且无界提供了一个去中心化的事件机制
iframe+ web component
- 接入简单:安装一个组件即可 wujie-vue
- css隔离
- js 隔离
Shadow DOM 是 Web Components 技术的一部分,它允许开发者创建封装、可复用的组件。当一个元素使用 Shadow DOM 创建时,它会包含一个 Shadow Root,这是一个独立的 DOM 子树,与文档中的其他部分相互隔离,可以在其中定义和控制样式和行为。因此,Shadow DOM 的插拔机制也是非常重要的。
在 Shadow DOM 中,插入和移除节点的过程称为“插拔”。Shadow DOM 提供了以下方法来实现插拔:
- attachShadow(options) 方法:该方法将返回一个 ShadowRoot 对象,通过该对象可以管理 Shadow DOM 的内容。
- appendChild(node) 和 removeChild(node) 方法:这些方法允许向 Shadow DOM 中添加或删除节点。
- MutationObserver API:使用该API,可以监视 DOM 树的变化,并在变化发生时采取适当的行动。
需要注意的是,在 Shadow DOM 中,被插入到 Shadow Root 中的元素有可能难以再次获取或操作,因为它们可能不会出现在文档的正常 DOM 树中。为了解决这个问题,我们可以使用 getElementById() 或 querySelector() 等方法,或者在创建自定义元素时定义自定义方法。
渲染子应用步骤
- 创建一个iframe,插入主应用document
- 立即停止iframe 的加载
- 因为 iframe 的 src 要设置为主应用的域名,继续请求资源会失败
- 修改为主应用域名是为了通信
- 修改请求的域名为子应用的真实域名
- 所以子应用需要能支持跨域
- 解析子应用的入口html
- 识别出html 部分,分离style 和js
- 处理css 重新注入html (有插件系统,可以对子应用的css定义)
- 创建 webComponent 并挂载 HTML
- CSS 由于在 shadowDOM 内,样式也不会影响到外部,也不会受外部样式影响。
- 创建script标签,并插入到 iframe 的 head 中
- 对 iframe 的 document.querySelector 进行改造,需要劫持 document改为从shadowRoot里面查找,才能使 Vue 组件能够正确找到挂载点
微前端蓝图
新团队组建后,首先不得不完成很多设置工作,例如创建一个基本的应用程序,梳理构建流程以及其他繁琐的任务
而共用前端蓝图这一概念能够帮助我们解决上述问题。蓝图实际上是一个示例项目,其中包括微前端项目需要的所有重要部分。可以将蓝图划分为两大类:技术和项目细节
技术细节
- 目录结构
- 测试(单元测试,端到端测试)
- 代码检查以及格式化规则
- 代码风格
- API通信
- 性能的最佳实践(优化静态文件)
- 编译工具配置
上述这些方向是所有项目都必须要考虑的,但并不具有很大的挑战性。大多数主流框架都提供了脚手架工具,能为你生成一个示例项目,但是对于一个团队来说,仅使用默认的前端配置是远远不够的。
项目细节
你的前端代码需要和其他团队进行整合,并且整合必须遵循整体架构的指南。全新的前端项目必须要考虑项目的一些细节。因此,我们的蓝图还应包括:
- 组合示例
- 接入其他微前端的示例
- 令你的微前端可以被接入的示例
- 通信示例
- 如何为团队设置CSS和URL前缀
- 微前端相关文档的模版
- 如何整合托管在中心化服务中的库
- 如何引入本地的库
- 如何开发通用服务,如异常跟踪,分析等
- CI/CD流程
新加入团队可以复制上面的蓝图,根据实际需要稍加改动,即可变成他们自己的蓝图。基于现有蓝图进行开发能够大大的节约时间。