如何接"地气"的接入微前端
前言
微前端,这个概念已经在国内不止一次的登上各大热门话题,它所解决的问题也很明显,这几个微前端所提到的痛点在我们团队所维护的项目中也是非常凸显。
但我始终认为,一个新的技术、浪潮,每每被讨论最热门的一定是他背后所代表的杰出思考。
“微前端就是…xx 框架,xx 技术”
这种话就有点把这种杰出的思路说的局限了,我只能认为他是外行人,来蹭这个词的热度。
在我所负责的项目和团队中,已经有非常大的存量技术栈和页面已经在线上运行,任何迭代升级都必须要保证小心翼翼,万无一失。
可以说,从一定程度来讲,微前端所带来的这些好处是从用户体验和技术维护方面的,对业务的价值并不能量化体现,落地这项技术秉着既要也要还要的指导方针。
我们对存量技术栈一定需要保持敬畏,隔离,影响范围可控的几个基本要素,然后再考虑落地实施微前端方案。
所以,在这个基本要素和指导方针下。要落地这项新的技术时,一定充分充分了解,当前改造站点所存在的技术方案、占比 以及 当前成熟微前端框架已提供的能力差异,切勿生搬硬套。
背景
我所在团队维护的项目都是些 PC 操作后台(Workstation),这些工作台会存在不同的国家,不同时区,不同合作方等等问题。
如果需要开发一个新的页面需求,很可能投入进来的开发人员都来自不同团队,此时我们要在完成现有需求的同时还需要保证多个管理页面的风格统一,设计规范统一,组件统一,交互行为统一这非常困难。
当该业务需要迁移到另外一个工作台时,虽然需要保持逻辑一致,但导航栏、主题等却不同。
当前存量的方案都是采用 Java 直接进行 Template 渲染出 HTML,经过前面几代前辈的迭代,不同系统中已经存在几种不同技术栈产出的页面。
虽然都是 React 来实现的,但是前辈们都非常能折腾,没有一个是按照常规 React 组件形式开发出来的。
比如:
大部分页面是通过一份 JSON 配置,消费组件生成的页面。
部分页面是通过另外一个团队定义的 JSON 配置消费组件生成的,与上面 JSON 完全不一样。
还有一部分页面,是通过一套页面发布平台提供的 JS Bundle 加载出来的。
面对这样的技术背景下,除了微笑的喊 MMP,含泪说着自己听不懂的话(存在即合理,不难要你干吗?),还得接地气出这样一个落地方案。
方案 & 流程图
首先,需要明确的分析出站点所有页面,所需要加载的通用特性:
上述是精简过后的一些通用功能特性,这里简单做下介绍:
Layout Loader 用于加载不同工作台的导航
DADA Loader 用于加载 JSON 配置的页面
Source Code Loader 用于加载 JS Bundle
Micro Loader 用于处理微前端加载
Log Report 用于日志埋点
Time Zone 用于切换时区
i18n 用于切换多语言
Guider 用于统一管控用户引导
除此以外可能还会存在以下这些页面扩展能力:
安全监控
流量管控
弹窗管控
问卷调查
答疑机器人
粗略统一归类后来看,页面的大体加载流程应该是这样:
实现细则
基于上述一个加载思路,首先需要做的是页面加载路径收口,需要保证所有页面的加载入口是在一个统一的 Loader 下,然后才可以较为系统的处理所有页面的加载生命周期。
在收敛的同时,同样需要保持开放,对核心加载路径要保持插件化开放,随时支持不同的扩展能力,渲染技术栈接入。
插件机制
所以,在主路径上,通过 Loader 加载配置进行处理,这份配置在主路径中提供上下文,然后交由插件进行消费,如图所示:
举个例子,拿一个独立的 JS Bundle 类型的子应用来说:
<div id="root"></div>
<script src="https://cdn.address/schema-resolver/index.js"></script>
<script src="https://cdn.address/schema-resolver/plugin/layout.js"></script>
<script src="https://cdn.address/schema-resolver/plugin/source-code.js"></script>
<script src="https://cdn.address/schema-resolver/plugin/micro-loader.js"></script>
<script src="https://cdn.address/schema-resolver/plugin/i18n.js"></script>
<script>
SchemaResolver.render(
{
micro: true,
host: "dev.address",
hfType: "layout1",
externals: ["//{HOST}/theme1/index.css"],
// host is cdn prefix, the resource maybe in different env & country
resource: {
js: "/index.js",
css: "/index.css",
},
},
{ container: document.querySelector("#root") }
);
</script>
通过上述的 Plugin 引入,即可开启和消费不同的配置。
这里引入了 Layout Plugin,该插件会消费 hfType
字段然后去加载对于的 Layout 资源提供 Container 交给下一个环节。
按照配置,当前页面开启了微前端,那么 Micro Loader 将会消费提供下来的 Container,然后建立沙箱(这里基于 qiankun),再提供 Container 出来。
最后交由 SourceCode Plugin 进行 Bundle 加载运行和渲染。如果这里是另外一种渲染协议或者技术栈,则可以根据不同配置交由不同插件消费 Container。
这个过程中,每个环节的插件是不依赖的,可插拔的。
比如:
如果不加载 Layout Plugin
将不会消费 hfType
字段,也就不会将Layout插件逻辑注入到getContainer
方法中,那么将直接得到由最外层下穿的Container进行渲染,也就不会有菜单相关透出。
如果不加载 Micro Plugin
同样不会有微前端的逻辑注入,也就不会建立沙箱,那么页面渲染流程将会按照常规模式继续运行。
当前SchemaResolver已经支持的插件有以下几种,详情参考 SchemaResolver:
MicroLoader – Base on qiankun using this plug-in can make your content loaded through a micro application so that your content can use all the features of the Micro-Front-End.
DadaLoader – Use this plugin can make your app render content by Dada.
SourceCodeLoader – Use this plugin can load your js\css bundle to render content, our bundle standard is same as qiankun. You can quick start developing your own page through our toolkit lzd-toolkit-asc.
LayoutLoader – Use this plugin can make your page load layout(menu), you can use different
hfType
configuration to switch different layouts.i18n – Use this plugin can make your page have multi-lang.
schema.locale
will be the mapping of multilingual keys in MCMS. The plugin will inject and register the language automatically.APlus – Use this plugin can make your page have the feature of APlus .Statistics page interaction events, such as pv\uv. With DadaLoader you can even see every module data(click pv, exposed pv) in pages.
WalkThrough – Use this plugin can make your page have the feature of Walk Through. One-stop page features guide.
SchemaResolver的插件能力采用plugin-decorator,如要了解更多插件设计思路可以参考:为你的JavaScript库提供插件能力
SchemaResolver plugin feature is base on plugin-decorator. It’s very easy to develop a new plugin.
More information about plugin can read this article Provide plugin capabilities for your JavaScript library
安全迁移
对于我所在团队负责的项目来说,万万做不得一刀切的方案,所以针对现有存量页面,需要完整分析当前存量技术栈:
针对上述存量页面来说,需要从左到右分批进行页面级别控制上线部署,对于左侧部分页面甚至需要做些项目改造后才可部署接入上线。
这类迁移测试需要处理出一套 自动化e2e测试 流程,通过分批迁移同时梳理出 微前端注册表 。
有了这两项流程保证及范围控制,当前方案所上线内容完全可控,剩下要处理的大部分就是较为重复的体力活了,覆盖率也可量化。
微前端形态
按照上述方案迁移,那么预期的微前端形态将会是:
每个开启微前端的页面都可成为主应用
微前端是插件可选项,如果因为微前端导致的业务异常可随时关闭
同为微前端的页面路由相互之间切换可实现局部刷新形态,而跳转至非微前端注册表中的页面则会直接页面跳转。随着微前端页面覆盖率提高,局部刷新的覆盖率也会逐渐提高
可通过不同扩展插件,加载不同技术栈类型的存量页面,转换为对应子应用
在SchemaResolver中的注册和调用路径如下:
总结
透过技术看本质,微前端所代表的杰出思维,才是真正解决具体问题关键所在,只有解决了具体的业务问题,这项技术才有价值转换。
不要为了微前端做微前端,不要为了小程序做小程序。
当前,通过 SchemaResolver,可以针对不同角色提供不同的开放能力:
针对平台管理员,提供插件能力开放全局扩展能力
针对页面开发者,提供标准化接入方案路径,提供多种技术栈接入能力,并无感知提供微前端,多语言,埋点,菜单,主题加载等能力。解耦了不同系统公共能力,同时,这种方式可以让页面开发者快速将具体业务逻辑迁移到其他平台。
针对第三方接入者,不需要关心了解系统菜单、主题接入方式,提供统一的接入口径,通过微前端隔离技术栈、隔离子应用样式。最后通过统一的页面系统管控,轻松入住对应平台,同时可以全局看到站点页面情况。
作者:Yee Wang
来源:https://yeee.wang/posts/3469.html