当第一次听到微前端这个词汇的时候,并不是很理解这是什么意思,一开始以为是和大前端一样的称呼。后来偶然的一次项目开发中才了解到什么是微前端。 微前端是一种类似于微服务的架构,它将微服务的理念应用于浏览器端,即将 Web 应用由单一的单体应用转变为多个小型前端应用聚合为一的应用。各个前端应用可以独立运行、独立开发、独立部署。
微前端的优缺点
优点
- 现在的前端技术更新迭代是相当大的,微前端的架构可以让团队不断引进新的技术和框架,提高开发效率、质量、用户体验。微前端可以很好的实现应用和服务的隔离,互相之间几乎没有影响。
- 可以让项目更加健壮,减少代码在主体项目中的体量,便于维护项目代码。让项目可以更灵活的满足产品经理以及客户提出的各种需求。
- 微前端的一大优势就是可以独立部署。当某个微前端应用需要迭代时,不需要迭代整个主框架代码,不需要整体下线或一次性升级所有内容,只需要单独迭代该微前端应用即可。
缺点
- 不同微前端应用之间依赖的包存在很多重复,由于各应用独立开发、编译和发布,难免会存在重复依赖的情况。导致不同应用之间需要重复下载依赖,额外再增加了流量和服务端压力。
- 前端实现时的父子应用通讯可能较为复杂。
- 对于浏览器有要求。(看实现微前端的技术)
微前端实现的方式
这里详细介绍一种iframe.也是实现起来最为简单的一种。
iframe
使用iframe实现,这也是我们公司项目中使用的实现方式。公司CTO的理念就是:simple is stable.当使用iframe的时候,就会遇到一个比较常见的问题:跨域。比较常见的解决跨域的方法就是使用postmessage事件去监听。
postMessage方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
语法:
otherWindow.postMessage(message, targetOrigin, [transfer]);
- otherWindow:其他窗口的引用,如 iframe的contentWindow、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
- message:将要发送到其他window的数据。
- targetOrigin:指定那些窗口能接收到消息事件,其值可以是字符串 “*” 表示无限制,或者是一个URI。
- transfer:是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送方将不再保留所有权。
postMessage方法被调用时,会在所有页面脚本执行完毕之后像目标窗口派发一个 MessageEvent 消息,该MessageEvent消息有四个属性需要注意:
window.addEventListener("message", receiveMessage, false);
- type:表示该message的类型
- data:为 postMessage 的第一个参数
- origin:表示调用postMessage方法窗口的源。用 postMessage 时消息发送方窗口的 origin . 这个字符串由 协议、“://“、域名、“ : 端口号”拼接而成。例如 “example.org (隐含端口 443)”、“example.net (隐含端口 80)”、“example.com:8080”。请注意,这个origin不能保证是该窗口的当前或未来origin,因为postMessage被调用后可能被导航到不同的位置。
- source:记录调用postMessage方法的窗口对象。对发送消息的窗口对象的引用; 您可以使用此来在具有不同origin的两个窗口之间建立双向通信。
使用postMessage时的安全问题。
-
如果您不希望从其他网站接收message,请不要为message事件添加任何事件侦听器。 这是一个完全万无一失的方式来避免安全问题。
-
如果您确实希望从其他网站接收message,请始终使用origin和source属性验证发件人的身份。 任何窗口(包括例如http://evil.example.com)都可以向任何其他窗口发送消息,并且您不能保证未知发件人不会发送恶意消息。 但是,验证身份后,您仍然应该始终验证接收到的消息的语法。 否则,您信任只发送受信任邮件的网站中的安全漏洞可能会在您的网站中打开跨网站脚本漏洞。
-
当您使用postMessage将数据发送到其他窗口时,始终指定精确的目标origin,而不是*。 恶意网站可以在您不知情的情况下更改窗口的位置,因此它可以拦截使用postMessage发送的数据。
A 页面
<iframe id="a" src="{url}"></iframe>
let miniAppIframe = document.getElementById("a");
setTimeout(() => {miniAppIframe.contentWindow.postMessage("hello there!", "http://example.org");})
function receiveMessage(event)
{
// 我们能相信信息的发送者吗? (也许这个发送者和我们最初打开的不是同一个页面).
if (event.origin !== "http://example.org")
return;
// event.source
// event.data 是发送给当前页面的消息 "hi there yourself! the secret response is: rheeeeet!"
}
window.addEventListener("message", receiveMessage, false);
B页面
window.addEventListener("message", receiveMessage, false)
function receiveMessage(event) {
if (event.origin !== "http://example.com:8080")
return;
// event.source 就当前弹出页的来源页面
// event.data 是 "hello there!"
// 假设你已经验证了所受到信息的origin (任何时候你都应该这样做), 一个很方便的方式就是把event.source
// 作为回信的对象,并且把event.origin作为targetOrigin
event.source.postMessage("hi there yourself! the secret response " + "is: rheeeeet!", event.origin);
}
路由分发式微前端
路由分发式微前端,即通过路由将不同的业务分发到不同的、独立前端应用上。其通常可以通过 HTTP 服务器的反向代理来实现,又或者是应用框架自带的路由来解决。 就当前而言,通过路由分发式的微前端架构应该是采用最多、最易采用的 “微前端” 方案。但是这种方式看上去更像是多个前端应用的聚合,即我们只是将这些不同的前端应用拼凑到一起,使他们看起来像是一个完整的整体。但是它们并不是,每次用户从 A 应用到 B 应用的时候,往往需要刷新一下页面。 -- 引用自phodal 微前端的那些事儿
目前自己还没有研究!所以也不知道这块该怎么写。
就简单的写到这里了!