1、MicroApp
1.1 MicroApp简介
MicroApp是由于京东前端团队推出的一款微前端框架,它从组件化的思维,基于类WebComponent进行微前端的渲染,旨在降低上手难度、提高工作效率。MicroApp无关技术栈,亦不和业务绑定,能够用于任何前端框架。
官网链接: https://micro-zoe.github.io/micro-app/
源码位置: https://github.com/micro-zoe/micro-app
微前端的概念是由于ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每一个应用都能够独立研发、独立运行、独立安排,再将这些小型应用融合为一个完整的应用,或将本来运行已久、无相关的几个应用融合为一个应用。微前端既能够将多个项目融合为一,又能够减少项目之间的耦合,提高项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活。
微前端的显现重点是为认识决了两个问题:
1、随着项目迭代应用越来越庞大,难以守护。
2、跨团队或跨分部协作研发项目引起效率低下的问题。
1.2 关于MicroApp
MicroApp借鉴了WebComponent的思想,经过js沙箱、样式隔离、元素隔离、路由隔离模拟实现了ShadowDom的隔离特性,并结合CustomElement将微前端封装成一个类WebComponent组件,从而实现微前端的组件化渲染,旨在降低上手难度、提高工作效率。
micro-app和技术栈无关,亦不和业务绑定,能够用于任何前端框架。
1.3 MicroApp优点
1、运用简单
咱们将所有功能都封装到一个类WebComponent组件中,从而实此刻基座应用中嵌入一行代码就可渲染一个微前端应用。
2、功能强大
micro-app供给了js沙箱、样式隔离、元素隔离、路由隔离、预加载、数据通信等一系列完善的功能。
3、兼容所有框架
为了保准各个业务之间独立研发、独立安排的能力,micro-app做了许多兼容,在任何前端框架中都能够正常运行。
2、快手上手
在微前端架构中,微前端工程重点由主应用和子应用,下面咱们分别列出主应用和子应用需要进行的修改。
2.1 主应用
首要,咱们需要在主应用中安装依赖。 npm i @micro-zoe/micro-app --save而后,初始化micro-app。 // index.js
import microApp from @micro-zoe/micro-app
microApp.start()而后,在主应用中嵌入子应用,对应的React的写法如下。 export function MyPage () {
return (
<div>
<h1>子应用</h1>
// name:应用名叫作, url:应用位置
<micro-app name=my-app url=http://localhost:3000/></micro-app>
</div>
)
}Vue的写法如下。 <template>
<div>
<h1>子应用</h1>
<!-- name:应用名叫作, url:应用位置 -->
<micro-app name=my-app url=http://localhost:3000/></micro-app>
</div>
</template>2.2 子应用
对应的,咱们需要在子应用的webpack-dev-server的headers中设置跨域支持,如下所示。 devServer: {
headers: {
Access-Control-Allow-Origin: *,
}
},完成以上过程即完成微前端的接入。不外,接入MicroApp需要重视以下几点: 1、name:必传参数,必须以字母开头,且不能够带特殊符号(中划线、下划线除外)
2、url:必传参数,必须指向子应用的index.html,如:http://localhost:3000/ 或 http://localhost:3000/index.html
3、子应用必须支持跨域,跨域配置参考这儿
3、功能简介
3.1 JS沙箱
在MicroApp开源后咱们收到社区的有些反馈,其中一条关于性能的问题导致咱们的注重。这不是MicroApp才存在的问题,而是微前端很久败兴的困难,在社区有海量关于沙箱性能问题的讨论,却始终无完美的处理方法。
MicroApp采用的是和qiankun同样的proxy+with的沙箱方法,这亦是目前js沙箱的主流方法 。with沙箱的功能非常完善,然则性能损耗却非常显著,在社区中亦不乏对with沙箱性能问题的讨论,但始终无尤其完美的处理方法,这是因为with改变了js的功效域链,从而产生海量的重复请求。问题的根源是with,但又不全是with的问题,准确的说是with和proxy两者叠加造成的,with和proxy本质上的性能都不高,需要一种方法避免对这两个办法的频繁读取操作,MicroApp采用的处理方法是变量前置和异步防抖。
• 变量前置:指的是运用Object.defineProperty定义全局变量,经过get和set设置响应数据,一是为了避免在proxy的get中进行多余的操作,二是defineProperty的性能比proxy更优秀 。文案源自位置 https://www.yii666.com/blog/719852.html
• 异步防抖:指的是在子应用运行时对promise进行标记,保证在上一个promise执行完成之后才会进入下一个,避免并行触发,防止promise被频繁触发会导致性能损失。
这里基本上,MicroApp沙箱还供给了快照、缓存、预加载等功能,在保准功能不变的前提下,彻底处理沙箱的性能问题,升级后的沙箱运行效率媲美原生JS。
不外,运用MicroApp沙箱需要重视以下几点:
1,子应用在沙箱环境中怎样获取到真实window
日前有3种方式在子应用中获取外边真实window。 new Function("return window")() 或 Function("return window")()(0, eval)(window)window.rawWindow
2,子应用抛出错误信息:xxx 未定义
xxx未定义错误包含如下有些: xxx is not definedxxx is not a function
Cannot read properties of undefined 产生错误的原由是,在沙箱环境中,顶层变量不会泄漏为全局变量。例如在正常状况下,经过 var name 或 function name () {} 定义的顶层变量会泄漏为全局变量,通过window.name或name就能够全局拜访。然则在沙箱环境下这些顶层变量没法泄漏为全局变量,window.name或name的值为undefined,引起显现问题。
处理的方式有两种:
第1种:将 var name 或 function name () {} 修改为 window.name = xx
第二种:经过插件系统修改子应用代码,例如平常的加载webpack打包的dll文件失败的问题,由于dll文件的内容和js位置相对固定,能够直接进行全局查询和修改。 microApp.start({
plugins: {
modules: {
应用名叫作: [{
loader(code, url) {
if (url === xxx.js) {
code = code.replace(var xx_dll=, window.xx_dll=)
}
return code
}
}]
}
}
})3,基座怎样对子应用 document 的有些属性进行自定义代理扩展
微前端模式下,一般由基座负责设置站点标题,不期盼受到子应用的干扰。然则由于 microApp 对 documet 的代理处理过程,并无处理 document.title,因此子应用中可能经过 document.title = xxx 意外改变了基座的站点标题。
处理的办法是,经过 customProxyDocumentProps 对 document 的属性进行自定义代理扩展经过给title设置一个空函数,来忽略 document.title 执行。 microApp.start({
customProxyDocumentProperties: new Map([
[title, (value) => {}]
]),
})3.2 虚拟路由系统
3.2.1 虚拟路由系统背景
微前端是将多个区别的web应用融合在一块渲染,但浏览器仅有一个路由系统,这很容易导致应用之间的路由冲突,最平常的便是vue3的路由冲突问题。
上面是vue-router作者针对在微前端环境下的冲突问题的回答,他认为vue-router已然覆盖足够多场景,微前端的问题应该由微前端处理。
在咱们刚开源时,并无对路由进行隔离,用户针对MicroApp的问题几乎一半都和路由关联,由于一个路由系统同期满足多个应用的渲染容易引起冲突,亦非常反直觉和难以理解,于是咱们推出了虚拟路由系统。
虚拟路由系统与浏览器的路由行径一致,它经过自定义location和history等核心路由API,重写了popState和hashChange事件,拦截路由导航和事件,并供给了一系列自定义API,模拟了在浏览器环境下的Web应用程序的渲染、转和返回等路由行径。子应用程序在这个虚拟路由系统中运行,与基座应用程序的路由相互隔离,从而避免相互影响,并加强了子应用程序与基座应用程序之间的交互能力。经过虚拟路由系统,基座应用程序能够方便地获取子应用程序的路由信息并掌控子应用程序的转,子应用程序的路由信息会做为参数同步到浏览器位置上。另外,虚拟路由系统还提供了许多功能,帮忙研发人员加强工作效率。
3.2.2 虚拟路由系统实战
路由模式
虚拟路由系统分为四种模式:search、native、native-scope、pure。search是默认模式,一般不需要特意设置,search模式下子应用的路由信息会做为query参数同步到浏览器位置上,如下。
倘若是设置单个子应用,如下所示。 <micro-app name=xx url=xx router-mode=search></micro-app>倘若需要全局设置,如下所示。 import microApp from @micro-zoe/micro-app
microApp.start({
router-mode: search,
})native模式下子应用完全基于浏览器路由系统进行渲染,比search模式持有更加简洁优雅的的浏览器位置,但相应的需要更加繁杂的路由配置。 倘若是设置单个子应用,如下所示。
<micro-app name=xx url=xx router-mode=native></micro-app>全局设置参考如下: import microApp from @micro-zoe/micro-app
microApp.start({
router-mode: native,
})native-scope模式的功能和用法和native模式同样,独一区别点在于native-scope模式下子应用的域名指向自己而非主应用。 倘若是设置单个子应用,参考如下。
<micro-app name=xx url=xx router-mode=native-scope></micro-app>倘若是全局设置,参考如下。 import microApp from @micro-zoe/micro-app
microApp.start({
router-mode: native-scope,
})pure模式下子应用独立于浏览器进行渲染,即不会修改浏览器位置,亦不会受其影响,其表现和iframe类似。 倘若是设置单个子应用,参考如下。<micro-app name=xx url=xx router-mode=pure></micro-app>
倘若是全局设置,参考如下。 import microApp from @micro-zoe/micro-app
microApp.start({
router-mode: pure,
})配置项
有时候,咱们可能会遇到需要关闭虚拟路由的场景。实质上虚拟路由系统是没法关闭的,这儿的配置只是为了向下兼容旧版本,它的表现和native路由模式一致。
针对单个子应用来讲,只需要运用下面的代码就可。 <micro-app name=xx url=xx disable-memory-router></micro-app>而倘若需要全局设置,能够参考下面的代码。 import microApp from @micro-zoe/micro-app
// 在start中增多配置
microApp.start({
disable-memory-router: true, // 关闭虚拟路由
})默认状况下,子应用卸载后重新渲染,将和首次加载同样渲染子应用的首页。设置keep-router-state能够保存子应用路由状态,在卸载后重新渲染时将恢复卸载前的页面(页面中的状态不保存)。 倘若保存某个子应用的路由状态,参考如下。
<micro-app name=xx url=xx keep-router-state></micro-app>倘若需要保存所有子应用的路由状态,参考如下。 import microApp from @micro-zoe/micro-app
// 在start中增多配置
microApp.start({
keep-router-state: true, // 保存路由状态
})重视: 倘若关闭了虚拟路由系统,keep-router-state亦将失效。当设置了default-page时keep-router-state将失效,由于它的优先级少于default-page。
3.3 样式隔离
MicroApp最初是基于style元素的CSSStyleSheet实现的样式隔离:即将CSS字符串插进style元素生成CSSStyleSheet,遍历每一个CSS规则,添加前缀实现样式隔离。
这种一种取巧的方式,利用浏览器自己的能力格式化CSS,并这里基本上进行修改,省去非常多工作量。但问题亦出此刻这儿,区别浏览器针对相同的CSS生成的CSSStyleSheet可能会区别,这就引起咱们在处理CSSStyleSheet会遇到不能够预知的问题,引起CSS表现不一致。
于是MicroApp换了一种方式来实现样式隔离,咱们运用正则将CSS字符串切割成最小单元,每一个单元包括一段CSS信息,将所有的信息整理生成CSSTree,遍历CSSTree的每一个规则,添加前缀实现样式隔离。
3.3.1 样式隔离
MicroApp的样式隔离是默认开启的,开启后会以标签做为样式功效域,利用标签的name属性为每一个样式添加前缀,将子应用的样式影响禁锢在当前标签区域。 .test {
color: red;
}
/* 转换为 */
micro-app[name=xxx] .test {
color: red;
}但主应用的样式依然会对子应用产生影响,倘若出现样式污染,举荐经过约定前缀或CSS Modules方式处理。
3.3.2 禁用样式隔离
禁用样式隔离分四个层次:
倘若是在所有应用中禁用,能够经过start办法进行全局配置,设置后所有应用的样式隔离都会停止。 import microApp from @micro-zoe/micro-app
microApp.start({
disableScopecss: true, // 默认值false
})倘若期盼在某个应用中不受全局配置掌控,能够设置disableScopecss=false。 <micro-app name=xx url=xx disableScopecss=false></micro-app>倘若在某一个应用中禁用,当前应用的所有css都不会进行样式隔离。 <micro-app name=xx url=xx disableScopecss 或 disable-scopecss></micro-app>倘若想要在某一个文件中禁用,能够在你的css文件中运用以下格式的注释来禁用样式隔离。 /*! scopecss-disable */
.test1 {
color: red;
}
/*! scopecss-enable */当然,亦能够对指定的选取器禁用样式隔离。 /*! scopecss-disable .test1, .test2 */
.test1 {
color: red;
}
.test2 {
color: yellow;
}
.test3 {
color: green;
}
/*! scopecss-enable */倘若想在全部文件范围内禁用样式隔离,将 /*! scopecss-disable */ 注释放在文件顶部。 /*! scopecss-disable */
...倘若需要在某一行中禁用,在文件中运用以下格式的注释在某一特定的行上禁用样式隔离,如下所示。 /*! scopecss-disable-next-line */
.test1 {
color: red;
}
.test2 {
/*! scopecss-disable-next-line */
bac公斤round: url(/test.png);
}3.3.3 shadowDOM
shadowDOM拥有更好的隔离性,但有些框架(如React)对shadowDOM的兼容性欠好,请小心运用。开启shadowDOM后,默认的样式隔离将失效。
4、Micro-App-DevTools
Micro-App-DevTools 是基于 MicroApp 推出的一款Chrome浏览器插件,目的是为了在研发和运用 MicroApp 过程中提有效率。经过此插件能够有效的处理调试困难、模拟数据通信、查看视窗范围、设置路由、获取环境变量等诉求,从而更好地帮忙用户去认识和运用 MicroApp。
Micro-App-DevTools经过模拟子应用研发环境,获取父应用数据,来可视化查看通讯数据,加强研发调试效率。针对路由,将会表示所有应用的路由,包括层层嵌套应用以及一个父应用多个子应用的路由,使区别团队应用亦能快速定位自己问题,方便协作。还供给了全局变量和高亮视窗功能,实现快速定位范围,加强排查效率的功能,并集结了图标、右键、掌控台的快捷进入方式,运用户快速上手,零成本运用。
参考链接:
MicroApp Github位置: https://github.com/micro-zoe/micro-app
Micro-App-DevTools Github位置: https://github.com/micro-zoe/micro-app-chrome-plugin
MicroApp官网位置: https://micro-zoe.github.io/micro-app
|