Why Not Iframe

为什么不用 iframe,这几乎是所有微前端方案第一个会被 challenge 的问题。但是大部分微前端方案又不约而同放弃了 iframe 方案,自然是有原因的,并不是为了 "炫技" 或者刻意追求 "特立独行"。

如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。

iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

1url 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。
2UI 不同步,DOM 结构不共享。想象一下屏幕右下角 1/4 的 iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..
3全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。
4慢。每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

其中有的问题比较好解决(问题1),有的问题我们可以睁一只眼闭一只眼(问题4),但有的问题我们则很难解决(问题3)甚至无法解决(问题2),而这些无法解决的问题恰恰又会给产品带来非常严重的体验问题, 最终导致我们舍弃了 iframe 方案。
2022-04-21 22:20
165135
54
Report
Markup comments (0)
All comments (54)
C7H8N4O2
这么短,意犹未尽啊
熊隆祥
短,但是粗啊
  • 17
  • 1
。。。嗯
莫名其妙的就上高速了

silence
评论虽短,但硬度还是有的👍🏻
  • 2
superman
另外某些情况下,比如网页截屏,iframe 就不被支持
NNNaixQvQ
问题3如果是同域情况下,cookie是可以通过nginx配置到同域名下的子路由然后内部转发到子应用服务的端口。
问题2只能在主应用抽象公共的全局操作,然后在子应用使用postMessage调用。
kuitos
问题2:弹出来的框在位置上一半处于主应用一半处于子应用。。
月光林地
问题3,后端不应该关心前端需要怎样的实现,每增加一个微服务就莫名其妙多了一层代理,长此以往,nginx配置会是一个灾难 问题2,主应用不应该关心微服务,它们应该保持松耦合。如果把真正的实现放在主应用,微服务只负责调postMessage,这种强耦合的跨应用开发方式,那还不如回到单应用
lemontree2000
问题1你们怎么解决的?能给个思路吗
MJX
addEventListener
lock
localstorage
谷佳宇Jay Gu
但是反而没法做到真·跨域了
loszer
第2个是可以解决的,iframe的页面用postMessage传递的message中加入关于“弹窗”的位置、大小等信息,让parent负责去显示
kuitos
这么搞主应用跟 iframe 应用都得累死😂
让上层去显示的话,所有 popup 就都得是上层来负责了。message、alert、notice、dialog 等等。dialog 里再加些交互,比如 dialog 里的表单某一个 checkbox 点击了,需要 iframe 里的页面做个其他响应,比如某个 button 变灰等等。

想象一下这个模式下 iframe 里的应用要怎么编码?
全程没有 UI 渲染全是各种 postMessage 和 onmessage 监听,还要保证消息时序,时序一乱 bug 丛生...
iframe 里的应用不被嵌还跑不起来了,因为只是个消息收发器,连自己的 UI 都没有,全都依赖宿主环境~
想想就觉得酸爽👻
  • 28
凯大胳膊
硬要解决是可以的,但“让parent负责去显示”可不仅要定义位置大小,关键的还有内容,这样父子应用肯定要出一套“关于弹框 UI 的数据协议”,进而子应用的弹框需求也会受制于这套协议。总结就是增加了父子应用的耦合度。
loszer
image.png
嗯。。。。
stone
这还开发个毛😂
The link is not exist

会一点点前端
你说的这个模式应该是部分传统ERP系统采用的模式了,不太能适应更灵活的场景。 不过不可否定的是微前端的选择还是得结合具体业务场景,iframe的最强的就是就在于接入第三方应用0成本。
loszer
都是上班太闲的人[斜眼/笑]
Tusi
bingo,我之前也这么搞过
- Rules° .
我觉得 这不是解决问题的办法 因为违背了微前端的基本原则了,微前端就是需要让每个应用可以独立运行、部署,什么事都在主应用处理,离开了主应用,那他还能独立运行吗,难道还需要做一套兼容是不是在主应用中加载的逻辑吗
  • 3
loszer
(⊙ꇴ⊙) 周末还在上班/学习?!?!
PS:已经调研过了,iframe隔离的太彻底了,要一个轻量的隔离
陈嘉硕
你觉得累死,只是因为作者的举例并不合适。 一个系统里的massage,常态是一致的,所以仅需传递msg即可。 只要涉及到了父子级,不可避免的global data,parent data,child data,emit都会出现
iframe有,乾坤也会有
爱笑的葱葱
问题1.
url不同步,通过postMessage互相通信,确定当前url

问题2.
UI不同步,这个也要通过postMessage解决,但问题也是有的,就像你说的,难道所有的弹窗类的都要在主应用里写?还有的回答说是强耦合……也是好解决的,需要通过一定的方法,可以无感知的在子应用中调用主应用的程序,但是主应用实际用的却是子应用的代码。

后端在这方面用的比较普遍,比如消息队列,grpc之类的
阿里还有一个比较出名的dubbo

问题3.
cookie确实与域名相关,但cookie实质携带的内容却没有限制,而且cookie一般放在redis里面,不同域名的cookie所携带的内容一致,redis那面取出来,只要认出来登录了,并且能够确定哪些域名是可以共享cookie的,那就可以实现单点登录,所以……你说的问题3,问题范围可能有误,这块其实是后端需要配合解决的

那可能有的小伙伴会说:我们的单点登录是通过token,不是cookie,要咋弄?
还是postMessage……你把你登录的token给别人不就好了?cookie共享也可以这么做,但cookie有个http only,一旦设置,js是没办法读取的

问题4. 呃,加载慢……都用微前端了,要的就是隔离!隔离就要独立加载!试试prefetch,加速一下!一旦加载进来就要缓存起来,重复利用!

可能有的小伙伴会说,乾坤更快……就算是再迅速的框架,比如乾坤,也是要把那边的html获取过来吧?然后再处理加工,执行里面的代码,这里面操心的事其实很多!
那你要用iframe就不用操心这个事儿了

最后乾坤子应用其实也可以用到应用全局的变量,并没有完全隔离。可能有人会说沙箱,这个沙箱其实就是代理,用的Proxy对象,你可以设置特定的白名单,但加载后的代码是运行在同一域名下,比如子应用要用sessionStorage,还能不让人家用?子应用如果错误的操作一个key,是不是大家都无法用?我只是举个例子

分割线

乾坤的一些硬伤,也是为了更好的促进乾坤更好的发展

1乾坤无法跨域名,只能在同域名操作
2乾坤的代码目前仍无法完全隔离
3乾坤仍然没有建立一套opinioned方案,比如对比一下spring




爱笑的葱葱
并不耦合,每个弹窗只要有自己独立的id就好
loszer
原来阁下是想在iframe对parent为所欲为。。。。。

七年
用到的就是 在 iframe 里 parent 为所欲为 , 惨不忍睹的场景
风吹麦浪
Quote from the original:问题
2222
xx
3333
Richard
亵渎技术
Toulon
只能说是二者相权取其轻了,虽然iframe可以带来真正意义上最彻底的应用间隔离,但恰恰是因为太过彻底,导致不够灵活。与其使用各种治标不治本的手段花巨大的代价去解决这些问题,并且大概率留下各种难以修复的bug,不如一开始就抛弃它了。
呵呵哒
确实 隔离的太死,导致失去了灵活性!
  • 1
qzttt
问题3 我们在用 postmessage,但是 iframe里面页面跳转以后,同步更新父应用的菜单标签处理上比较费劲,尤其是父应用采用多tags的方式展示页面的话 通信跟麻烦。
隔离 样式 、js iframe 确实做到了,但是 劫持路由这点 自己在代码里实现还是比较麻烦的。
耗子
其实这几个问题,iframe 也是可以解的,比如通过 history 或hash,同步 iframe 里的地址
使用隐式 iframe 加载,提供非白屏体验
使用桥接,弹出全局模式窗口
另外还有个优势,是单页比不了的。比如完全的大域隔离,安全接入一些三方页面
小石头
Quote from the original:challenge
6666
热爱
7777
刘莹鑫
测试
bbb324
Quote from the original:导致应用间上下文无法被共享
postMessage 不算吗
joinmouse
也很想问问这个
热爱
postMessage没办法传递应用间的全局上下文,就像worker里不能访问window一样
子桀
微前端和iframe的关系有点像docker和vmware的区别
  • 1
雨夜千里
事件处理也是个问题,比如实现顶层菜单展开时,需要点击空白处收起,如果点到ifram则无法触发
  • 3
👹
说这个能解决那个能解决的,到底懂不懂什么叫含金。。。哦不,低耦合啊!惹啊
Dengju
Quote from the original:最完美
mark
Winter
是的
洼里哗西
子应用跨域的场景可以用吗?iframe应该是不限制的
ZZZ
目前在用iframe做微前端,确实很多问题。
Alson
简短精辟
你说的对
和不用框架的 多个xx.html放到一个文件夹下面 的最大区别是啥
暴躁小喵
大家现在的产品都是spa了么,多页签的话 qiankun是否就无法适用了?
豆子
慢的问题:慢的问题可以使用单例的iframe,不销毁,而且可以预加载
路由问题:主应用和iframe的路由做个映射关系,这样iframe就可以实时响应url变化了
弹框遮罩、通讯问题:可以在创建iframe的时候把topwindow的对象挂在到子应用的window上,这样子应用就能直接调用topwindow的方法了,比如使用topwindow的弹框,而且这种方式主应用可以往iframe中注入脚本和样式等,通讯也可以通过管理“事件中心实现” (这个方案还在探索中)

rich bai
第一条好解决,子应用的路由跳转可以简单封装下,如果在iframe内,所有的跳转操作都通过postMessage来通知基座应用进行跳转。
第二条是iframe无法解决的。

第三条看场景,公司内的中后台业务一般都有单点登陆,用iframe没啥问题;toC的项目可能会要处理cookie。

第四条也看场景,公司内的中后台业务加载慢点可忍;toC的项目慢了会被产品怼
desert sky
iframe 还有一个问题就是不能改变其在 DOM 树中的位置,否则也会导致重新加载 iframe。而在以 VDOM + Router 的场景中 iframe 都会被重新加载
李正
李正01-17 15:11IP region北京
类比Hybrid的开发模式,问题2和问题3也可以由父层提供bridge能力解决
问题2:父层提供通用弹层,子层通过bridge唤起
问题3:父层提供token,子层通过bridge获取
Sign Up / Login Yuque to comment
54
Adblocker