当前位置: 首页 > 科技观察

本文带你走进微前端的世界

时间:2023-03-19 01:49:03 科技观察

什么是微前端?批量应用转化为多个小前端应用聚合为一个的应用。2016年的TECHNOLOGYRADAR[1]中提到了微前端这个词。微前端架构具有以下特点:技术栈无关。主框架不限制接入应用的技术栈,微应用拥有完全的自主开发和部署的自主权。微应用仓库独立,前后端可独立开发。部署完成后,主框架自动完成同步更新和增量升级。面对各种复杂的场景,我们通常很难升级或重构现有系统的整个技术栈,而微前端是一个很好的在独立运行时实现渐进重构的手段和策略。各个微应用之间状态隔离,运行时状态不共享。微前端解决什么问题?微前端架构旨在解决单体应用在较长时间跨度内的问题。由于参与人员和团队的增加和变化,从普通应用演化为前端单体应用(FrontendMonolith)后,随之而来的是应用不可维护的问题。例如:一个项目原来由一个团队管理,后来由多个团队管理。随着项目规模变大,编译速度变长,研发效率下降。随着项目变大,系统的复杂度也会相应增加。越来越低,重构的成本越来越高……把微前端拆分成一个容器应用和多个子应用后,各个应用可以独立部署,相互隔离,从而实现:研发效率提升:多个业务线并行开发,团队自主,独立迭代运维风险降低:变更范围变窄技术选择增加:每个应用都可以选择更适合自己的技术栈重构风险减量:低风险部分置换,逐步完成大规模改造。..微前端与Nginx路由转发的实现方案对比通过Nginx配置反向代理,将不同的路径映射到不同的应用。例如www.abc.com/app1对应app1,www.abc.com/app2对应app2。这个方案本身不属于前端层面的改造,更多的是属于运维的配置。优点:简单、快速、易于配置缺点:切换应用时,浏览器会刷新,影响体验。iframe嵌套父应用为单页,每个子应用嵌套一个iframe,父子通信可以使用postMessage或contentWindow。优点:实现简单,子应用之间内置沙箱,自然隔离,互不影响缺点:url不同步。浏览器刷新iframeurl状态丢失,后退和前进按钮无法使用。UI不同步,DOM结构不共享。想象一下,在屏幕右下角的iframe中有一个带有遮罩层的弹框。同时,我们要求这个弹框显示在浏览器的中央,并且在浏览器调整大小时自动居中。全局上下文完全隔离,内存变量不共享。针对iframe内外系统的通信和数据同步需求,必须将主应用的cookie透传给不同根域名的子应用,以达到避免登录的效果。慢的。每个子应用入口都是一个浏览器上下文重构和资源重新加载的过程。WebComponents的每个子应用都需要使用纯WebComponents技术编写组件,这是一种全新的开发模式。优点:每个子应用都有独立的script和css,也可以单独部署。缺点:对于历史系统,改造成本高,子应用之间通信困难复杂易踩webpack5的ModuleFederation使用ModuleFederation,我们可以在一个应用中动态加载和执行另一个应用的代码,无论的技术栈,并可以共享模块,从而减少编译时间和包大小。优点:可以共享模块,减少编译时间和包体积缺点:需要升级webpack5,构建工具受限联合应用路由分发每个子应用独立构建和部署,父应用在运行时进行路由管理和应用加载。启动、卸载和通信机制。优点:纯前端改造,体验好,无感知切换,子应用相互隔离缺点:需要设计和开发,因为父子应用运行在同一个页面,样式冲突等技术点子应用、可变对象污染、通信机制等需要解决组合应用路由分发是目前业界普遍采用的解决方案,可以满足大部分需求。接下来,让我们详细看一下这个实现。组合应用路由分发的微前端实现思路本方案采用base模式,通过一个主应用(baseapplication-MainAPP)管理其他应用(sub-applications-MicroAPP)。基础应用大部分是一个前端SPA项目,主要负责应用注册、路由映射、消息传递等,而微应用是一个独立的前端项目。这些项目不限于React、Vue、Angular或JQuery开发。每个微应用都注册在码头应用中,由码头管理,但如果脱离码头,则可以独立访问。整个微前端框架运行时,用户体验类似下图:简单的描述就是在基础应用中有一些菜单项,点击每个菜单项可以显示对应的微应用。这些应用的切换是纯无前端感知的上述实现过程,主要是获取注册中心和初始化,这些都是在基础应用中进行的。路由分配。浏览器路径发生变化后,dock应用会监听hashchange或popstate事件,获取路由切换的时机。通过查询注册信息,可以得到转发到的微应用。经过一些逻辑处理后,使用修改后的hash方法或pushState方法将路由信息推送到微应用。小程序可以手动监听hashchange或者popstate事件接收,或者使用React-router和vue-router接管路由,后续逻辑由小程序自己控制。远程拉取资源和加载应用程序。这里一般使用JavaScriptEntry或者HTMLEntry作为渲染入口。注意:子应用也可以打包成多个包,然后使用webpack的webpack-manifest-plugin插件打包manifest.json文件生成资源列表,然后主应用的loadApp可以远程读取每个子应用的manifest文件,依次加载文件中的资源;但是,该方案无法享受子应用的按需加载能力。HTML输入。更加灵活,直接将子应用的HTML作为入口打出来,主框架可以通过fetchhtml获取子应用的静态资源,同时将HTML文档作为子节点插入到主框架的容器。这样不仅大大降低了主应用的接入成本,基本不需要调整子应用的开发方式和封装方式,也自然解决了子应用之间的风格隔离问题(后面会提到)。这个方案可以通过。JavaScript入口。通常子应用程序将资源打包成一个入口脚本。但是这种方案也有很多局限性,比如需要将子应用的所有资源都打包成一个jsbundle,包括css、images等资源。除了包可能很大的问题外,资源的并行加载等特性也无法使用。微前端应用隔离CSS隔离主应用和微应用同屏渲染时,部分样式可能会相互污染。可以采用以下两种方案:CSSModule命名空间,通过webpack的postcss插件,添加特定的前缀,即每个子应用使用特定的前缀来命名类。但是对于一些插入到body中的样式,比如elementUI的Popover弹出框,这个要特殊处理。但是,微应用之间的CSS隔离非常简单。每次加载应用程序时,都会标记应用程序的所有链接和样式内容。App卸载后,在卸载页面同步对应的链接和样式即可。JavaScript隔离当一个微应用的JavaScript加载运行时,其核心其实就是全局对象Window的修改和一些全局事件的变化。比如jQueryjs运行后,会在Window.$对象上挂载一个窗口,对于React、Vue等其他类库也不例外。为此,在加载和卸载各个微应用时,需要尽可能地消除这种冲突和影响,最常用的方法是采用沙箱机制(SandBox)。沙箱机制的核心是在本地JavaScript运行时,使外部对象的访问和修改在可控范围内,即无论在内部如何运行,都不会影响外部对象。通常在Node.js端可以使用vm模块,而对于浏览器则需要结合with关键字和window.Proxy对象来实现浏览器端的沙箱。微前端的消息通信微前端通常不限制应用程序使用的框架。如何在不同的应用程序和框架之间进行通信是一个需要仔细考虑的决定。有许多方法可以在应用程序之间进行通信。当然,要实现多个独立的微应用之间的通信,本质上还是离不开一个中介或者一个全局对象。自定义事件通过事件进行通信应该是最简单和最常见的解决方案[3]。//监听事件window.addEventListener('message',(event)=>{//处理事件});//触发事件window.dispatchEvent(newCustomEvent('message',{detail:input.value}))release-订阅消息订阅(pub/sub)模式的通信机制非常适用。基础应用中会定义事件中心Event,每个微应用会单独注册事件。事件触发后,由事件中心统一分发。这形成了基本的通信机制。import{Observable}from'windowed-observable';constobservable=newObservable('konoha');observable.subscribe((ninja)=>{console.log(ninja)})observable.publish('UchihaShisui');WebWorkers通过WebWorkers来通信事件。importWorkyfrom'worky'constworker=newWorky("some-worker.js");worker.on("eventName",function(some,data){//process});worker.emit("someEvent",和一些数据);共享状态主应用程序创建状态存储并与子应用程序共享。适用于主、子应用技术栈相同的场景。总结微前端是将单个巨应用转化为多个微应用的应用,可以解决“单体应用”的维护问题。微前端的实现方式有很多种,每种方案都需要考虑应用隔离和应用通信的问题。目前比较常用的是组合路由分发方式。参考微前端(一)——概念【4】微前端——最容易理解的微前端知识【5】微前端解决什么问题?[6]微前端如何落地[7]微前端解决方案[8]HTMLEntry源码解析[9]参考资料[1]科技雷达:https://www.thoughtworks.com/zh-cn/radar/techniques/micro-frontends[2]import-html-entry:https://www.npmjs.com/package/import-html-entry[3]事件:https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent[4]微前端(一)-概念:https://www.lumin.tech/blog/micro-frontends-1-concept/[5]微前端-最容易理解微前端知识:https://juejin.cn/post/6844904162509979662[6]微前端解决什么问题?:https://cloud.tencent.com/developer/article/1546556[7]微前端如何端登陆:https://www.infoq.cn/article/xm_aaiotxmlppgwvx9y9[8]微前端解决方案:https://segmentfault.com/a/1190000040275586[9]HTML入口源码分析:https://juejin.cn/post/6885212507837825038#heading-6