文章目录
网易严选企业级微前端解决方案与落地实践
网易微前端的建设背景
-
1.技术栈的迭代与升级
-
2.巨石应用的维护困难
-
3.新的前端复用模式探索,各系统之间有很多功能需要复用
即使通过npm包来管理模块,但是业务模块并不像基础组件一样稳定,需求迭代频繁、模块本身过大会导致bug多需要频繁修改 -
4.跨多团队合作开发困难
建设要点分析
微前端其实是一个完整的技术应用框架体系。
- 应用开发链路闭环
- 主框架的关键技术点
主流的微应用架构:MPA+路由分发;类Single-SPA;基座式SPA,主从应用设计;传统SPA+组件化+私有npm源
网易严选的微前端方案,是基于类Single-SPA的思想
-
主应用是微前端框架的承载体,主要包含:
- 页面主体框架的渲染,比如一些通用的导航
- 监听捕获全局的路由变化,加载/卸载子应用,active标签等
- 应用隔离、应用通信、数据共享等全局方法的载体
-
子应用在被主应用启动后,会接管系统路由,与一个独立运行的应用没有本质区别
-
在获取子应用的配置信息时,可以按照约定的path规则。
应用隔离
一个子应用从加载到运行,再到卸载,有可能会对全局产生一些污染。这些污染包括但不限于:添加 / 删除 / 修改全局变量(比如:window.$ = jQuery)、绑定全局事件(比如:window.addEventListener(‘popstate’,cb) )、修改原生方法或对象(比如:Promise)、修改原生方法或对象的原型链(比如:XMLHttpRequest.prototype.open)。而所有这些子应用造成的影响都可能引起潜在的全局冲突。为此,我们需要在加载和卸载一个应用的同时,尽可能消除这种影响。
①硬隔离
简单来说,就是在每个子应用加载之前,都进行一次 window reload,这样我们可以保证每个子应用在渲染时都是一个全新的环境,哪怕是上一个子应用把 window 上的属性改了个遍,也丝毫没有影响。
window reload页面刷新带来的体验问题:
- 前端snapshot + resume,快速恢复应用界面
- 主应用使用SSR局部直出,是页面在视觉效果上无刷新
②软隔离
简单来说,就是在应用加载之前做一次全局快照,在应用卸载之后,按快照恢复全局属性。考虑到主应用和子应用会同时运行在 Window 中,所以,我们必须区分哪些修改是由子应用引起而需要恢复的。为此,我们创建了一个 sandbox。在子应用加载前后,我们需要做这些事。
- 记住对全局变量的修改,接触应用时恢复原有值
- 记住全局事件的修改,比如window/document.addEventListener,卸载应用时remove事件;
- 记住setTimeout和setInterval的修改,卸载应用时解除
- sandbox并不能监听到对全局方法(对象)和他们的原型链的修改,因此还需要在加载子应用前创建一份window snapshot,卸载后按snapshot恢复全局方法(对象)和它们的原型链。
CSS隔离
子应用与子应用之间的 css 隔离非常简单,我们只需要在子应用加载时,标记该子应用所有的 link 和 style 文件。在子应用卸载后,同步卸载所有的 link 和 style 即可。
主应用和子应用的隔离相对没有那么麻烦,因为主应用的功能是可收敛的,需要包含的功能基本可预见,在相对可控的情况下,隔离起来并没有那么麻烦。(子应用与主应用不同,你不能约束一个子应用会用什么第三方包,使用什么样的框架,乃至于使用一些 hack 的方法。)
JS隔离
基于webpack模块化的打包方式,应用之间天然就可以避免大多数的全局冲突。余下的一小部分可以通过约束业务代码开发规范的形式,避免产品全局冲突和污染,规范包括但不限于:尽量不挂载会引起副作用的全局变量、建立模块池,收敛不可控第三方包等等。
CSS隔离
当主应用与子应用同屏渲染时,要彻底隔离CSS污染,当前有两种方法 iframe 和shadow dom,都各有不足,因此,对于全局共享的基础样式,并不能做到绝对隔离,对于具体业务代码的样式,可采用CSS Module或者命名空间的方式,给每个业务模块以特定的前缀,即可保证不会互相干扰。
配置中心等相关配套设施
配置中心是组成微前端应用架构体系不可或缺的一部分。
需要在上面维护应用的基本信息、应用关联信息、应用代理层配置、应用访问权限控制等。
如果说主框架让我们从技术上实现了微前端,那么 相关配套设施则是在具体的业务场景中落地的点睛之笔。
实际价值:
- 巨石应用化整为零
- 模块复用能力的提升
- 工单开发模式的革新
- 多团队合作模式的优化