Garfish.registerApp
用于注册子应用信息,为 Garfish 实例方法。
Garfish.run()
中 apps 应用信息注册底层就是依赖registerApp
的注册能力;registerApp
为 Garfish 实例方法,用户可调用该 API 动态注册子应用信息,若出现Garfish.run()
中的同名 app 应用信息,将覆盖Garfish.run()
中的 app 应用信息(merge, not override);
类型
registerApp(list: interfaces.AppInfo | Array<interfaces.AppInfo>): Garfish;
默认值
- 无
示例
import Garfish from 'garfish';
// 注册单个应用:
Garfish.registerApp({
name: 'vue-app',
basename: '/demo',
activeWhen: '/vue-app',
entry: 'http://localhost:3000',
props: {
msg: 'vue-app msg',
},
});
// 注册多个应用
Garfish.registerApp([
{
name: 'vue-app',
activeWhen: '/vue-app',
entry: 'http://localhost:3000',
},
{
name: 'react-app',
activeWhen: '/react-app',
entry: 'http://localhost:2000',
},
]);
Type AppInfo
AppInfo 为子应用 app 配置类型,此配置与 Garfish.run() 全局配置中 app 相关参数含义相同。
export interface AppInfo extends AppConfig, AppLifecycle {}
Garfish 处理 app 参数的原则是:
- 对于同名字段,子应用中的配置具备更高优先级;
- 默认情况下,Garfish 使用全局配置作为每个子应用配置;
- 针对单个子应用的信息配置不影响其它子应用;
参数
name
- Type: string
- 子应用名称,必选;
- 请确保每个子应用名称唯一;
basename?
- Type: string
- 子应用的基础路径,可选,默认值为全局 basename;
- 通过路由驱动自动加载子应用时实际传递给子应用的 basename 为
basename + activeWhen
计算的值 - 若手动载入渲染应用时
basename
为实际传入的值 - 通过 provider 函数 的
basename
参数透传给子应用,子应用需要将 basename 设置为相应子应用的基础路由,这是必须的; - 为什么子应用需要设置 basename ?
entry
- Type: string
- 子应用的入口资源地址,支持 HTML 和 JS 入口,必选
domGetter?
- Type: interfaces.DomGetter
export type DomGetter =
| string
| (() => Element | null)
| (() => Promise<Element>);
- 子应用的默认挂载点,可选,没有默认值,若省略需要在子应用 AppInfo 中单独指定。二者同时存在时,子应用指定优先级更高;
- 当提供
string
类型时需要其值是selector
, Garfish 内部会使用document.querySelector(domGetter)
去选中子应用的挂载点 - 当提供
string
类型的domGetter
时,子应用在触发渲染后并不会若当前文档流上并不存在挂载点,Garfish
框架内部在3s
内轮讯是否有挂载点 - 当提供函数时,将在子应用挂载过程中执行此函数,并期望返回一个 dom 元素;
- 若
domGetter
在子应用渲染时无法查询到挂载点,则会丢出domGetter
无效的异常
props?
- Type: Object
- 初始化时主应用传递给子应用的数据,可选。子应用
provider
导出函数 生命周期方法中将接收到此数据;
sandbox?
Type: SandboxConfig | false 可选,默认值为 全局 sandbox 配置,当设置为 false 时关闭沙箱;
SandboxConfig:
interface SandboxConfig {
// 是否开启快照沙箱,默认值为 false:关闭快照沙箱,开启 vm 沙箱
snapshot?: boolean;
// 是否自动以子应用入口的域名前缀对子应用 fetch 请求的进行补齐,默认值为 false
fixBaseUrl?: boolean;
// 是否自动以子应用入口的域名前缀对相对路径资源进行前缀修正,默认值为 true,v1.15.0 版本提供
fixStaticResourceBaseUrl?: boolean;
// 是否开启开启严格隔离,默认值为 false。开启严格隔离后,子应用的渲染节点将会开启 Shadow DOM close 模式,并且子应用的查询和添加行为仅会在 DOM 作用域内进行
strictIsolation?: boolean;
// modules 仅在 vm 沙箱时有效,用于覆盖子应用执行上下文的环境变量,使用自定义的执行上下文,默认值为[]
modules?: Array<Module> | Record<string, Module>;
// disableElementtiming 1.14.4 版本提供,默认值为 false,将会给子应用元素注入 elementtiming 属性,可以通过此属性获取子应用元素的加载时间
disableElementtiming?: boolean;
// fixOwnerDocument 1.17.2 版本提供 ,默认值 false,目前可能会存在 ownerDocument 逃逸的情况,设置为 true 之后将会避免 ownerDocument 逃逸
fixOwnerDocument?: boolean;
}
type Module = (sandbox: Sandbox) => OverridesData | void;
export interface OverridesData {
recover?: (context: Sandbox['global']) => void;
prepare?: () => void;
created?: (context: Sandbox['global']) => void;
override?: Record<PropertyKey, any>;
}
- 示例
Garfish.run({
sandbox: {
snapshot: false,
strictIsolation: false,
// 覆盖子应用 localStorage,使用当前主应用 localStorage
modules: [
() => ({
override: {
localStorage: window.localStorage,
},
}),
],
},
});
请注意: 如果你在沙箱内自定义的行为将会产生副作用,请确保在 recover 函数中清除你的副作用,garfish 将在应用卸载过程中执行 recover 函数销毁沙箱副作用,否则可能会造成内存泄漏。
在什么情况下我应该关闭 sandbox ?
Garfish 目前已默认支持沙箱 esModule 能力,若需要在 vm 沙箱支持 esModule 应用,请使用
@garfish/es-module
garfish 官方插件支持此能力,但这会带来严重的性能问题,原因。如果你的项目不是很需要在 vm 沙箱下运行,此时可以关闭沙箱;
若开启快照沙箱,请注意:
- 快照沙箱无法隔离主、子应用
- 快照沙箱无法支持多实例(同时加载多个子应用) :::
activeWhen?
Type: string | ((path: string) => boolean)
子应用的激活路径或激活条件,是子应用配置中的重要配置项,接收 string 和 函数类型,可选。
activeWhen
使用场景为基于路由模式加载子应用时,计算当前应激活的子应用的判断条件,当使用手动加载 loadApp 时将忽略activeWhen
选项。如果你的应用是基于路由驱动式挂载子应用,你应该始终传递activeWhen
;在每次发生路由变化时,Garfish 都会触发 activeWhen 的校验逻辑去判断当前应该激活的子应用;
当参数为 string 类型时:
activeWhen
应设置为子应用的一级路由Garfish 将使用字符串最短匹配原则作为激活判断条件匹配子应用,各子应用的
activeWhen
参数应保持唯一(即:Garfish 能够精准匹配到当前应该激活的子应用,应避免子应用间出现activeWhen
重合的情况;在路由驱动模式下,子应用中接收到的
activeWhen: '/vue-app',(basename:'/')basename
参数将是basename
+activeWhen
:- ✅ https://demo.app/vue-app
- ✅ https://demo.app/vue-app/about
- ✅ https://demo.app/vue-app/detail/goods
- 🚫 https://demo.app/vue-app2
- 🚫 https://demo.app/react-app
当参数为 function 类型时:
- function 将接受到参数 path,用户可在函数内定义判断逻辑,返回
true
表示激活当前应用,否则应返回false
; - 示例
import Garfish from "garfish";
Garfish.run({
...,
apps: [
{
name: "vue",
activeWhen: (path) => path.startsWith('/vue-app') || path.startsWith('/sub-app')
entry: 'http://localhost:3000'
}
]
})- 校验过程中,当参数为 function 类型时,Garfish 会将当前的路径传入激活函数分割以得到子应用的最长激活路径,并将
basename
+子应用最长激活路径
传递给子应用参数;
- function 将接受到参数 path,用户可在函数内定义判断逻辑,返回
什么时候不需要设置 activeWhen?
activeWhen 为基于路由模式加载子应用时的激活路径(或条件),目的是为了寻找当前应该激活的子应用。当用户使用 loadApp 手动挂载应用时,此时可省略
activeWhen
参数。
- 子应用如果本身具备路由,在微前端的场景下,必须把 basename 作为子应用的基础路径,没有基础路由,子应用的路由可能与主应用和其他应用发生冲突;
- 我们强留建议不要使用根路径作为子应用的激活条件,为什么?
cache?
- Type: boolean
- 是否缓存子应用。若已加载过应用,在缓存模式下将返回相同的应用实例,可选,默认值为
true
; - Garfish 默认会对加载过的 app 进行缓存策略,目的是为了节省二次渲染开销,避免重复的编译代码造成的性能浪费,以及避免逃逸代码可能造成的内存泄漏。若关闭此选项,将会严重影响子应用的加载速度,需要仔细权衡;
- 在缓存模式下,Garfish 将不会执行子应用所有代码,仅执行 render ,可以避免逃逸代码造成的内存问题;
- 缓存模式也存在一定的弊端,关于 Garfish 的缓存机制,请移步 Garfish 缓存机制;
noCheckProvider
- Type: boolean
- 是否检查
provider
函数,可选,默认为 true;
asyncProviderTimeout
- Type: number
- 全局异步provider超时时间,默认是2000ms,设置为0的话,只允许同步provider;
- 此项特性适用于那些不太方便处理成同步暴露provider的子应用,比如某些脚手架新建的项目,项目里看到的entry文件,实际上会被包裹一层并且动态import进来;