前言:最近有种感觉,如同微前端成为当下前端工程师的标配,从 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 中理解到两个特色:CustomElement
和ShadowDom
,前者使得咱们能够创立自定义标签,后者则促使咱们能够创立反对隔离款式和元素隔离的暗影 DOM。而首次提及的 类 WebComponent是个啥玩意?实质上就是通过应用 CustomElement 联合自定义的 ShadowDom 实现 WebComponent 基本一致的性能
换句话说:让微前端下微利用实现真正意义上的组件化
2.2 很赞的机制
micro-app 有这几个机制我感觉很赞:
- 不必像 qiankun 一样在每个微利用都事后定义好生命周期函数,如:
created
、mounted
等,而是另辟蹊径,当你在基座集成后,在基座能够间接定义,也能够进行全局监听。如下所示
上图的属性配置中 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✨