一、安装依赖

# 使用npm安装依赖
npm i @cvte/resource-center-sdk@1.7.28
# 或使用yarn安装依赖
yarn add @cvte/resource-center-sdk@1.7.28

资源中心SDK类型声明文档

资源中心SDK - 版本变更日志

二、环境检查

工程须使用webpack5,且开启topLevelAwait特性

module.exports = (config) => {
    if (!config.experiments) {
        config.experiments = {};
    }
    config.experiments.topLevelAwait = true;

    return config;
}

三、加载资源

资源名称

每个单独的资源个体,其名称在资源管理系统中唯一;

资源宿主

每个使用到远程资源的资源,就是资源宿主;

导出名

每个资源都有开发者自定义的导出内容,可以在资源管理系统中查看;

导出内容

由资源开发者在资源的rc.exposes.js文件中定义;

如果当前宿主工程是资源

首先在宿主资源中package.json所在目录下执行命令:

rc install group1/dep1@version group2/dep2@version
# 或缩写 rc i group1/dep1@version group2/dep2@version
# 其中group为资源所属项目分组,缺省为public
# 其中dep为资源名称,必填信息
# 其中version为资源版本,缺省为latest

查看资源的导出内容

方式一:资源详情页面查看当前【DEV】最新版本导出点;

方式二:资源历史版本也没查看对应历史版本的导出点;

其中shared代表共享出本资源下的依赖模块,并且可被全局其他资源使用;

普通加载

import Loader, { ILoaderResourceEnv } from '@cvte/resource-center-sdk';

const loader = new Loader({
    appName: '资源宿主对应在资源中心中的资源名称',
    name: '资源名称可在资源管理系统中获得,具体操作可见下文【资源管理系统】',
    env: '',  // 加载对应环境下的资源,资源枚举的环境有【DEV,FAT,UAT,PRO】
});
// 假设资源导出内容为 { default: {} }
const { default } = await loader.load('导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】', {
    useShared: true,
    mode: 'page',
})

// 如果需要加载指定导出内容里的某一个键 { default: {}, A: {} }
// 要求@cvte/resource-center-sdk版本>=1.6.5
const { default } = await loader.load('导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】', {
    useShared: true,
    mode: 'page',
    // 当该参数为string时,如果导出为对象类型,则作为键值获取对象中对应的值作为导出内容,否则该参数无效直接返回原始导出内容
    // 当该参数为<T = any>(expose?:T)=>T|Promise<T>时,则执行该转换方法,返回结果则作为导出内容,如果方法无返回,则直接返回原是导出内容
    exposeTransfer: 'A'
})

其中在同步代码中使用await关键字,如想通过tslint检查,须将tsconfig.json做如下修改:

{
    "module": "esnext",
    "target": "ES2017",
    // ...其他内容
}

React组件资源载入

远端组件直接载入

用于当远端文件内容为export default Component的方式

import Loader, { ReactRemoteLoaderComponent, ILoaderResourceEnv } from '@cvte/resource-center-sdk';

const Component = ReactRemoteLoaderComponent(
  new Loader({
    appName: '资源宿主对应在资源中心中的资源名称',
    name: '资源名称可在资源管理系统中获得,具体操作可见下文【资源管理系统】',
    env: `${document.getElementById('ENV')?.getAttribute('value') as ILoaderResourceEnv}`, // 元素id名必须与server.js中injectData增加的环境变量参数名一致,加载对应环境下的资源,资源枚举的环境有【DEV,FAT,UAT,PRO】
  }),
  '导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】',
  {
    useShared: true,
    mode: 'page',
  },
  (component)=>{
   // 加载完成后的回调函数,返回加载完成的远程组件
  },
  ()=>{
   // 组件销毁时的回调函数
  }
);

// 如果相对React组件进行监听可使用参数:__loaderLoading,__loaderOnError,__onLoaded,__onEnded
<Component
__loaderLoading={
 // 加载时展示的元素
 <Spin spinning />
}
__loaderOnError={
 // 加载错误时回调
 (err,info)=>{}
}
__onLoaded={
 // 加载完成时回调
 (component)=>{}
}
__onEnded={
 // 组件销毁时回调
 ()=>{}
} />

其中在执行顺序上,ReactRemoteLoaderComponent参数中传入的回调函数先执行,加载后组件的参数中传入的__loaderLoading,__loaderOnError,__onLoaded,__onEnded回调函数后执行

远端组件载入指定内容(v1.6.5+)

该特性在@cvte/resource-center-sdk@1.6.5及其以后版本存在。

用于当远端文件内容为export { Component, ...otherComponents }的方式

import Loader, { ReactRemoteLoaderComponent, ILoaderResourceEnv } from '@cvte/resource-center-sdk';

const Component = ReactRemoteLoaderComponent(
  new Loader({
    appName: '资源宿主对应在资源中心中的资源名称',
    name: '资源名称可在资源管理系统中获得,具体操作可见下文【资源管理系统】',
    env: `${document.getElementById('ENV')?.getAttribute('value') as ILoaderResourceEnv}`, // 元素id名必须与server.js中injectData增加的环境变量参数名一致,加载对应环境下的资源,资源枚举的环境有【DEV,FAT,UAT,PRO】
  }),
  '导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】',
  {
    useShared: true,
    mode: 'page',
    exposeTransfer: 'Component'
  },
  (component)=>{
   // 加载完成后的回调函数,返回加载完成的远程组件
  },
  ()=>{
   // 组件销毁时的回调函数
  }
);

远端组件自定义载入容器

用于需要自定义远端组件加载容器的场景

import Loader, { ILoaderResourceEnv, ReactLoaderContainer } from '@cvte/resource-center-sdk';

const Component = (
  <ReactLoaderContainer
      __loaderErrorDisplay={
        // 组件渲染异常时展示内容
    }
    __loaderLoading={
        // 加载展示的元素
    }
    __loaderOnError={
        // 组件发生错误时回调
    }
    __onEnded={
        // 组件销毁时回调
    }
    __onLoaded={
        // 加载完成时回调
    }
   >
    {React.lazy(
      () =>
        new Promise<{ default: React.FC<any> }>(async (resolve) => {
          const loader = new Loader({
            appName: '资源宿主对应在资源中心中的资源名称',
            name: '资源名称可在资源管理系统中获得,具体操作可见下文【资源管理系统】',
            env: `${document.getElementById('ENV')?.getAttribute('value') as ILoaderResourceEnv}`,
          });
          const { Component } = await loader.load<{ Component: React.FC<any> }>(
              '导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】',
              {
                useShared: true,
                mode: 'page',
              }
          );
          resolve({ default: Component });
        })
    )}
  </ReactLoaderContainer>
);

// JSX调用该组件
{ Component }

四、高级场景

根应用特性

@cvte/resource-center-sdk包版本version>=1.7.2中,我们内置了设置根应用的特性。可将该应用资源下资源依赖平铺,直接定向在某环境下动态调整某应用资源的依赖资源版本。具体场景示例如下:

对CSB应用设置为根应用

修改CSB工程的global.js文件内容,新增改动如下:

import { GlobalRootApp } from '@cvte/resource-center-sdk';

GlobalRootApp.setRootApp({
  name: '当前CSB工程的资源名称',
});

设置所有嵌套资源访问资源服务的域名地址

修改CSB工程的global.js文件内容,新增改动如下:

import { GlobalRootApp } from '@cvte/resource-center-sdk';

GlobalRootApp.setRootApp({
  name: '当前CSB工程的资源名称',
  host: '//rc-overseas.cvte.com' // host的配置中不能携带协议名称(http|https),只能用//开头
});

rc-overseas.cvte.com地址是资源中心服务专门针对海外访问场景所做的域名

此处修改会将该根宿主下所有依赖资源文件访问的主域名从rc.cvte.com变更为rc-overseas.cvte.com;

如访问tz-render资源原来的url为:https://rc.cvte.com/api/resource/当前CSB工程的资源名称/tz-render/pro/latest/rc.meta.json

设置之后则会变更为:https://rc-overseas.cvte.com/api/resource/当前CSB工程的资源名称/tz-render/pro/latest/rc.meta.json

资源管理系统中修改根应用下依赖资源的版本

请参见资源开发-指定根应用下的资源版本变更

资源上下文

@cvte/resource-center-sdk包版本version>=1.3.5中,我们内置了资源上下文的特性。
可根据当前资源或全局共享上下文进行操作。
具体场景示例如下:

获取全局资源依赖

获取全局的共享依赖数据及其实例对象

import { Context } from '@cvte/resource-center-sdk';

const allDeps = new Context().getContext();
/*
allDeps = {
  antd: {
    '0':{ // 0为全局默认依赖版本
     from: 共享依赖的资源名称
     loaded: 共享依赖是否加载完成,0|1
     eager: 共享依赖是否为即时依赖
     get: 获取共享依赖实例
    },
    '4.17.2':{
     from: 共享依赖的资源名称
     get: 获取共享依赖实例
    }
  }
}
**/

const getAntd = new Context().getContext()?.antd['4.17.2']?.get;
const antd = await getAntd();

操作指定资源

在某个资源中设置了数据,在其他资源中引用该数据

// resource-a.tsx
import { Context, ContextData } from '@cvte/resource-center-sdk';

const context = new Context('resource-a');
const data = new ContextData();
data.setCommon({ a: 1 });
context.setContext(data);

//resource-b.tsx
import { Context, ContextData } from '@cvte/resource-center-sdk';

const context = new Context('resource-a');
const data = context.getContext();
/**
 data: {
 a: 1,
 }
**/

资源管理器

@cvte/resource-center-sdk包版本version>=1.4.0中,我们内置了资源导出点集合的统一引入及使用。具体场景示例如下:

批量预加载资源

提前配置全部资源及所需的导出点信息

资源加载是个异步的过程,如果想要立即使用,须使用async/await执行资源管理器的.load()

import { GlobalLoaderManager, ILoadConfig } from "@cvte/resource-center-sdk";

const appName = "HOST_NAME";
const commonConfig: ILoadConfig = {
  useShared: true,
  mode: "currentPure",
};
GlobalLoaderManager.setLoaders([
  {
    appName,
    name: "RES_1_NAME",
    exposes: {
      RES_1_EXP_1_NAME: commonConfig,
    },
  },
  {
    appName,
    name: "RES_2_NAME",
    exposes: {
      RES_2_EXP_1_NAME: commonConfig,
      RES_2_EXP_2_NAME: {
        mode: "currentPure",
      },
    },
  },
]).load();

使用资源

在不同文件中使用已提前加载的资源导出内容

// fileA.ts
import { GlobalLoaderManager } from "@cvte/resource-center-sdk";

const res = GlobalLoaderManager.get("RES_1_NAME");
const { RES_1_EXP_1_NAME } = res;
console.log(RES_1_EXP_1_NAME); // 打印资源导出点的导出内容

// fileB.ts
import { GlobalLoaderManager } from "@cvte/resource-center-sdk";

const resExp = GlobalLoaderManager.get("RES_2_NAME", "RES_2_EXP_1_NAME");
console.log(resExp); // 打印资源导出点的导出内容

// fileC.ts
import { GlobalLoaderManager } from "@cvte/resource-center-sdk";

const resExps = GlobalLoaderManager.get("RES_2_NAME", [
  "RES_2_EXP_1_NAME",
  "RES_2_EXP_2_NAME",
]);
console.log(resExps); // 打印资源导出点集合的导出内容
/**
 * {
 *  RES_2_EXP_1_NAME: 对应导出点导出内容
 *  RES_2_EXP_2_NAME: 对应导出点导出内容
 * }
 */

资源共享上下文域

@cvte/resource-center-sdk包版本version>=1.5.0中,我们内置了指定资源共享上下文域并映射其共享模块的特性。具体场景示例如下:

宿主工程背景

宿主工程使用UMD特性,将一些全局的共享依赖或模块挂载在window对象中,并且名称做了一些修改,例如:

react在该宿主工程的window对象中挂载名为React,并且使用Module的方式直接导出,并没有安装esModule的方式采用default导出;

方案一 转换映射共享模块

将当前共享上下文域直接指向目标的共享依赖模块所在的上下文域,并且通过将资源的共享模块键名进行转换,以匹配新的共享上下文域。

此方案须开发者了解模块所需依赖的版本和目标共享上下文域中的键名;

import Loader, { ReactRemoteLoaderComponent } from '@cvte/resource-center-sdk';

const Component = ReactRemoteLoaderComponent<any,any>(
    new Loader({
      appName: '资源宿主对应在资源中心中的资源名称',    
      name: '资源名称可在资源管理系统中获得,具体操作可见下文【资源管理系统】',
      env: `${document.getElementById('ENV')?.getAttribute('value') as ILoaderResourceEnv}`, // 元素id名必须与server.js中injectData增加的环境变量参数名一致,加载对应环境下的资源,资源枚举的环境有【DEV,FAT,UAT,PRO】
    }),
    '导出名可在资源管理系统中查看,具体操作可见下文【资源管理系统】',
    {
      sharedScope: 'window',    // 指定共享上下文域,可选值有【'default' | 'window' | (() => any) | string】
      sharedTransfer:{    // 指定共享依赖模块的转换映射规则
        react:{
          key:'React',
          version:'17.0.2',    
          'isEager':true,
          transferer:(dep)=>({...dep,default:dep})    // 需要转换共享模块内容的方法;兼容CommonJS引入场景,增加default导出
        },
        'react-dom':{
          key:'ReactDOM',
          version:'17.0.2',
          'isEager':true,
          transferer:(dep)=>({...dep,default:dep})    // 需要转换共享模块内容的方法;兼容CommonJS引入场景,增加default导出
        },
        // antd:'antd',
        axios:'axios'
      },
      useShared: true,
      mode: 'page'
    }
  );

方案二 重构共享上下文域

将当前宿主工程的共享上下文域和期望指向的共享上下文域结合,并且直接在上下文域中转换目标共享域中的模块键名。

此方案须开发者了解模块所需依赖的版本和webpack模块联邦开发规则

// initSharedScope, loadSharedScope使用版本可见代码块下方说明
import Loader, { ReactRemoteLoaderComponent, initSharedScope, loadSharedScope } from '@cvte/resource-center-sdk';
import * as Mobx from 'mobx';

const Component = ReactRemoteLoaderComponent(
    new Loader({
      appName: 'qms',
      name: sourceName,
      env: 'dev'
    }),
    exportName,
    {
      sharedScope: async ()=>{
          // 获取window上下文
        const wScopeFn=new Function(`return window;`);
        const oriWScope=wScopeFn();
        // 获取宿主工程共享上下文域
        await loadSharedScope('default');
        const wpScope=initSharedScope('default');
        // 定向选择window上下文中的部分共享模块
        const wScope={
          react:{
            '17.0.2':{
              from:'qms',eager:true,loaded:1,
              get:()=>Promise.resolve(()=>({
                ...oriWScope['React'],
                default:oriWScope['React'],
              }))
            }
          },
          'react-dom':{
            '17.0.2':{
              from:'qms',eager:true,loaded:1,
              get:()=>Promise.resolve(()=>({
                ...oriWScope['ReactDOM'],
                default:oriWScope['ReactDOM'],
              }))
            }
          },
          mobx:{
            '17.0.2':{
              from:'qms',eager:true,loaded:1,
              get:()=>Promise.resolve(()=>({
                ...Mobx,
                default: Mobx,
              }))
            }
          },
        };
        // 组合成为新的共享上下文域进行
        const scope={
          ...wpScope,
          ...wScope
        };

        return scope;
      },
      useShared: true,
      mode: 'page'
    }
  );

initSharedScope,loadSharedScope工具方法在@cvte/resource-center-sdk1.5.1及其以上版本才有
针对1.5.0版本的开发者如有需要请自行升级至1.5.1

五、资源管理系统

访问地址:资源管理系统

可查看当前资源中心所有资源:

点击每一项前的编辑按钮可查看对应资源的详情

查看当前资源的导出内容:

作者:袁子涵  创建时间:2022-03-02 15:29
最后编辑:袁子涵  更新时间:2025-04-29 09:54