前提
业务背景
业务中需要解决三大问题:
- 业务多迭代快,一个站点多业务并行开发
- 功能多投,同一个功能需要投放到不同站点
- 页面管控,访问每个页面需要展示loading、进行前置校验等
技术背景
- 微前端架构,站点由主子应用构成,各应用独立开发迭代
- singleSpa,只定义机制(基于路由,应用生命周期),不限定实现
- 主子应用协同,三级模型(主应用-子应用-页面),协同规范(应用配置、页面配置等的定义和应用)
- 扩展机制,支持针对页面生命周期添加钩子,定义业务行为
框架实现
实现的几个部分:
- 如何注册子应用?
- 如何发现子应用?
- 如何加载子应用?
- 如何渲染子应用?
- 子应用渲染时,如何添加其他逻辑?
注册子应用
根据三级模型和协同规范,注册子应用会分为三步,加载子应用配置、解析子应用配置和向singleSpa注册页面。
子应用配置包含子应用名称和页面列表信息等。
{
microAppName: 'web-crm-marketing',
pages: [
{
name: 'home',
route: '/home',
url: ['//g.alicdn.com/web-crm-marketing/1.0.0/home.js', '//g.alicdn.com/web-crm-marketing/1.0.0/home.css']
}
]
}
加载子应用配置
通过registerApps
指定子应用配置文件地址,框架通过resourceLoader.mount(可以通过setResourceLoader进行指定)加载配置文件。
解析子应用配置
加载到的配置文件的内容将用于创建子应用实例,在创建子应用实例时,读取配置中页面列表字段,创建页面实例。
向singleSpa注册页面
创建页面实例后,根据页面配置,向singleSpa注册页面,
- appName由子应用名称和页面名称共同构成
- 应用生命周期主要是加载页面资源、渲染页面和卸载页面
- 应用激活函数则是基于path-to-regexp进行路由的匹配
如何发现子应用
向singleSpa注册页面时传入的应用激活函数,在注册时都会被遍历执行,只有执行返回为true(路由命中)的页面会被渲染,而之前已经渲染的页面一旦路由未命中则会被卸载。此后,每次路由变化时,singleSpa都会遍历执行应用激活函数。
如何加载子应用
加载子应用页面,其实就是在加载子应用页面的静态资源,框架通过resourceLoader.mount来进行加载,resourceLoader可以通过setResourceLoader进行指定。可以是通过script、link加载,也可以通过Systemjs加载,还可以是fetch加载(用于沙箱执行)。
为避免样式冲突,采用了动态样式机制,所以每次页面mount时,都会重新加载页面资源。
如何渲染子应用
当子应用页面mount时,框架获取到当前级别的渲染器,通过渲染器的mount方法渲染页面。这里涉及两个点,
- 当前级别。由于存在三级模型,可以将渲染器设置在不同级别,这样可以共享渲染器,避免编写重复代码,而且也便于管理。
- 渲染容器如何获取。可以通过setPageContainer进行指定。
子应用渲染时,如何添加其他逻辑
子应用页面渲染时,存在着多个阶段(加载资源、渲染页面、卸载页面等),每个阶段前后可以添加逻辑。