前言:最近有种感觉,如同微前端成为当下前端工程师的标配,从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团队别离负责蓝色和绿色区域(在红色区域内展现),那他们是怎么实现的?

咱们以绿色区域的性能为示例,来看看demo的代码实例,实质上能够了解为定义一个组件green-recos

通过上图,咱们来剖析这段代码,次要包含以下几点信息:

  • 如何自定义元素?: 通过Api:window.customElements中的defind办法来定义注册好的实例
  • 如何定义一个组件实例?: 通过继承HTMLElement定义一个是实例类
  • 如何与内部通信的?:通过创立一个CustomEvent来自定义一个新的事件,而后通过addEventListener来监听以及element.dispatchEvent() 来散发事件
  • 如何管制组件的生命周期?: 次要是包含这几个生命周期函数,程序如下

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

拓展:

  • 具体demo能够fork下这个仓库: 链接

1.2 对于兼容性

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


你能够看上图 ,大部分浏览器新版本反对,如果想兼容旧版本,莫慌,能够通过引入polyfill来解决兼容问题 webcomponents/polyfills

你也能够通过坚挺WebComponentsReady这个事件来得悉web components是否胜利加载

1.3 对于款式抵触

对于款式,下面例子的款式是全局援用的,并没有解决款式抵触的问题,那如果想基于Web Components 开发组件,又放心各组件间存在款式抵触,这个时候你能够应用Shadow DOM来解决,有点相似vue中定义组件中的scoped解决

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

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

咱们能够看到通过上图比照上一节的例子,多了attachShadow的办法应用。它是啥玩意?

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

扩大浏览:

  • 以后端工程师遇到了Web Component

1.4 留神细节

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

能够的,然而有一点要留神就是,Vue 组件开发很相似自定义元素,如果咱们不做点“伎俩”解决,vue会把你基于Web Component开发的组件当作自身框架下的组件来对待,so 咱们须要配置ignoredElements,下图是vue官网的示例

如果想理解更多对于Web Component的组件开发,能够看看上面这个开源的组件库

  • github:xy-ui

2 Mrcio-app

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

应用过qiankun的童鞋晓得,咱们要在基座集成一个微利用离不开上面 这三要素:

  • 在基座注册子利用
  • 须要在子利用定义好生命周期函数
  • 批改微利用的webpack打包形式

尽管革新老本不算特地高,然而能尽量升高对源代码的侵入性不香吗?

Mrcio-app 走的就是极简的路线,只有批改一丢丢代码就能够实现微利用的集成,号称是目前市面上接入微前端老本最低的计划。那它是如何做到的?

2.1 原理

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

官网介绍:通过自定义元素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等,而是另辟蹊径,当你在基座集成后,在基座能够间接定义,也能够进行全局监听。如下所示

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

  • 资源地址主动补全:咱们在基座加载微利用的时候,当微利用波及图片或其余资源加载时,如果拜访门路是绝对地址,咱们会发现会以基座利用所在域名地址补全动态资源,导致资源加载谬误。而micro-app反对将子利用动态资源的绝对地址补全为相对地址,解决了上述的问题

2.3 实际

2.3.1 demo上手

上手也很简略,以vue2利用为例,具体参考 github文档。这里不做反复陈说

通过官网在线演示vue微利用Demo,咱们来看看集成后的成果

在控制台咱们能够看到,基座加载完微利用"vue2",在自定义标签micro-app渲染后就是一个残缺子利用Dom,有点相似iframe的感觉,而后该子利用的css款式,都多了一个前缀 micro-app[name=vue2]。这是利用标签的name属性为每个款式增加前缀,将子利用的款式影响禁锢在以后标签区域,防止各个微利用之间的款式抵触。这是micro-app的默认隔离机制

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

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

2.3.2 渲染微利用的过程

渲染微利用的过程次要流程图能够参照官网提供,次要包含以下流程

  • fetch 子利用HTMl: 获取html,而后转换为dom构造并递归解决每一个子元素,对不同元素做相应的解决 源码链接

目标是为了提取微利用的link和script,绑定style作用域。最初实现将微利用的style挂在micro-app-head中 外围源码如下

通过源码的浏览,当咱们在微利用的初始化定义的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个性的反对状况来定义不同的款式的规定

最初将转化胜利的style内容,append到micro-app-head中

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

是的,如果开启shadowDOM后,下面提到的默认的款式隔离将生效。 且兼容性会比拟差

上面是个删减版:对于mircro-app通过Web Component + shadowDOM的实现子利用初始化的定义,具体的源码你能够浏览框架源码中对于micro_app_element的定义 源码链接

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

3 写到最初

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

你好,我是 树酱,请你喝杯 记得三连哦~

1.浏览完记得点个赞哦,有 有能源

2.关注公众号前端那些趣事,陪你聊聊前端的趣事

3.文章收录在Github frontendThings 感激Star✨