微前端应用功能开发指引

1. 开发须知

1.1 什么是微前端?

微前端:将巨大的单体前端系统拆分成多个独立的小型系统,最后集成为一个系统的架构思路,分而治之,让系统更加容易维护、更易扩展。

微前端架构

1.2 模块联邦 Module Federation

DM Hub 中的微前端技术使用的是 webpack5 引入的新特性 - 模块联邦,所以插件应用同样需要使用 webpack5 以上的版本。

通过模块联邦,可以实现跨应用的代码共享。在插件应用中将代码提供给其他应用,然后在 DM Hub 中进行消费。

const { ModuleFederationPlugin } = require('webpack').container // 模块联邦插件

module.exports = {
  // ...
  // webpack 插件配置
  plugins: [
    new ModuleFederationPlugin({
      name: 'dashboard', // exposeRemoteName 共享的模块名字,在消费该模块的应用中会用到 不能使用 -
      filename: 'remoteEntry.js', // 远程加载的文件名字,在浏览器请求面板可看到,默认名字就是 remoteEntry.js
      exposes: {
        './DashboardApp': './src/bootstrap', // 从本应用暴露的共享模块,可共享多个模块 key 以 ./ 开头,value 指向本地的一个文件
      },
      shared: packageJson.dependencies, // 希望共享的依赖
    }),
  ],
}

具体原理,可参考如下链接:

2. 应用配置

本开发流程以抖音插件为例。

插件的开发依赖于 dmhub-ui,如果无此项目,请使用 ui-starter-shell 项目,CLONE 该项目并安装好依赖

2.6 版本应用的 ui-starter-shell 下载地址:https://gitlab.cd.xsio.cn/tmc_campaign/ui-starter-shell/-/tree/2.6 2.7 及以上版本应用的 ui-starter-shell 下载地址:https://gitlab.cd.xsio.cn/tmc_campaign/ui-starter-shell

下载项目,安装、启动服务,具体参考该项目的 README.md,本地服务地址默认 http://localhost:3003.

2.1 创建 repo

微前端应用模板:

基于微前端应用模板创建一个新的 repo:extdouyin

2.2 创建应用

应用在和 DM Hub 对接之前,需要先在 DM Hub 开放平台上创建一个应用,并做相应的设置。主要的设置项说明如下:

2.2.1 基本信息设置

基本信息

应用 ID:以 cp_ 开头,可以包含字母和数字,必须全局唯一,创建时系统会做唯一性检查。

名称:该应用的名称,最长 20 个字符。

简介:应用的描述,最多支持 1000 字符。

支持的产品类型:主要分为 DM Hub 版 和集客版,默认 DM Hub,根据需求选择。

主页地址:在应用市场点击应用时要打开的链接,一般为 extension/服务名称/dist/index.js,服务名称一般就是 repo 名称。

图标地址:可访问的图片链接

部件:配置各个接入点,详见下文。

测试账号:用于测试的 tenant id,可以填入多个。只有填写的 tenant 才可以参与测试。

2.2.2 开发设置

开发设置

所需权限:包括客户、群组、微信相关和会员相关权限集,按需选择,可以多选。

授权回调地址:授权完成后回调的地址,在进行应用授权时会使用到该地址。

事件订阅回调地址:可选项,用于接受事件推送的地址。

保存后会生成一对 clientID 和 clientSecret。为了安全起见,应用密钥需要马上保存,关闭对话框后将无法再次看到,如果遗失,需要重置密钥。

2.3 自动流程集成

第三方服务往自动流程里添加的 action 在运行的过程中通过 webhook 的方式往第三方服务指定的地址推送消息。为了往自动流程里添加一个第三方服务的 action,第三方服务需要提供两样内容:action 的编辑页面,接收自动流运行时消息推送的接口。

2.3.1 开放平台的配置

在开放平台上新增一个自定义 action 时需要做如下配置:

基本信息

各字段说明如下:

动作 ID:格式为 应用ID_action_动作ID,可以填入字母和数字。

图标 class:支持可访问的图片链接及 DMHub 内置支持的图标名称(包括 ant-design 图标、c-design 图标)

名称:自动流程中 action 的名称,建议尽可能短,否则排版会有问题。

渲染 Url:在自动流程中编辑该 action 时的编辑页面,同主页地址一致。

上下文属性:勾选该属性,会在自动流程的该节点中多一个上下文节点选项,用于选择上下文节点。

自定义对象:应用插件默认用于客户对象营销,勾选后支持自定义对象营销。

webhook 设置:自动流程里的 action 在执行过程中通过 webhook 的方式将参数推送到第三方服务的指定地址。这里需要指定第三方服务接收消息的地址和鉴权方式。具体使用方式可参考产品中 webhook 的用法。

3. 项目配置

拉取创建好的 repo 到本地

3.1 调整 webpack.config.js 配置

webpack 主要调整 ModuleFederationPlugin 插件的配置,其他配置保持不动

module.exports = {
  // ...
  plugins: [
    // TODO 1: 配置项目主页(如果不需要主页,则删除该配置)
    new ModuleFederationPlugin({
      name: 'extension_cp_{{name}}',  // TODO 1.1 替换{{name}}为具体插件内部id (此处替换后是 extension_cp_extdouyin)
      // TODO: 1.2 将开放平台中的【主页地址】配置为: /extension/插件服务地址/dist/index.js(前面步骤已设置(见2.2.2),可检查确认)
      // 插件服务地址应与插件内部id相同,如果不一致,请通知后端同学修改
      filename: 'index.js',  // 打包后的文件名。
      exposes: {
        // TODO 1.3 修改项目入口文件路径
        // 将./src/index.tsx 替换为实际使用的入口文件路径
        // ./index.module 为固定格式 请勿修改
        './index.module': './src/index.tsx',
      }
    }),

    // TODO 2: 设置自动流程插件(如果不需要自动流插入点,则删除该配置)
    new ModuleFederationPlugin({
      name: 'extension_cp_{{name}}',  // TODO 2.1 替换{{name}}为具体插件内部id (以ext开头)
      // TODO: 2.2 设置开放平台:【部件】:【自动流】->【动作设置-渲染Url】
      // 修改为: /extension/插件服务地址/dist/actions.js
      // 所有的自动流渲染Url均相同。
      // 插件服务地址应与插件内部id相同,如果不一致,请通知后端同学修改
      filename: 'actions.js', // 打包后的文件名。
      exposes: {
        // TODO 2.3 cp_{{name}}_action_send_card 对应开放平台中的配置【部件】:【自动流】->【动作Id】,注意 exposes的key前面有./
        // TODO 2.4 ./src/actions/TikTokCard.tsx 是插件对应的组件路径,替换为实际开发中的路径
        './cp_{{name}}_action_send_card': './src/actions/TikTokCard.tsx',

        // 如果有多个, 可增加多个
        // './cp_{{name}}_action_send_card_2': './src/actions/TikTokCard2.tsx',
      },
    }),
  ]
}

3.2 调整 dmhub-ui 配置

  • 如果开发应用插件,修改 ModuleApp.tsx 中的 config,如下:
config = {
  config: {
    scope: `extension_${pluginId}`,
    url: 'http://localhost:9000/index.js', // 对应启动的插件端口号,可根据实际开发调整
    path,
    module: './index.module',
  },
};
  • 如果开发自动流程插件,修改 PluginModuleAction.tsxconfig,如下:
setConfig({
  config: {
    scope: `extension_${pluginId}`,
    url: 'http://localhost:9000/index.js', // 对应启动的插件端口号,可根据实际开发调整
    path,
    module: './cp_extdouyin_action_send_message', // 设置为需要开发的自动流插件的 actionId
  },
});

4. 本地开发

4.1 安装并启动 dmhub-ui

# 安装依赖
yarn

# 启动服务,默认地址:http://localhost:3003/
yarn start

4.2 安装启动应用

# 安装依赖
yarn

# 启动服务
yarn start

4.3 安装并打开应用

打开 http://localhost:3003,登录系统,然后打开应用集成 - 应用与市场 - 应用市场,找到配置好的插件,点击安装

安装应用

安装完成之后,再点击打开按钮,即可看到模板文件的界面

预览应用

4.4 开发应用

可参考模板中 src/index.tsx 文件

应用的入口文件会接收到 DM Hub 传入的两个参数:baseUrlrights

  • baseUrl: 基础路径,在使用 Link 或者 navigate 进行跳转时,注意添加 baseUrl
  • rights: 用于判断用户权限的函数,根据实际情况选择使用

应用开发 `` 然后根据具体的开发需求,调整 src 中的相关文件

4.4 开发自动流程插件

可参考模板中 src/acitons/TiktokCard.tsx 文件

自动流插件都会接收到如下参数:

  • refObjId,自动流程主对象的关联对象objId
  • identity,自动流程主对象所关联对象的属性ID
  • openAppId,插件的 openAppId
  • actionBody,插件保存的数据
  • onActionBodyChange,保存插件的数据的方法
  • openAppId,应用ID
  • onContext,函数,入参为布尔值,无返回值。用于控制上下文节点选项的展示与隐藏,传入 true,则会展示上下文节点选项,false 则会隐藏上下文节点选项
  • getContext,函数,入参字符串,返回值为数组。用于获取格式化后的上下文事件属性列表。配合 onContext 使用,可通过数组长度判断是否包含上下文事件属性,具体见 4.5

自动流程插件开发

在自动流程运行的过程中,当执行到该 action 时,系统会将处理好的消息体(比如替换变量等)推送给上文在开放平台上设置的消息接收地址,该接口需要能正确处理传入的消息。

例如,当 action 编辑页面生成的 content 为下面数据时:

{
  "actionBody": {
      "customerId": "${id}",
      "mobile": "${mobile}",
      "attribute1": "value1",
      "attribute2": "value2"
  }
}

那么,自动流程在运行时推送的对应的 webhook 消息格式如下:

{
  "customerId": "123456",
  "mobile": "13333333333",
  "attribute1": "value1",
  "attribute2": "value2"
}

其中的变量支持所有的客户属性和自定义客户属性,如上面例子中,id 和 mobile 都是客户的属性。

如果需要传递自动流程的 ID,可以在 actionBody 中插入一个特殊的属性:

"flowId": "${flowId}"

4.5.1 上下文节点

开启方式:开发平台 - 选择具体应用 - 编辑 - 部件 - 自动流 - 配置 - 编辑具体动作节点 - 勾选上下文属性开启。

开启改配置之后,会多出一个上下文节点选项。在默认情况下,自动流程会校验插件返回的数据,必须包含如下的上下文事件属性内容, 否则会报错提示;

当然会存在某些数据存在,某些数据不存在上下文事件属性的情况。在不存在的情况下,需要将上下文节点选项隐藏,此时需要插件内部实现相关 的校验及隐藏上下文节点。自动流会通过 props 传递两个参数给插件,分别是 onContextgetContext

  • onContext,用于控制上下文节点选项的展示与隐藏,入参为布尔值,无返回值。传入 true,则会展示上下文节点选项,false 则会隐藏上下文节点选项
  • getContext,配合 onContext 使用,获取上下文事件属性,返回值为数组,可通过数组长度判断是否包含上下文事件属性。

示例代码:

const { onContext, getContext } = props;

const contextList = getContext('返回给自动流的数据,可通过 JSON.stringfy 转换为字符串传入');

if (contextList.length > 0) {
  // 显示自动流上下文节点
  onContext(true);
} else {
  // 隐藏自动流上下文节点
  onContext(false);
}

上下文事件属性:${event.EVENT_NAME.PROP_COLUMN!"REPLACEMENT"}

  • EVENT_NAME 事件名称,不能为空
  • PROP_COLUMN 事件属性名称,不能为空
  • REPLACEMENT 未获取到事件属性时的显示值,可以为空

5. 应用自定义事件设置

如果应用里需要记录事件,可以在开放平台配置。通过开放平台配置的事件会在 DM Hub 设置中心的事件设置中显示,但是无法修改,如需修改要在开放平台进行,并进行重新上架。事件配置方法和 DM Hub 的设置中心中事件的设置方法基本一致,说明如下:

开发流程

事件名称为事件的中文描述。

事件 ID 以应用的 ID 为前缀,需要保证全局唯一。

是否接触事件:即是否为客户接触类事件,所有客户接触类事件会在客户事件轴上显示。

是否允许评分:设置为是,则可以为该事件设置评分,事件发生时,会将对应的分数加在客户身上。

自定义属性:属性的类型和可添加的个数如图中所示。

6. 自定义身份设置

应用可以定义自己要使用的自定义客户身份。设置方法和 DM Hub 设置中心的自定义身份设置方法基本一致,但是不可以在产品的设置中心修改。设置方式如下:

开发流程

身份名称:即身份的中文描述,例如淘宝身份。

身份类型:即身份 ID,以应用 ID 为前缀,需要全局唯一。

身份图标:在 DM Hub 中显示的身份图标,可以设置图标和背景色。

7. 发布上架流程

对于私有云部署环境,可以简化上架流程。在前文 1.1 的基本设置中,直接把要安装该应用的 tenantID 添加在“测试账号”中,则这些 tenant 即可在应用市场看到该应用。无需再进行额外的发布上架流程。

对于公有云环境,则需要在应用列表页面发布该应用,并联系对应的项目经理或运维人员通知系统管理员进行上架审批。