这种微前端设计思维听说过吗?

简介: 前言:最近有种感觉,好像微前端成为当下前端工程师的标配,从single-spa到qiankun,各种微前端架构解决方案层出不穷。那一夜,我在翻阅github时,留意到一个新的微前端框架,来自京东零售开源的MicroApp,号称无需像上面提到那两个框架一样需要对子应用的渲染逻辑调整,甚至还不用修改webpack配置。还有一个成功引起我注意的是:它把web-components的概念给用上了!让我们一探究竟!

微信截图_20220514224314.png


前言:最近有种感觉,好像微前端成为当下前端工程师的标配,从single-spa到qiankun,各种微前端架构解决方案层出不穷。那一夜,我在翻阅github时,留意到一个新的微前端框架,来自京东零售开源的MicroApp,号称无需像上面提到那两个框架一样需要对子应用的渲染逻辑调整,甚至还不用修改webpack配置。还有一个成功引起我注意的是:它把web-components的概念给用上了!让我们一探究竟!


1.饭后小菜 - Web Components 🍵


众所周知,Web Components 是一种原生实现可服用web组件的方案,你可以理解为类似在vue、React这类框架下开发的组件。不同的是,基于这个标准下开发的组件可以直接在html下使用,不用依赖其他第三方的库。


换句话说:部分现代浏览器提供的API使我们创建一个可复用的组件而无需依赖任何框架成为一种可能,不会被框架所限制


主要包括以下几个特征:

  • 使用custom elements自定义标签
  • 使用shadow DOM做样式隔离
  • 使用 templates and slots 实现组件拓展 (本期不拓展)


那 Web Components是如何创建一个组件的?我们来看下下面这个demo实践


1.1 实践


针对web components的实践, 我在github上找到一个demo。如下图所示,假设一个页面是由三个不同团队负责独立开发,A团队负责红色区域的整体展示功能,B团队和C团队分别负责蓝色和绿色区域(在红色区域内展示),那他们是怎么实现的?


微信截图_20220514224331.png


我们以绿色区域的功能为示例,来看看demo的代码实例,本质上可以理解为定义一个组件green-recos


微信截图_20220514224342.png


通过上图,我们来分析这段代码,主要包括以下几点信息:


  • 如何自定义元素?: 通过Api:window.customElements中的defind方法来定义注册好的实例
  • 如何定义一个组件实例?: 通过继承HTMLElement定义一个是实例类
  • 如何与外部通信的?:通过创建一个CustomEvent来自定义一个新的事件,然后通过addEventListener来监听以及element.dispatchEvent() 来分发事件
  • 如何控制组件的生命周期?: 主要是包括这几个生命周期函数,顺序如下 👇


constructor(元素初始化) -> attributeChangedCallback(当元素增加、删除、修改自身属性时,被调用) -> connectedCallback(当元素首次被插入文档DOM时,被调用) -> disconnectedCallback(当 custom element从文档DOM中删除时,被调用)`


拓展:


1.2 关于兼容性


👨‍🎓 啊乐同学:树酱,听说web component兼容性不太好?咋整?


微信截图_20220514224356.png


你可以看上图👆 ,大部分浏览器新版本支持,如果想兼容旧版本,莫慌,可以通过引入polyfill来解决兼容问题 webcomponents/polyfills


你也可以通过坚挺WebComponentsReady这个事件来得知web components是否成功加载


1.3 关于样式冲突


关于样式,上面例子的样式是全局引用的,并没有解决样式冲突的问题,那如果想基于Web Components 开发组件,又担心各组件间存在样式冲突,这个时候你可以使用Shadow DOM来解决,有点类似vue中定义组件中的scoped处理


Shadow DOM: 也称影子DOM,它可以将一个隐藏的、独立的 DOM 附加到一个元素上。如下图MDN官方介绍图所示


微信截图_20220514224417.png


那基于web component如何开发一个挂在#shadow-root的组件?


微信截图_20220514224425.png


我们可以看到通过上图对比上一节的例子,多了attachShadow的方法使用。它是啥玩意?


官方介绍:通过attachShadow来将一个 shadow root 附加到任何一个元素上。它接受一个配置对象作为参数,该对象有一个 mode 属性。当mode为true,则表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM


🌲 扩展阅读:


1.4 注意细节


啊乐同学:树君,那我在vue中可以使用Web Component开发的自定义组件吗?


可以的,但是有一点要注意就是,Vue 组件开发很类似自定义元素,如果我们不做点“手段”处理,vue会把你基于Web Component开发的组件当作本身框架下的组件来看待,so 我们需要配置ignoredElements,下图是vue官网的示例


微信截图_20220514224453.png


如果想了解更多关于Web Component的组件开发,可以看看下面这个开源的组件库


2 Mrcio-app


一不小心绕远了,言归正传,聊聊今日主角:micro-app


使用过qiankun的童鞋知道,我们要在基座集成一个微应用离不开下面👇 这三要素:


  • 在基座注册子应用
  • 需要在子应用定义好生命周期函数
  • 修改微应用的webpack打包方式


虽然改造成本不算特别高,但是能尽量降低对源代码的侵入性不香吗?


Mrcio-app 走的就是极简的路线,只要修改一丢丢代码就可以实现微应用的集成,号称是目前市面上接入微前端成本最低的方案。那它是如何做到的?


2.1 原理


本质上 micro-app 是基于类WebComponent + HTML Entry实现的微前端架构


微信截图_20220514224502.png


官方介绍:通过自定义元素micro-app的生命周期函数connectedCallback监听元素被渲染,加载子应用的html并转换为DOM结构,递归查询所有js和css等静态资源并加载,设置元素隔离,拦截所有动态创建的script、link等标签,提取标签内容。将加载的js经过插件系统处理后放入沙箱中运行,对css资源进行样式隔离,最后将格式化后的元素放入micro-app中,最终将micro-app元素渲染为一个微前端的子应用。在渲染的过程中,会执行开发者绑定的生命周期函数,用于进一步操作。


  • 关于HTML Entry:相信用过qiankun 的童鞋应该都很熟悉,就是加载微应用的入口文件,一方面对微应用的静态资源js、CSS等文件进行fetch,一方面渲染微应用的dom


  • 类WebComponent: 我们在上一节学习web Component中了解到两个特征:CustomElementShadowDom,前者使得我们可以创建自定义标签,后者则促使我们可以创建支持隔离样式和元素隔离的阴影DOM。而首次提及的类WebComponent是个啥玩意?本质上就是通过使用CustomElement结合自定义的ShadowDom实现WebComponent基本一致的功能


换句话说:让微前端下微应用实现真正意义上的组件化


2.2 很赞的机制


micro-app 有这几个机制我觉得很赞:


  • 不用像qiankun一样在每个微应用都预先定义好生命周期函数,如:createdmounted等,而是另辟蹊径,当你在基座集成后,在基座可以直接定义,也可以进行全局监听。如下所示


微信截图_20220514224532.png


上图的属性配置中name是微应用的名称配置,url是子应用页面地址配置,其他则是各个生命周期函数的定义


  • 资源地址自动补全:我们在基座加载微应用的时候,当微应用涉及图片或其他资源加载时,如果访问路径是相对地址,我们会发现会以基座应用所在域名地址补全静态资源,导致资源加载错误。而micro-app支持将子应用静态资源的相对地址补全为绝对地址,解决了上述的问题


微信截图_20220514224542.png


2.3 实践


2.3.1 demo上手


上手也很简单,以vue2应用为例,具体参考 github文档。这里不做重复陈述


通过官方在线演示vue微应用Demo,我们来看看集成后的效果


微信截图_20220514224602.png


在控制台我们可以看到,基座加载完微应用"vue2",在自定义标签micro-app渲染后就是一个完整子应用Dom,有点类似iframe的感觉,然后该子应用的css样式,都多了一个前缀 micro-app[name=vue2]。这是利用标签的name属性为每个样式添加前缀,将子应用的样式影响禁锢在当前标签区域,避免各个微应用之间的样式冲突。这是micro-app的默认隔离机制


啊乐同学:树酱,他这个元素隔离是怎么实现的?


你听我解释,看下一节源码分析


2.3.2 渲染微应用的过程


渲染微应用的过程主要流程图可以参照官方提供,主要包括以下流程


微信截图_20220514224615.png


  • fetch 子应用HTMl: 获取html,然后转换为dom结构并递归处理每一个子元素,对不同元素做相应的处理 源码链接


目的是为了提取微应用的link和script,绑定style作用域。最后实现将微应用的style挂在micro-app-head中 核心源码如下


微信截图_20220514224622.png


通过源码的阅读,当我们在微应用的初始化定义的app.scopecss配置时(默认开启),就会调用scopedCSS处理dom ,以此实现绑定微应用的css作用域,让我们看下这个方法的实现 源码链接


我在源码中看到scoped_css主要针对几种cssRule来做区分处理


啊恒同学:树酱,什么是Css Rule?


这是一个有历史的概念了,CSSRule 表示一条 CSS 规则。而一个 CSS 样式表包含了一组表示规则CSSRule对象。 CSSRule 有几种不同的规则类型,你可以在micro-app主要针对以下几种常规的cssRule区分处理


  • CSSRule.STYLE_RULE: 一般的style规则
  • CSSRule.MEDIA_RULE:  CSS @media 媒体属性查询的规则
  • CSSRule.SUPPORTS_RULE: CSS @support 可以根据浏览器对CSS特性的支持情况来定义不同的样式的规则


微信截图_20220514224633.png


最后将转化成功的style内容,append到micro-app-head中


啊恒同学:树酱,你说micro-app隔离元素支持shadowDom ?


是的,如果开启shadowDOM后,上面提到的默认的样式隔离将失效。 且兼容性会比较差


下面是个删减版:关于mircro-app通过Web Component + shadowDOM的实现子应用初始化的定义,具体的源码你可以阅读框架源码中关于micro_app_element的定义 源码链接


微信截图_20220514224659.png


本质上开启shadowDom后,<micro-app>标签才算真正实现意义上的WebComponent


3 写到最后


关于JS沙箱(sandbox)和数据通信的实现机制等,在后面展开跟童鞋们分享



相关文章
|
7月前
|
移动开发 前端开发 搜索推荐
(前端开发入门必看)一口气读完HTML5与CSS3基础教程,快速建造前端思维(更新中)
(前端开发入门必看)一口气读完HTML5与CSS3基础教程,快速建造前端思维(更新中)
87 0
|
9月前
|
敏捷开发 前端开发 JavaScript
设计思维在前端开发中的应用
设计思维在前端开发中的应用
|
11月前
|
前端开发 架构师
前端学习笔记202304学习笔记第八天-架构师的思维设计需求1
前端学习笔记202304学习笔记第八天-架构师的思维设计需求1
42 0
|
11月前
|
前端开发 架构师
前端学习笔记202304学习笔记第八天-架构师的思维设计需求1
前端学习笔记202304学习笔记第八天-架构师的思维设计需求1
39 0
|
前端开发 JavaScript
思维-网页技术设计大作业前端HTML+CSS+JS(精美完整)
思维-网页技术设计大作业前端HTML+CSS+JS(精美完整)
158 0
思维-网页技术设计大作业前端HTML+CSS+JS(精美完整)
|
4天前
|
Web App开发 缓存 前端开发
前端性能优化的整理笔记(一)
前端性能优化的整理笔记(一)
109 0
|
1天前
|
移动开发 前端开发 JavaScript
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
10款精美的web前端源码的特效,2024年最新面试题+笔记+项目实战
|
4天前
|
存储 前端开发 JavaScript
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
前端笔记_OAuth规则机制下实现个人站点接入qq三方登录
39 1
|
4天前
|
XML 编解码 前端开发
css设计文本样式 前端开发入门笔记(十二)
css设计文本样式 前端开发入门笔记(十二)
7 0
|
4天前
|
Web App开发 XML 前端开发
CSS中的非布局样式+CSS布局 前端开发入门笔记(十一)
CSS中的非布局样式+CSS布局 前端开发入门笔记(十一)
33 0