logologo
指南
API
博客
常见问题
指南
API
博客
常见问题
logologo

快速上手

介绍
快速开始
环境变量

接入指南

概述
react 子应用
vue 子应用
vite 子应用
angular 子应用

核心能力

bridge
缓存机制
生命周期
路由机制
构建配置
沙箱机制

进阶

插件指南
Previous Pageangular 子应用
Next Page缓存机制

#bridge

#介绍

Garfish bridge 是 garfish 提供的帮助用户降低接入成本的工具函数,它能自动提供 provider 函数所需的应用生命周期函数 render 和 destroy ,并实现框架不同版本的兼容。封装底层实现,降低接入成本和出错概率。

INFO
  1. garfish bridge 应用在子应用接入场景;
  2. 使用 garfish bridge 后不再需要显示提供 render 和 destroy 函数;
  3. 目前 garfish 仅针对 react 和 vue 框架提供 bridge 函数支持,支持的版本分别为 react v16、v17、v18,vue v2、v3;
  4. garfish bridge 暂未针对构建工具如 webpack、vite 提供相应的构建工具插件,我们后期会针对这块能力进行补全,请持续关注;

#工具包

#@garfish/bridge-react

@garfish/bridge-react 工具包是 garfish 为 react v16/v17 应用 提供的 bridge 工具函数包,其导出的 reactBridge 可用于 react v16/v17 子应用的接入,@garfish/bridge-react 的使用见 demo。

#@garfish/bridge-react-v18

@garfish/bridge-react-v18 工具包是 garfish 为 react v18 应用 提供的 bridge 工具函数包,其导出的 reactBridge 可用于 react v18 子应用的接入,@garfish/bridge-react-v18 的使用见 demo。

#@garfish/bridge-vue-v2

@garfish/bridge-vue-v2 工具包是 garfish 为 vue v2 应用 提供的 bridge 工具函数包,其导出的 vueBridge 可用于 vue v2 子应用的接入,@garfish/bridge-vue-v2 的使用见 demo。

#@garfish/bridge-vue-v3

@garfish/bridge-vue-v3 工具包是 garfish 为 vue v3 应用 提供的 bridge 工具函数包,其导出的 vueBridge 可用于 vue v3 子应用的接入,@garfish/bridge-vue-v3 的使用见 demo。

#安装

react 应用
vue2 应用
vue3 应用
npm install @garfish/bridge-react --save

#reactBridge(for react v16/v17/v18)

reactBridge 是 @garfish/bridge-react 工具包为 react 子应用提供的 bridge 工具函数。

INFO
  • 针对 react v16/v17 子应用,请使用 @garfish/bridge-react 工具包
  • 针对 react v18 子应用,请使用 @garfish/bridge-react-v18 工具包

reactBridge 是 @garfish/bridge-react 或 @garfish/bridge-react-v18 工具包为 react 子应用提供的 bridge 工具函数。

#Type

function reactBridge(userOpts: Options): (
  appInfo: any,
  props: any,
) => Promise<{
  render: (props: any) => any;
  destroy: (props: any) => any;
  update: (props: any) => any;
}>;

#示例

可访问 react16 子应用、 react17 子应用、react18 子应用 查看完整 demo

react v16/v17 应用
react v18 应用
import { reactBridge } from '@garfish/bridge-react';
import RootComponent from './components/root';
import ErrorComponent from './components/ErrorBoundary';

export const provider = reactBridge({
  el: '#root',
  rootComponent: RootComponent,
  errorBoundary: () => <ErrorComponent />,
});

#参数

Options

  • el
    • Type: string
    • 非必传
    • 子应用挂载点
      • 若子应用构建为 JS 入口时,不需要传挂载点,Bridge 将会以子应用的渲染节点作为挂载点;
      • 若子应用构建成 HTML 入口时,则直接传入选择器,bridge 内部通过 dom.querySelector 来基于子应用的 dom 来找到挂载点;
  • rootComponent
    • Type:React.ComponentType
    • 此参数和 loadRootComponent 至少传一个
    • 当前应用的顶层 React 组件,该组件中将接受到 garfish 传递的 appInfo 应用相关参数:
      // components/root.tsx
      const RootComponent = ({ appName, basename, dom, props }) => { ... }
    • 当同时传入了 loadRootComponent 参数时,rootComponent 参数将失效,且 rootComponent 组件不会默认接收到 garfish 传递的子应用相关参数;
  • loadRootComponent
    • Type:loadRootComponentType = (opts: Record<string, any>) => Promise<ComponentType>;
    • 此参数和 rootComponent 至少传一个
    • 当前应用的顶层 React 组件,该组件中将接收到 garfish 传递的子应用相关参数:
    // components/root.tsx
    const RootComponent = ({ appName, basename, dom, props }) => { ... }
    • loadRootComponent 是一个函数,返回一个 Promise 对象,resolve 后需要返回当前 React 应用的顶层组件,该顶层组件含义与 rootComponent 含义相同。当需要在 render 前进行异步操作时,可使用 loadRootComponent 加入副作用逻辑。
    • loadRootComponent 将默认接收到 garfish 传递的子应用相关参数:
     import { reactBridge } from "@garfish/bridge-react";
     export const provider = reactBridge({
       ...,
       loadRootComponent: ({ basename, dom, appName, props }) => {
          // do something async
         return Promise.resolve(() => <RootComponent basename={ basename } />);
       }
     });

    此时,RootComponent 接收到的参数取决于此处 loadRootComponent 传递的参数。

    • 当同时传入了 rootComponent 参数时,loadRootComponent 的优先级更高, rootComponent 将失效;
  • errorBoundary
    • Type:errorBoundary: (caughtError: boolean, info: string, props: any) => ReactNode | null;
    • 非必传
    • 设置应用的 errorBoundary 组件,errorBoundary 是一个函数,并在子应用发生错误时触发,该函数将传递 error 报错信息及报错相关应用堆栈信息:
     import { reactBridge } from "@garfish/bridge-react";
     export const provider = reactBridge({
       ...,
       errorBoundary: ( error, info ) => <ErrorComponent />,
     });

#vueBridge(for vue v2)

INFO

针对 vue v2 子应用,请使用 @garfish/bridge-vue-v2 工具包。

vueBridge 是 @garfish/bridge-vue-v2 工具包为 vue v2 子应用提供的 bridge 工具函数。

#类型

function vueBridge(userOpts: Options): (
  appInfo: any,
  props: any,
) => Promise<{
  render: (props: any) => any;
  destroy: (props: any) => any;
  update: (props: any) => any;
}>;

#示例

可访问 vue2 子应用 查看完整 demo

import { vueBridge } from '@garfish/bridge-vue-v2';
import store from './store';
import App from './App.vue';
import Home from './components/Home.vue';

Vue.use(VueRouter);
Vue.config.productionTip = false;

function newRouter(basename) {
  const router = new VueRouter({
    mode: 'history',
    base: basename,
    routes: [{ path: '/home', component: Home }],
  });
  return router;
}

export const provider = vueBridge({
  rootComponent: App,
  // 可选,注册 vue-router或状态管理对象
  appOptions: ({ basename, dom, appName, props }) => {
    // pass the options to Vue Constructor. check https://vuejs.bootcss.com/api/#%E9%80%89%E9%A1%B9-%E6%95%B0%E6%8D%AE
    return {
      el: '#app',
      router: newRouter(basename),
      store,
    };
  }
});

#参数

Options

  • rootComponent
  • Type:vue.Component

  • 非必传。此参数和 loadRootComponent 至少传一个

  • 当前应用的顶层 Vue 组件,该组件中将接受到 garfish 传递的子应用相关参数:

    // components/root.tsx
    const RootComponent = ({ appName, basename, dom, props, appInfo}) => { ... }
  • 当同时传入了 loadRootComponent 参数时,rootComponent 将失效,且 rootComponent 组件不会默认接受到 garfish 传递的子应用相关参数;

  • loadRootComponent
    • Type:loadRootComponentType = (opts: Record<string, any>) => Promise<ComponentType>;

    • 非必传。此参数和 rootComponent 至少传一个

    • 当前应用的顶层 Vue 组件,该组件中实例的 data 对象中将接收到 garfish 传递的子应用相关参数

    • loadRootComponent 是一个函数,返回一个 Promise 对象,resolve 后需要返回当前 Vue 应用的顶层组件,该顶层组件含义与 rootComponent 含义相同。当需要在 render 前进行异步操作时,可使用 loadRootComponent 加入副作用逻辑。

    • loadRootComponent 将默认接收到 garfish 传递的子应用相关参数:

     import { vueBridge } from "@garfish/bridge-vue-v2";
     export const provider = vueBridge({
       ...,
       loadRootComponent: ({ appName, basename, dom, props, appInfo }) => {
         // do something async
         return Promise.resolve(App);
       }
     });
    • 当同时传入了 rootComponent 参数时,loadRootComponent 的优先级更高, rootComponent 将失效;
  • appOptions
    • Type: appOptions: (opts: Record<string, any>) => Record<string, any> | Record<string, any>
    • 非必传
    • 作为函数时,接收 garfish 传递的子应用相关参数并返回用来实例化 Vue 应用的对象参数,也可作为对象类型直接返回用来实例化 Vue 应用的对象参数。实例化完成后,garfish 子应用相关参数将会自动注入到组件实例的 data 对象中。
    • appOptions 参数将直接透传为 Vue 构造函数实例化时的初始化参数 new Vue(appOptions),此时参数类型与 vue 保持一致。若未传递 appOptions 参数,则将自动提供 vue2 应用 render 函数用于渲染:render: (h) => h(opts.rootComponent)。
    • 若需要指定子应用挂载点,可在此参数中指定:appOptions: { el: '#app', ...},若未指定 el 参数,将默认使用全局挂载点。
TIP

需要注意的是,appOpitons 中并不会默认包含路由或状态逻辑的处理,可显示在 appOpitons 中传递路由参数信息。

import { vueBridge } from '@garfish/bridge-vue-v2';
export const provider = vueBridge({
  rootComponent: App,
  appOptions: ({ basename, dom, appName, props, appInfo }) => {
    // pass the options to Vue Constructor. check https://vuejs.bootcss.com/api/#%E9%80%89%E9%A1%B9-%E6%95%B0%E6%8D%AE
    return {
      el: '#app',
      router: newRouter(basename),
      store,
    };
  }
});
  • handleInstance
    • Type: handleInstance: (vueInstance: InstanceType<vue.VueConstructor>, opts: optionsType) => void;
    • 非必传
    • 处理 app 实例对象的函数,接受创建的 app 实例对象及 garfish 子应用相关参数,可自定义处理逻辑如路由注册或状态管理等相关能力。

#vueBridge(for vue v3)

INFO

针对 vue v3 子应用,请使用 @garfish/bridge-vue-v3 工具包。

vueBridge 是 @garfish/bridge-vue-v3 工具包为 vue v3 子应用提供的 bridge 工具函数。

#类型

function vueBridge(userOpts: Options): (
  appInfo: any,
  props: any,
) => Promise<{
  render: (props: any) => any;
  destroy: (props: any) => any;
  update: (props: any) => any;
}>;

#示例

可访问 vue v3 子应用 查看完整 demo

import { createRouter, createWebHistory } from 'vue-router';
import { stateSymbol, createState } from './store.js';
import App from './App.vue';
import Home from './components/Home.vue';
import { vueBridge } from '@garfish/bridge-vue-v3';

function newRouter(basename) {
  const router = createRouter({
    history: createWebHistory(basename),
    routes: [{ path: '/home', component: Home }],
  });
  return router;
}

export const provider = vueBridge({
  rootComponent: App,
  // 可选,注册 vue-router或状态管理对象
  handleInstance: (vueInstance, { basename, dom, appName, props, appIndfo }) => {
    vueInstance.use(newRouter(basename));
    vueInstance.provide(stateSymbol, createState());
  },
});

#参数

Options

  • rootComponent
  • Type:vue.Component

  • 非必传。此参数和 loadRootComponent 至少传一个

  • 当前应用的顶层 Vue 组件,该组件中将接受到 garfish 传递的子应用相关参数:

    // components/root.tsx
    const RootComponent = ({ appName, basename, dom, props, appInfo}) => { ... }
  • 当同时传入了 loadRootComponent 参数时,rootComponent 将失效,且 rootComponent 组件不会默认接受到 garfish 传递的子应用相关参数;

  • loadRootComponent
    • Type:loadRootComponentType = (opts: Record<string, any>) => Promise<ComponentType>;

    • 非必传。此参数和 rootComponent 至少传一个

    • 当前应用的顶层 Vue 组件,该组件中实例的 data 对象中将接收到 garfish 传递的子应用相关参数

    • loadRootComponent 是一个函数,返回一个 Promise 对象,resolve 后需要返回当前 Vue 应用的顶层组件,该顶层组件含义与 rootComponent 含义相同。当需要在 render 前进行异步操作时,可使用 loadRootComponent 加入副作用逻辑。

    • loadRootComponent 将默认接收到 garfish 传递的子应用相关参数:

     import { vueBridge } from "@garfish/bridge-vue-v3";
     export const provider = vueBridge({
       ...,
       loadRootComponent: ({ appName, basename, dom, props, appInfo }) => {
         // do something async
         return Promise.resolve(App);
       }
     });
    • 当同时传入了 rootComponent 参数时,loadRootComponent 的优先级更高, rootComponent 将失效;
  • appOptions
    • Type: appOptions: (opts: Record<string, any>) => Record<string, any> | Record<string, any>
    • 非必传
    • 作为函数时,接收 garfish 传递的子应用相关参数并返回用来实例化 Vue 应用的对象参数,也可作为对象类型直接返回用来实例化 Vue 应用的对象参数。实例化完成后,garfish 子应用相关参数将会自动注入到组件实例的 data 对象中。
    • 在 Vue3 中,appOptions 参数将直接透传给 createApp 函数调用: createApp(appOptions),此时参数类型与 createApp 保持一致。若未传递 appOptions 参数,则将直接调用 createApp(rootComponent) 创建根组件。
    • 若需要指定子应用挂载点,可在此参数中指定:appOptions: { el: '#app', ...},若未指定 el 参数,将默认使用全局挂载点。
TIP

需要注意的是,appOptions 中并不会默认包含路由或状态逻辑的处理,可通过 handleInstance 函数拿到创建的 vue 实例对象后进行路由注册。

  • handleInstance
    • Type: handleInstance: (vueInstance: vue.App, opts: optionsType) => void;
    • 非必传
    • 处理 app 实例对象的函数,接受创建的 app 实例对象及 garfish 子应用相关参数,可自定义处理逻辑如路由注册或状态管理等相关能力。
import { vueBridge } from '@garfish/bridge-vue-v3';
export const provider = vueBridge({
  rootComponent: App,
  // 获取 vue 实例并进行路由注册和状态注册
  handleInstance: (vueInstance, { basename, dom, appName, props, appInfo }) => {
    vueInstance.use(newRouter(basename));
    vueInstance.provide(stateSymbol, createState());
  },
});