这里只是列举一些我在工作中使用到的一些应用集成方案,可能不成体系,希望能帮助到正在阅读的你,欢迎一起交流探讨;
地址跳转
这算是最早的方式了吧,直接跳转到另一个应用,好处就是快速、几乎零成本、问题也是最少的;缺点也很明显,体验比较差;
script
直接在html中插入第三方的资源文件,这算是最早的集成方式了,目前一些sdk还在使用这种方式,比如微信的js sdk、iconfont这些不经常变化的东西。
不过在经常变化的业务中,为了解决缓存问题,都会生一个hash文件名,这就导致每次业务方发布后都需要替换html中的文件名字,特备经过如webpack等打包工具的chunk之后,这种方式就更不适用了。
适合不常变的基础库的使用;
多变的业务下版本更新是很大的问题,特别是当项目数量到达一定数量之后;
不能按需引入;
共有一个window对象
npm
这种方式大家都比较熟悉,应该也是大家使用最多的方式,各种公共组件、业务组件、物料库都采用这种方式,有点规模的公司一般都会搭建私有npm库来管理公司的npm包;
这种方式在一些基础库中使用起来还是很方便的,比如react、vue。
但是在多变的业务模块中也存在更新和版本管理问题,因为每次业务变化发布包之后,当应用比较少的时候不怎么明显,当工程项目到几十个上百个,出现跨部分沟通时,需要通知很多人跟着你一起发布;
当然你也可以另辟蹊径,npm只提供一个”壳“,一个加载资源的方法,真正的资源加载是npm包内部自己实现的,这样只要不是特别大的改动,比如资源地址域名发生变化,就不需要升级这个npm包。
这个中方式也面临着script方式问题,只能说一定程度上做了些优化;
适合不常变的基础库的使用;
多变的业务下版本更新是很大的问题,特别是当项目数量到达一定数量之后;
按需引入:需要第三方模块提供了es module的代码;
**共有一个window对象
**
iframe
我感觉这个最大的不同就是沙盒隔离,虽然这个沙盒也是在顶层沙盒内部;这种方式需要集成一个能完全独立运行的应用。
iframe在早期是大家不屑使用的,可能是太占内存了吧,毕竟一个iframe就相当于打开了一个浏览器标签,在早期设备性能比较差的情况下运行起来比较吃力。
而且在交互体验上也不是那么好,比如iframe内的一个遮罩弹框,只能遮住ifram自己的区域,不能遮住父应用部分;
可能大家还会说父子应用的通讯也是个问题,其实这反而比较好解决,而且方式上也和npm这种形式差不多。无论是使用postmessage还是自己写一套简单的消息订阅方法都能很方便的解决这个问题。为什么说和npm这种形式差不多了,以为本质上都是注册事件触发事件的过程,只不过一个是传方法内部触发、一个是通过消息触发;
这种方式其实在我们的一些应用中也是深度使用的,在现在普通用户设备商运行良好,优点是集成效率高,父应用环境对子应用的影响很小,几乎不用考虑环境问题;
我们还通过iframe单例模式来解决ifram切换是加载的性能问题,特备在现在的SPA模式下,几乎能做到和父应用模块切换无缝衔接,完全看不出来哪些是iframe,还通过预加载iframe来解决第一次加载ifram的性能问;
当然也存在一些问题,因为iframe集成的应用本身是一个完整的应用,所以在集成式需要做一些特殊处理,比如隐藏菜单和导航,因为父应用已经有菜单和导航了;
另外我们还在移动端做了一些尝试,只要处理好”返回“一些操作,理论上可以实现类似支付宝、微信等这种”小程序“的效果;父应用作为一个平台,通过iframe打开各种第三方应用;
完全的沙盒隔离,不需要考虑父应用环境对子应用的影响;
子应用要是一个完整的独立应用;
交互体验上存在一些问题,比如弹框位置、遮罩;
hahsjs(动态加载资源)
上面提到过npm包一层”壳“的形式,其实就是这种模式,这是在ModuleFederation、乾坤、EMP出现之前我们采用的主要模式;这种模式也不是什么新的技术,相信在一些大型互联网公司早就使用过了;
这种模式的核心是有一个”资源列表“,这个资源列表就是要在家的资源,然后再动态加载这些资源列表;
当然也存在一些问题,比如资源列表文件不能被缓存;版本管理问题;
解决了更新问题,这里可以不做版本控制,始终是最新的资源,这样子应用发布后,所有的集成方都是最新的了;
依赖问题,如果存在依赖关系,动态加载资源需要同步加载资源,这个就增加了耗时;
按需加载做起来不是那么方便;
ModuleFederation
webpack5增加的新特性,具体可以参考官方文档
我们在应用也已经使用改模式,可能会从hash模式先逐渐切换到该模式,该模式比hash模式的好处是可以分模块导出和导入,不需要人工切分模块;
该模式我还没有深入使用过暂时不做过讨论哈,可以自行查阅官方文档;
qiankun(乾坤)、EMP
这是一整套的微服务应用框架,qiankun我们有使用过一个工程,quankun的策略也是”沙盒“,qiankun重写整个window对象,qiankun为每个子应用分配了自己重写的window对象,所以又不是完全的沙盒化。我们使用过程中也遇到了一些问题,满足不了我们的业务场景,所以后面也就放弃了这条路;
EMP我们没有使用过,所以大家自行查阅资料哈;
RDECO
我们目前自研的一套涵盖微服务模式的一套框架体系,虽然核心代码是开源的,但是与之相对的还有一整套”前端研发平台“,所以单从rdeco这个库本身可能感触不大,感兴趣的可以看下github.com/kinop112365…
总结
上面几种方式其实核心思路有很多相似性:
script、hashjs、moduleFederation、quankun、(EMP不确定、rdeco都属于动态加载的方式来集成带三方应用;
iframe、qiankun采用沙盒模式来隔离环境造成的影响;
moduleFederation、rdeco提供了更好友好方式来动态加载资源;
浏览器的特性限制了前端不可能像服务端微服务那样,每个服务真的是”独立“的,前端始终在同一个浏览器窗口中,使用共用一个window对象这是不可避免的,这也给很多集成方式带来了各种各样的问题,比如:css对全局的影响,全局对象的污染;
样式问题现在也有一些结局方案,比如cssmodule、css in js,都是不错的方案。不过没个工程都存在一堆”历史“代码,在业务架构治理引进新技术不能带来新的问题,又能和”历史“代码有好的结合才是最让人头疼的问题;
依赖:也是一个比较让人痛疼的问题,要说webpack比ground、rollup有啥不一样,依赖相信可以拿出来说说了。想上面的hash、moduleFederation就存在这个问题,无法有效管理依赖,只能人肉,当项目多了之后就”一团乱了“。我们在探索rdeco时候是想着通过类似服务端这种线上注册的模式,在向上统一管理依赖,每个服务都有唯一id,这个id需要线上申请,这只是一个初步设想,也是我们想实现”信息化“的一部分;