桂林整站优化网站互动推广
桂林整站优化,网站互动推广,如何跟建网站的人员沟通,如何查询网站的注册信息Bifrost#xff08;英 [‘bi:frɔst]#xff09;原意彩虹桥#xff0c;北欧神话中是连通天地的一条通道。而在漫威电影《雷神》中#xff0c;Bifrost是神域——阿斯加德#xff08;Asgard#xff09;的出入口#xff0c;神域的人通过它自由穿梭于“九界”#xff08;指… Bifrost英 [‘bi:frɔst]原意彩虹桥北欧神话中是连通天地的一条通道。而在漫威电影《雷神》中Bifrost是神域——阿斯加德Asgard的出入口神域的人通过它自由穿梭于“九界”指九个平行的宇宙之间。借用“彩虹桥”的寓意我们希望Bifrost可以成为前端不同SPA(Single Page Application)系统之间的桥梁使得不同的单页应用可以用这种方式实现功能的自由聚合/拆分。 项目背景 立项之初闪购赋能企管平台以下简称“企管平台”仅仅是面向单个商家的CRM管理系统采用常规的Vue单页应用方式来实现。随着项目的推进它的定位逐渐发生了变化从一个单一业务的载体逐渐变成了面向多种场景的商家管理平台。另一方面由于系统由多个前端团队共同开发维护越来越多的问题随之浮现 异地协作时信息同步不及时引起的代码冲突以及修改公共组件引入的Bug。不同的商家针对同一个页面存在定制化的需求。已经实现的一些功能需要集成到企管平台中来。因此我们希望构建一个更高维度的解耦方案使我们能够在开发阶段把互不干涉的模块拆成一个个类似后端微服务架构那样的子系统各自迭代在运行时集成为一个能够覆盖上述各种使用场景的完整系统。 方案选型 首先我们整理了核心诉求按优先级排序如下 希望异地开发时不同的模块能够独立开发、独立部署。对已在线上运行的项目希望能够低成本地接入企管平台而不需要对开发、部署流程做大规模的改动。各个子系统独立运行互不影响但允许我们在开发阶段与其他子系统进行联调。保持单页应用的体验。由于现有项目都是基于Vue技术栈开发因此我们的框架并不需要做到技术栈无关只要满足Vue的项目即可。基于以上这些诉求我们调研了目前市面上常用的微前端方案最常见的方案有 基于Nginx的路由分发。使用Iframe将页面嵌入。除此之外还有美团集团内部的微前端实践——美团HR系统用微前端方式搭建类单页应用和业界比较知名的微前端框架——SingleSPA。 这些方案的优劣整理如下 从用户体验角度出发Nginx和Iframe首先被否决HR系统的方案需要对现有的项目进行改造把不同团队目前开发的项目整合到同一个单页应用中在项目快速迭代的过程中成本过高所以也被否掉。SingleSPA看起来完美但它没有照顾到实际生产环境中的开发、部署的差异性并不是Product-Ready。综合多种因素考虑我们最终决定采用自研的方式来实现微前端化Bifrost。 核心架构 Bifrost框架在设计的时候参考了SingleSPA的思路将系统了分为主系统和子系统。 主系统是用来控制子系统的调度中心职责包括 维护子系统的注册表。管理各个子系统的生命周期。传递路由信息。加载子项目的入口资源。为子系统的实例提供挂载点。子系统只负责业务逻辑的实现。如果进一步细分的话子系统可以分为业务子系统、实现公共菜单子系统、导航布局子系统其中布局子系统会先于业务子系统加载。 Bifrost采用路由消息分发的方式来控制子系统的加载和跳转。主系统维护了一条路由消息总线当路由发生变化时子系统会将路由事件推送给路由总线然后由路由总线决定加载/跳转的目标子系统。如果路由不需要切换子系统则交由当前子系统进行处理。 如果子系统发生切换主系统会在DOM中添加对应子系统的挂载节点并异步加载系统的静态资源。由于子系统都是完整的Vue实例当子系统的代码加载并执行之后子系统就会自动在其对应的挂载节点上渲染相应的内容。 整个系统的生命周期如下图所示 具体实现 基于Bifrost实现的项目架构如下图所示 这里我们主要关注主系统、业务子系统和布局子系统的实现。 主系统 主系统的逻辑比较简单主要是实例化Bifrost中定义的Platform对象并注册各个子系统。子系统的注册信息包括 AppName子系统名与系统的路由前缀保持对应同时也会作为子系统在DOM中挂载节点的ID。Domain非必填如果出现多个路由前缀都对应同一个子系统可以通过Domain进行映射。ConfigPath对应子系统配置文件的URL。一个简单的主系统实现如下 import { Platform } from sfe/bifrostnew Platform({layoutFrame: {render () {// render layout}},appRegister: [{ appName: app1, configPath: /path/to/app1/config.js }]
}).start()业务子系统 在设计方案时我们始终保持一个理念就是保证对业务代码的零侵入因此业务系统改造的工作量很小。代码层面只需要把原本子系统的初始化流程放到AppContainer对象的Mounted回调函数里即可 import { AppContainer } from sfe/bifrost
import Vue from vue
import VueRouter from vue-routerVue.use(VueRouter)
const router new VueRouter({})
new AppContainer({appName: app1,router,mounted () {return new Vue({router,components: { App },template: App/}).$mount()}
}).start()另外还需要修改子系统的构建流程构建完成之后生成一个包含子系统入口资源信息的配置文件。一个典型的配置文件如下 ((callback) callback({ scripts: [/js/chunk-vendors.dee65310.js,/js/home.b822227c.js],styles: [/css/chunk-vendors.e7f4dbac.css,/css/home.285dac42.css]
}))(configLoadedCb.crm)此处我们实现了sfe/bifrost-config-plugin插件在Webpack构建脚本中引入该插件就可以自动生成项目对应的配置文件。配置文件是一个立即执行函数主系统可以通过JSONP的方式读取配置文件中的内容。 在实际生产环境中我们可以将子系统发布到任意CDN只要能够保证配置文件的URL始终不变那么无需依赖任何服务主系统就可以感知到子系统的发布。 布局子系统 布局子系统是用来实现菜单和导航栏的Vue工程本质上和一般的业务子系统没有区别。只需要注意布局子系统使用的是LayoutContainer而非AppContainer进行包装。 import { LayoutContainer } from sfe/bifrost
import Vue from vueimport App from ./appnew LayoutContainer({appName: layout,router,onInit ({ appSlot, callback }) {Vue.config.productionTip falseconst app new Vue({el: #app,router,store,render: (h) (App appSlot{appSlot} /)})callback()}
}).start()布局子系统作为主系统的一部分既可以放在主系统中去实现也可以像其他子系统一样通过异步的方式去加载。在我们的项目中结合了上面两种方式布局子系统既可以为作为常规的Vue项目构建也可以发布成NPM包每次发布时会同时发布布局的静态资源和NPM包。主系统通过NPM包的方式引入布局子系统将它打包到项目中避免线上运行时额外加载布局子系统的资源减小项目体积加快渲染速度。 本地开发时我们则会通过Bifrost定义的MockPlatform异步加载布局子系统的静态资源保证线上/线下运行效果的一致性方便本地联调。 工程实践 代码层面的改动虽然不多但要在实际的生产环境中落地还需要解决一系列老生常谈的问题包括 本地开发时如何保证与线上实际运行效果的一致性如何实现全局状态管理和子系统之间的通信如何对公共依赖和公共模块进行管理发布部署流程需要怎样调整根据闪购业务实践我们总结了一套适用于Bifrost的解决方案。 本地联调 采用微前端的方式意味着子系统的完全隔离这给我们的开发带来了一系列困扰 本地开发时无法看到当前开发的功能在主系统中实际运行的效果。子系统之间有时会存在跳转关系在开发阶段难以验证这种跳转逻辑的正确性。为了解决这些问题Bifrost定义了MockPlatform。MockPlatform的思路很简单既然主系统可以动态加载线上的子系统那么我们只需要在开发时模拟主系统的运行方式去加载其他子系统的线上资源之后就可以像调用后端API一样同各个子系统进行联调了。这也就解释了为什么布局子系统在输出NPM包的同时还维护了一份静态资源。 MockPlatform的API同Platform对象的API是一致的开发时我们只需要按照主系统的方式引用布局或业务子系统的配置文件URL即可 // ...others...new AppContainer({// ...others...runDevPlatform: process.env.NODE_ENV development, // 只在开发环境下启动mock platformdevPlatformConfig: {layoutFrame: {mode: remote,configPath: path/to/layout/config.js},appRegister: [{appName: app2,mode: remote,configPath: path/to/app2/config.js}]},// ...others...
}).start()借助MockPlatform我们项目在开发阶段的感受和开发普通的单页应用没有任何差异如果某个我们依赖的子系统更新了功能只需要让对应的RD发布一下就可以在本地看到它的最新效果。 全局状态 除了本地联调全局通信也是微前端项目中绕不开的一个话题。由于我们所有项目采用的都是Vue技术栈所以会选择基于Vuex来实现全局通信。Bifrost的主系统会维护一个全局的Vuex Store用于保存全局状态。 当子系统希望监听全局状态时子系统并不是直接订阅全局StoreVue的依赖收集机制也决定了子系统无法响应全局Store的变化而是借助Bifrost提供的syncGlobalStore函数来订阅全局Store。调用该函数后任何全局状态的变化都会被同步到本地Store的Global命名空间下。之后就可以像普通的单页应用那样调用Vuex的mapState方法实现和全局状态的双向绑定。 import { AppContainer, syncGlobalStore } from sfe/bifrost
import Vue from vue
import Vuex from vuex
// ...others...
Vue.use(Vuex)
const store new Vuex.Store({})
new AppContainer({mounted () {// 同步全局store状态syncGlobalStore(store)// ...others...return new Vue({store,router,components: { App },template: App/}).$mount()}
}).start()如果子系统自身的状态需要共享Bifrost还会提供installGlobalModule函数。该函数会将当前子系统需要共享的状态挂载到全局Store下其他子系统可以通过前面提到的方式来同步这些状态。虽然Bifrost提供了子系统通信的能力但在实际拆分子系统时应该尽量避免这种情况发生。如果两个子系统之间需要频繁通信那就应该考虑把他们划分到同一个子系统。 公共依赖 由于各个子系统都需要集成到企管平台为了保证体验的一致性大家都是基于同样的组件库进行开发。几乎所有项目都会依赖lodash、Moment等基础库因此如果不对公共依赖进行管理项目会加载大量冗余代码。 针对这个问题我们采用的是Webpack External方式来解决。构建时各个子系统会将公共依赖排除主系统会打包一份包含所有这些公共依赖的DLL文件。子系统在运行时直接从全局引用对应的依赖。如果子系统希望使用某些库的特定版本也可以选择不排除这些依赖项。这在子系统希望升级某些依赖库的时候显得极为有用通过子系统的局部升级可以限制依赖库升级的影响范围避免造成全局影响。 DLL文件会包含大部分公共依赖但有一个例外——我们不会将Vue打到DLL文件中。因为在实际开发中很多库都喜欢向Vue的原型链上挂载方法和属性。如果不同团队开发时挂载的内容恰好用到同一个字段就会带来不可预知的影响。 模块复用 除了底层的依赖我们还需要考虑对公共的业务模块和工具函数进行复用。在企管平台我们为公共业务组件库和公共函数库创建独立的Git工程然后将所有的子系统和公共模块通过Git Submodule的方式引入到主系统的工程中。主系统采用Lerna的方式组织代码各个子系统在开发时可以通过软链直接引用到本地公共模块的代码实现公共模块的复用。当公共模块发生更新直接调用Lerna Publish就可以同时更新所有子系统package.json中依赖版本。 发布及部署流程 前面提到主系统采用的是JSONP方式加载子系统的配置文件整个发布过程都只需要发布静态资源因此Talos美团内部自研的持续集成平台提供的前端静态资源发布的能力就可以满足我们的需求。每次发布时只需要构建有更新的项目并将打包后的静态资源上传到CDN即可。 版本控制 采用微前端架构还有一个额外的好处在Nginx和实际的业务层之间多了一层主系统我们可以像客户端一样动态决定需要加载的子系统版本。基于此我们实现了子系统的版本控制和定向灰度功能。发布时我们通过参数确定本次发布是否是灰度版本。在发布成功后会记录本次发布的灰度信息、版本和配置文件URL等信息。 主系统每次启动时首先会调用接口确定当前用户所处的链路全量/灰度再根据链路信息加载相应的子系统。我们记录了每次发布的资源URL所以也支持子系统的版本切换。只需要在版本服务中修改各条链路上需要激活的子系统版本就可以轻松实现子系统版本切换。 埋点及错误上报 这里我们主要讨论Bifrost框架的埋点方案。在Bifrost项目中可以借助主系统提供的一系列钩子函数实现针对子系统的埋点包括onAppLoading、onAppLoaded、onAppRouting、onError。每当子系统发生切换都会调用onAppRouting函数因此我们可以在这里记录子系统加载的次数PV。onAppLoading和onAppLoaded则会在子系统初次加载时调用通过计算Loading和Loaded成功率的比值我们可以得到子系统加载的成功率。子系统加载失败时会调用onError函数帮助排查子系统加载失败的原因。 收益 今年年初我们对企管平台进行了微前端改造目前系统已经在线上平稳运行半年时间支持上百个零售商品牌上千家门店业务的运转。 采用微前端架构给我们项目带来的好处是显而易见的 实现了异地合作开发时的完全解藕。采用微前端架构之后两地团队在开发过程中再也没有遇到代码冲突的问题。避免了单页应用发展成“巨石”应用。目前企管平台总共实现了上百个页面采用微前端的方式进行划分后每个子系统包含的页面都不超过三十个子系统的可维护性得到大大提高。今年企管平台经历了两次大的组件库版本升级。第一次升级时项目还是单页应用我们在暂停业务开发的基础上耗费了大约一周的时间对所有的页面进行回归验证、完成升级。第二次升级时我们已经完成了项目的微前端改造可以通过增量的方式先升级不常用的子系统验证通过后再升级其他子系统。这样既不用中断正常的业务开发也保证了依赖库升级时的影响范围和风险可控。不是“银弹” 当然同所有的架构方案一样微前端这种模式也存在一些折衷和妥协。在获得低耦合和灵活性的同时也引入了额外的复杂度。在微前端项目中我们需要考虑多个工程的规范和代码质量的统一需要引入更多的自动化工具来管理项目的发布部署流程还需要处理多个前端工程运行在同一个域名下引起的Cookie覆盖等问题。 因此在采用微前端架构之前建议大家要谨慎的评估自己的项目是否真的适合采用微前端的方式避免盲目引入微前端导致项目难以维护得不偿失。 我们认为如果项目中存在以下两个场景比较适合采用微前端架构 功能模块较多且各个功能模块相对较为独立的中后台系统。项目存在大量历史遗留问题希望在保留已有功能的基础上开发新的功能模块。其他大部分项目都可以通过调整代码结构构建单页应用甚至采用最传统的多页应用等方式来进行优化、调整从来达到降低耦合的目的。微前端并不是“银弹”。 期许 从去年12月立项至今Bifrost经历了近一年的迭代发布了2个大版本和38个小版本。诞生之初Bifrost仅仅是针对企管平台这个特定业务场景的微前端方案。如今已进化为面向Vue技术栈的通用微前端框架。期间我们围绕Bifrost逐步完善了整个微前端技术体系的建设实现了Bifrost主/子系统的脚手架工程和命令行工具、子系统的管理平台、灰度发布功能等一系列平台和工具完成了Bifrost微前端生态的雏形。 当然Bifrost依然还有很多可以提升的地方。未来我们将会从以下几个方面进一步完善Bifrost 提供更加完善的前端微服务治理工具。实现JS和CSS沙盒。支持更多的技术栈。结语 随着前端工程的日益复杂我们对可扩展的前端架构的诉求也变得更加强烈。微前端作为一种前端解藕的方案自然更加频繁地被大家所提及和应用。另一方面虽然网上已经有了很多关于微前端的讨论但依然缺乏真正落地到生产环境的案例。因此我们希望通过对闪购团队近半年在微前端方案上的实践分享帮助大家对微前端从概念到应用有一个更加清晰的认识也期待与大家一起交流碰撞出更多的火花。 作者简介 雨甫美团闪购前端研发工程师。 招聘 美团闪购是美团点评旗下的零售到家业务闪购专注于为消费者提供丰富、便捷的零售品类选择和及时配送服务为零售商家提供线上、线下的整体解决方案助力商家提升经营效率。 用户通过手机下单即可快速买到周边各类商家提供的丰富商品涵盖食材生鲜、超市便利、鲜花绿植、母婴用品和健康护理等众多品类。美团闪购与美团外卖共享配送网络平均30分钟配送上门24小时无间断配送打造全品类一站式零售到家平台。 美团闪购前端团队诚招高级前端开发、前端开发专家。欢迎各位大佬的加入共同打造极致的LBS电商体验。感兴趣同学可投递简历至techmeituan.com邮件标题注明美团闪购前端团队
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/90456.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!