一、什么是微前端
微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个完整的应用,或者将原本运行已久、没有关联的几个应用融合为一个应用。微前端既可以将多个项目融合为一,又可以减少项目之间的耦合,提升项目扩展性,相比一整块的前端仓库,微前端架构下的前端仓库倾向于更小更灵活
-
它主要解决了两个问题:
-
随着项目迭代应用越来越庞大,难以维护。
-
跨团队或跨部门协作开发项目导致效率低下的问题
二、 关于 micro-app 原理
静态资源请求
/**
* fetch source of html, js, css
* @param url source path
* @param appName app name
* @param config fetch options
*/
export function fetchSource (url: string, appName: string | null = null, options = {}): Promise<string> {
/**
* When child navigate to new async page, click event will scope dom to child and then fetch new source
* this may cause error when fetch rewrite by baseApp
* e.g.
* baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
*/
removeDomScope()
if (isFunction(microApp.options.fetch)) {
return microApp.options.fetch(url, options, appName)
}
// Don’t use globalEnv.rawWindow.fetch, will cause sgm-2.8.0.js throw error in nest app
return window.fetch(url, options).then((res: Response) => {
return res.text()
})
}
-
定义自定义元素
-
micro-app 使用 window.customElements.define 自定义元素。可参考
-
shadow DOM 原始的隔离方式,Shadow DOM 内部的元素始终不会影响到它外部的元素(除了 :focus-within),这为封装提供了便利。可参考
-
micro-app 中默认是关闭 shadow DOM 配置的,即并这里没有做到物理上的隔离
-
shadowDOM具有更好的隔离性,但一些框架(如React)对shadowDOM的兼容性不好,请谨慎使用。
-
开启shadowDOM后,默认的样式隔离将失效。
CSS 样式隔离
-
样式隔离采用添加样式前缀的方式,但是依然会存在问题,例如
-
position:fixed 原理上的定位问题
-
modal 类组件,插入到 body 元素中,导致子应用样式匹配不中
-
样式系统本质上统一的,基座应用的样式会在全局的作用域下生效
JS 沙箱隔离
-
全局基本类型变量,采用 proxy, 子应用的 window 对象实际上是 proxyWindow 对象,访问的时候采用 with 语法改变其作用域。即访问属性时先在proxyWindow上获取,如果找不到在从 window 上查找
-
全局引用类型变量引用还是一致的,基本是重写了指定的方法劫持,例如 document.body.appendChind 等,但是JS沙箱隔离是不完全的。沙箱问题
-
vite esmodule 不支持沙箱
micro-app 原理介绍
三、微前端的其他方案
微前端如何落地 可参考
四、改造项目中所遇到的问题
1、路由一致性问题,基座应用和子应用拥有不同的 router 对象,但是底层依赖浏览器的原理是一致的(pushStatus 等),所以需要注意路由的一致性问题,可替代这部分的通信障碍处理
2、各个子应用样式框架不统一的问题,原则上尽量统一,减少多余的样式引入
3、框架存在的问题,导致不可预料的其他问题