乐趣区

关于javascript:这种微前端设计思维听说过吗

前言:最近有种感觉,如同微前端成为当下前端工程师的标配,从 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✨

退出移动版