微前端思考与总结
点击上方蓝字关注我们
微前端是最近一年以来前端领域非常火的一个概念,同时阿里集团内也衍生了很多相关的技术产品。这篇文章是考拉运营中台组最近调研微前端的一些尝试和思考
微前端介绍
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略 https://micro-frontends.org
微前端工程价值
独立开发、独立部署;
框架无关;
跨业务域复用;
方便功能扩展、升级;
便于多人协作开发;
如果微前端只存在工程上的价值是不值得大张旗鼓去做的
微前端业务价值
业务原子化输出;
业务编排整合;
应用场景
巨石应用的拆分-pop partner系统
业务编排整合-搭建&大促系统
微前端的优势可以有效的弥补当前运营中台遇到的一些痛点:
技术:考拉加入阿里之后有很多网易技术背景下的工程,特别是中台组这边 angular 和 vue 框架实现的代码,甚至还有前后端不分离的 java+angular 的老工程,这些工程开发效率慢,开发体验差,没有成就感
运营:运营同事针对各种内部系统没有统一的调配入口,一次操作有可能需要在多个不同系统完成,操作效率底下
single-spa & qiankun
single-spa 是现在市场上比较成熟的技术方案,以及蚂蚁基于 single-spa 研发的 qiankun 框架
import * as singleSpa from 'single-spa';
singleSpa.registerApplication('app-1', () =>
import ('../app1/app1.js'), pathPrefix('/app1'));
singleSpa.registerApplication('app-2', () =>
import ('../app2/app2.js'), pathPrefix('/app2'));
singleSpa.start();
function pathPrefix(prefix) {
return function(location) {
return location.pathname.startsWith(`${prefix}`);
}
}
我们需要注册对应的 application,并且指定对应 application 的激活函数。同时 application 需要在入口文件导出相应的生命周期函数
export async function bootstrap(props) {...}
export async function mount(props) {...}
export async function unmount(props) {...}
如果简单来看的话,single-spa 就是在合适的时候执行我们传入的 loadFunctin, bootstarp, mount, unmount, unload 方法,并抛出了一些事件
qiankun 的启动调用方式和 single-spa 非常相似,但是在 single-spa 的基础上增加了一些功能
import-html-entry
js沙箱
更丰富的生命周期
prefetch
https://qiankun.umijs.org/zh/guide/getting-started.html#%E4%B8%BB%E5%BA%94%E7%94%A8
技术难点
1.应用隔离
js 沙箱实现
通过proxy代理window对象,监听对应的get set方法
在应用的 bootstrap 及 mount 两个生命周期开始之前分别给全局状态打下快照,然后当应用切出/卸载时,将状态回滚至 bootstrap 开始之前的阶段,确保应用对全局状态的污染全部清零。而当应用二次进入时则再恢复至 mount 前的状态的,从而确保应用在 remount 时拥有跟第一次 mount 时一致的全局上下文
对象,函数劫持
setInterval、setTimeout,addEventListener,removeEventListener,appendChild
单实例 多实例的场景
2.样式隔离
Shadow DOM
CSS Module? BEM
Dynamic Stylesheet
3.html-entry
获取html页面内容
解析成dom,script,style,entry入口文件
获取style的内容填充到html中
通过sandbox执行script代码
4.应用通信
initGloabalState,props
参考:https://zhuanlan.zhihu.com/p/78362028
https://zhuanlan.zhihu.com/p/107240132
大促系统改造方案:
主应用改造:
在大促系统的工程下新建了一个服务,单独用来做微服务的主应用工程
提供统一的吊顶服务
因为各个系统都维护了各自独立的登录体系,主应用暴露出login入口
自定义了fetch方法
css中相对路径替换
子应用改造:
静态文件,接口请求支持跨域 egg-cors
入口文件导出生命周期
dll output配置 library librarytarget
kapp/cas 去掉 loginSuccessUrl
mounted 增加login组件
接口请求 publicpath 配置
静态文件 __webpack_publicpath_ 配置
href 跳转替换,子应用互跳
独立的路由规则
隐藏侧边栏和顶栏
文件上传组件publicpath设置
regular nej改造
https://www.yuque.com/docs/share/95b0302c-dba6-44d0-9292-9b81d7415de7?#
https://www.yuque.com/docs/share/35788488-2bfc-406d-8627-aacd6a7e79e3?#
技术上的痛点:巨石应用,可维护性
代码量达到一定量的时候,单次构建时间很长,开发&发布效率极低
代码库中依赖升级会影响整个应用,而代码量又非常大,导致回归成本极高
变成一个非常臃肿的巨石应用,完全失去灵活性,无论是多人协作还是业务接入成本都会大大增加
业务上的场景:应用的拆分和编排
用户端必须是「一个系统」的心智,从域名到体验
能够根据功能拆分成多个子应用,每个子应用独立开发独立部署
子应用尽量保证跟传统单页面应用一样的开发体验,不要让开发者有太多学习成本
所有子应用可被统一管理起来,不能无限制的泛滥
微前端生态体系?
什么样的模式是最佳实践?
后续规划
考拉集团内部技术栈统一
统一的配置发布平台产品,提供快速的业务整合串联能力,帮助业务提效
账号登录统一收敛
微前端子应用接入方案
包含应用 组件库 方法主应用接入方式
本地的开发工具
其他:
webpack5 module federation
webcomponent
调试
登录模式不友好
报错:ResizeObserver loop limit exceeded
推荐阅读