@cqsjjb/jjb-cloud-component 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # ImportCloudComponent
2
+
3
+ 手动导入云组件
4
+
5
+ ## 何时使用
6
+
7
+ 需要提前预加载、批量加载云组件等场景时使用
8
+
9
+ ## 代码演示
10
+
11
+ ```jsx
12
+ import { useEffect } from 'react';
13
+ import { ImportCloudComponent } from '@cqsjjb/jjb-cloud-component';
14
+
15
+ function App() {
16
+ useEffect(() => {
17
+ ImportCloudComponent({
18
+ lib: '__coreLib',
19
+ from: 'https://xxx.xxx.xx/index.js'
20
+ }).then(m => {
21
+ // m
22
+ });
23
+ }, []);
24
+ }
25
+ ```
26
+
27
+ ## 参数
28
+
29
+ | 属性 | 说明 | 类型 | 默认值 |
30
+ |---------|:----------|:-----------------------------------------------------------------------:|----------:|
31
+ | from | 云组件资源链接 | `string` | - |
32
+ | lib | 云组件依赖库变量 | `string` | `coreLib` |
33
+ | cache | 云组件资源缓存策略 | `default` `force-cache` `no-cache` `no-store` `only-if-cached` `reload` | `default` |
34
+ | headers | 请求头 | `Record<string, any>` | - |
35
+
36
+ ## 返回值
37
+
38
+ | 属性 | 说明 | 类型 | 默认值 |
39
+ |--------------|:------------------------------------------------------|:---------:|----:|
40
+ | styleId | 样式id,云组件加载时,自动判断内部是否有自定义样式,如果有内部自定义添加到head元素上,并返回样式ID | `string` | - |
41
+ | isNewVersion | 是否是新版云组件模板开发的云组件 | `boolean` | - |
42
+ | module | 加载成功返回的组件模块 | `IModule` | - |
43
+
44
+ ## IModule
45
+
46
+ | 属性 | 说明 | 类型 | 默认值 |
47
+ |-------------------|:-------|:-----------------:|----:|
48
+ | info.name | 组件的名称 | `string` | - |
49
+ | info.remark | 组件说明 | `string` | - |
50
+ | info.version | 组件版本 | `string` | - |
51
+ | info.description | 组件描述 | `string` | - |
52
+ | info.environment | 组件环境 | `string` | - |
53
+ | info.dependencies | 组件依赖清单 | `string` | - |
54
+ | default | 组件本体 | `React.Component` | - |
55
+
56
+ ## FAQ
57
+ * 在底座中加载云组件报:Error: Minified React error #321
58
+ 这个错误通常是应用ReactDOM渲染了分别来自不同React构建的DOM树,简单来说就是存在两个React库。由于云组件默认使用__coreLib依赖变量,当你的云组件加载时可能用到其他应用的__coreLib,解决办法是把应用main.js中的__coreLib改成唯一变量名,例如:__coreUserLib,然后修改云组件的lib属性即可。
59
+ ```jsx
60
+ <CloudComponent lib="__coreUserLib" />
61
+
62
+ * 组件"XX"不存在"info"配置,疑似旧版云组件或配置错误
63
+ 这个警告通常是使用了旧版云组件或链接不是云组件导致。
64
+ * 需要"XX"依赖,请在"window.XX"中提供此依赖!
65
+ 这个错误只有新版云组件才会有,通常是应用依赖变量(__coreLib)不匹配云组件的依赖清单,请请检查!注意应用依赖变量的键名必须与云组件的依赖清单键名一致,否则会报错!
66
+ 云组件
67
+ ```text
68
+ // src/jjb.config.json
69
+ { dependencies: { 'react': 'react', 'react-dom': 'react-dom' } }
70
+ ```
71
+ 应用
72
+ ```js
73
+ // src/main.js
74
+ window.__coreLib = {
75
+ 'react': require('react'),
76
+ 'react-dom': require('react-dom')
77
+ }
78
+ ```
@@ -1,19 +1,24 @@
1
1
  // @ts-ignore
2
2
  import * as React from 'react';
3
- import type I_ImportCloudComponent from './import-cloud-component';
4
3
 
5
4
  interface ComponentProps {
6
5
  ref?: React.Ref<{ [ p: string ]: any }>;
7
6
  children?: React.ReactNode;
8
7
  }
9
8
 
9
+ /**
10
+ * @description 卸载云组件样式
11
+ * @param styleId {string} 样式id
12
+ */
13
+ export function useUnMountCloudComponentStyle (styleId: string): void;
14
+
10
15
  interface CloudComponentProps extends ComponentProps {
11
16
  // 云组件依赖库变量
12
- lib: string;
17
+ lib?: string;
13
18
  // 组件资源地址
14
19
  from: string;
15
20
  // 缓存
16
- cache?: string;
21
+ cache?: 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload';
17
22
  // 请求头
18
23
  headers?: {};
19
24
  // 是否需要初始化更新settings和dataSource
@@ -46,4 +51,4 @@ interface CloudComponentFc extends React.FC<CloudComponentProps> {
46
51
  }
47
52
 
48
53
  declare const CloudComponent: CloudComponentFc;
49
- declare const ImportCloudComponent: typeof I_ImportCloudComponent;
54
+ export default CloudComponent;
@@ -4,7 +4,11 @@ import { tools } from '@cqsjjb/jjb-common-lib';
4
4
 
5
5
  import ImportCloudComponent from './import-cloud-component';
6
6
 
7
- function unMountCloudComponentStyle(styleId) {
7
+ /**
8
+ * @description 卸载云组件样式
9
+ * @param styleId {string} 样式id
10
+ */
11
+ export function useUnMountCloudComponentStyle(styleId) {
8
12
  const root = document.querySelector('head');
9
13
  const styled = root.querySelectorAll(`[data-cloud-component-style-id="${styleId}"]`);
10
14
  for (const style of styled) {
@@ -12,6 +16,10 @@ function unMountCloudComponentStyle(styleId) {
12
16
  }
13
17
  }
14
18
 
19
+ /**
20
+ * @description 云组件
21
+ * @param props {object} 组件props
22
+ */
15
23
  export default function CloudComponent(props) {
16
24
  let styleId;
17
25
  const [ Component, setComponent ] = React.useState(null);
@@ -35,7 +43,8 @@ export default function CloudComponent(props) {
35
43
  onLoadStart && onLoadStart();
36
44
  const {
37
45
  module,
38
- styleId: _styleId
46
+ styleId: _styleId,
47
+ isNewVersion
39
48
  } = await ImportCloudComponent({
40
49
  lib,
41
50
  from,
@@ -47,14 +56,16 @@ export default function CloudComponent(props) {
47
56
 
48
57
  setComponent(() => {
49
58
  onLoadEnd && onLoadEnd();
50
- return module.default();
59
+ return isNewVersion
60
+ ? module.default()
61
+ : module.default;
51
62
  });
52
63
  }
53
64
 
54
65
  load().then(() => null);
55
66
 
56
67
  return () => {
57
- unMountCloudComponentStyle(styleId);
68
+ useUnMountCloudComponentStyle(styleId);
58
69
  onDestroy && onDestroy();
59
70
  };
60
71
  }, []);
@@ -1,17 +1,15 @@
1
1
  // @ts-ignore
2
2
  import React from 'react';
3
3
 
4
- declare function ImportCloudComponent (options: {
5
- // 组件依赖库变量
6
- lib?: string;
7
- // 组件地址
8
- from: string;
9
- // 缓存
10
- cache?: string;
11
- // 请求头
12
- headers?: {}
13
- }): {
4
+ /**
5
+ * @description 云组件模块
6
+ */
7
+ type CloudModule = {
8
+ // 样式id
14
9
  styleId: string;
10
+ // 是否是新版云组件
11
+ isNewVersion: boolean;
12
+ // 组件模块
15
13
  module: {
16
14
  // 组件信息
17
15
  info: {
@@ -31,6 +29,52 @@ declare function ImportCloudComponent (options: {
31
29
  // 组件本体
32
30
  default: () => React.Component
33
31
  }
34
- }
32
+ };
33
+
34
+ /**
35
+ * @description 依赖检测
36
+ * @param lib {string} 依赖变量
37
+ * @param name {string} 依赖名称
38
+ * @return {boolean}
39
+ */
40
+ declare function checkDependence (lib: string, name: string): boolean;
41
+
42
+ /**
43
+ * @description 依赖检测
44
+ * @param lib {string} 依赖变量
45
+ * @param dependencies {string[]} 依赖名称
46
+ * @return {Array<{ name: string, check: boolean }>}
47
+ */
48
+ declare function checkDependencies (lib: string, dependencies: string[]): Array<{ name: string, check: boolean }>
49
+
50
+ /**
51
+ * @description 生成CJS运行环境
52
+ * @param options {string} 依赖变量
53
+ * @param code {string} 依赖名称
54
+ * @return {CloudModule}
55
+ */
56
+ declare function genCommonJSRuntime (options: { lib: string, from: string }, code: string): CloudModule;
57
+
58
+ /**
59
+ * @description 导入云组件
60
+ * @param options {string} 依赖变量
61
+ * @return {Promise<CloudModule>}
62
+ */
63
+ declare function ImportCloudComponent (options: {
64
+ // 组件依赖库变量
65
+ lib?: string;
66
+ // 组件地址
67
+ from: string;
68
+ // 缓存
69
+ cache?: 'default' | 'force-cache' | 'no-cache' | 'no-store' | 'only-if-cached' | 'reload';
70
+ // 请求头
71
+ headers?: {}
72
+ }): Promise<CloudModule>
35
73
 
36
74
  export default ImportCloudComponent;
75
+
76
+ export {
77
+ checkDependence,
78
+ checkDependencies,
79
+ genCommonJSRuntime
80
+ };
@@ -1,25 +1,18 @@
1
1
  import { tools } from '@cqsjjb/jjb-common-lib';
2
2
 
3
- /**
4
- * @description 优化依赖变量
5
- * @param name {string} 依赖变量名
6
- * @return {*|string}
7
- */
8
- function ansLibField(name) {
9
- return name.indexOf('.') !== -1
10
- ? name
11
- : `.${name}`;
3
+ function resolveLib(lib) {
4
+ if (typeof window.proxy !== 'undefined' && lib.indexOf('base') === -1) {
5
+ return genFieldPath(`window.proxy.${lib}`);
6
+ } else {
7
+ return genFieldPath(`window.${lib}`);
8
+ }
12
9
  }
13
10
 
14
- /**
15
- * @description 给地址加随机字符串
16
- * @param url {string} 地址
17
- * @return {string}
18
- */
19
- function fromURL(url) {
20
- return `${url}${url.indexOf('?') !== -1
21
- ? '&'
22
- : '?'}v=${new Date().getTime()}`;
11
+ function genFieldPath(field) {
12
+ return field
13
+ .split('.')
14
+ .filter(Boolean)
15
+ .join('.');
23
16
  }
24
17
 
25
18
  /**
@@ -28,7 +21,7 @@ function fromURL(url) {
28
21
  * @param {string} from 云组件地址
29
22
  * @param {string} code 注入云组件代码
30
23
  */
31
- function genCommonJSRuntime({
24
+ export function genCommonJSRuntime({
32
25
  lib,
33
26
  from
34
27
  }, code) {
@@ -40,7 +33,12 @@ function genCommonJSRuntime({
40
33
  const module = { exports: null };
41
34
  const exports = {};
42
35
  const require = function (id) {
43
- return window${ansLibField(lib)}[ id ];
36
+ const find = ${resolveLib(lib)}[ id ];
37
+ if (find) {
38
+ return find;
39
+ } else {
40
+ throw Error('云组件使用依赖失败,请确认"['+ id +']"是否在${resolveLib(lib)}中?');
41
+ }
44
42
  };
45
43
  /* cloud-component-code */
46
44
  ${code.replace(/\{cloudComponentStyleId\}/g, styleId)}
@@ -50,18 +48,14 @@ function genCommonJSRuntime({
50
48
  };
51
49
  }
52
50
 
53
- function print(msg) {
54
- return `[ImportCloudComponent]: ${msg}`;
55
- }
56
-
57
51
  /**
58
52
  * @description 宿主环境依赖检测
59
53
  * @param lib {string} 依赖变量
60
54
  * @param name {string} 依赖名称
61
55
  * @return {boolean}
62
56
  */
63
- function checkDependence(lib, name) {
64
- const dependencies = new Function(`return window${ansLibField(lib)}`)();
57
+ export function checkDependence(lib, name) {
58
+ const dependencies = new Function(`return ${resolveLib(lib)}`)();
65
59
  return tools.isUndefined(dependencies[ name ]);
66
60
  }
67
61
 
@@ -69,14 +63,13 @@ function checkDependence(lib, name) {
69
63
  * @description 依赖检测
70
64
  * @param lib {string}
71
65
  * @param dependencies {string[]}
72
- * @param isProxy {boolean}
73
66
  * @return {Array<{ name: string, check: boolean }>}
74
67
  */
75
- function checkDependencies(lib, dependencies, isProxy) {
68
+ export function checkDependencies(lib, dependencies) {
76
69
  return Object.keys(dependencies).map(name => {
77
70
  return {
78
71
  name,
79
- check: checkDependence(lib, name, isProxy)
72
+ check: checkDependence(lib, name)
80
73
  };
81
74
  }).filter(i => i.check);
82
75
  }
@@ -85,67 +78,71 @@ function checkDependencies(lib, dependencies, isProxy) {
85
78
  * @description 手动加载模块
86
79
  * @param options {{ from: string, lib: string, cache: string, headers: {} }}
87
80
  * @example
88
- * Import({
81
+ * ImportCloudComponent({
89
82
  * from: 'https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.min.js'
90
83
  * }).then(res => {
91
84
  * console.log(res);
92
85
  * });
93
86
  * @return {Promise<{ module: { info: {}, default:() => React.Component }, styleId: string }>}
94
87
  */
95
- export default function ImportCloudComponent(options) {
96
- const lib = typeof window.proxy === 'undefined' ? `${options.lib || '__coreLib'}` : `.proxy.${options.lib || '__coreLib'}`;
88
+ export default async function ImportCloudComponent(options) {
89
+ const lib = options.lib || '__coreLib';
97
90
  const from = options.from;
98
91
 
99
92
  const cache = options.cache || 'force-cache';
100
93
  const headers = tools.toObject(options.headers);
101
94
 
95
+ let isNewVersion = true;
96
+
102
97
  if (!from) {
103
- throw Error(print('云组件资源访问地址不能为空!'));
98
+ throw Error('云组件资源访问地址不能为空!');
104
99
  }
105
100
 
106
- return fetch(from, {
101
+ const response = await fetch(from, {
107
102
  cache,
108
103
  headers
109
- })
110
- .then(response => response.text())
111
- .then(response => {
112
- const {
113
- styleId,
114
- useModule
115
- } = genCommonJSRuntime({
116
- lib,
117
- from
118
- }, response);
119
- // 获取云组件导出CJS模块
120
- const module = useModule();
121
- // 获取云组件info变量
122
- const { info } = module;
123
- // 判断当前云组件是否导出了info变量
124
- if (tools.isUndefined(info)) {
125
- throw Error(print(`${from} 缺少info变量导出, 无法获知此组件的基本信息, 请在组件包入口处导出组件的info变量!`));
126
- }
127
- // 获取云组件的基本信息
128
- const {
129
- name,
130
- dependencies
131
- } = info;
132
- // 判断云组件是否有依赖配置
133
- if (!tools.isEmptyObject(dependencies)) {
134
- // 是否存在未安装的依赖项
135
- const noInstallDependencies = checkDependencies(lib, dependencies);
136
- // 判断是否有
137
- if (tools.isValidArray(noInstallDependencies)) {
138
- throw Error(print(`${name} 需要${noInstallDependencies.at(0).name}依赖, 请在window.${lib}中提供此依赖!`));
139
- }
104
+ });
105
+ const responseText = await response.text();
106
+
107
+ const {
108
+ styleId,
109
+ useModule
110
+ } = genCommonJSRuntime({
111
+ lib,
112
+ from
113
+ }, responseText);
114
+ // 获取云组件导出CJS模块
115
+ const module = useModule();
116
+ // 获取云组件info变量
117
+ const { info } = module;
118
+ // 判断当前云组件是否导出了info变量
119
+ if (tools.isUndefined(info)) {
120
+ window[ 'console' ][ 'warn' ](`组件 "${from}" 不存在"info"配置,疑似旧版云组件或配置错误`);
121
+ isNewVersion = false;
122
+ } else {
123
+ // 获取云组件的基本信息
124
+ const {
125
+ name,
126
+ dependencies
127
+ } = info;
128
+ // 判断云组件是否有依赖配置
129
+ if (!tools.isEmptyObject(dependencies)) {
130
+ // 是否存在未安装的依赖项
131
+ const noInstallDependencies = checkDependencies(lib, dependencies);
132
+ // 判断是否有
133
+ if (tools.isValidArray(noInstallDependencies)) {
134
+ throw Error(`"${name}" 需要"${noInstallDependencies.at(0).name}"依赖,请在"${resolveLib(lib)}"中提供此依赖!`);
140
135
  }
136
+ }
141
137
 
142
- console.log(print(`${module.info.name} 加载完成!`));
138
+ window[ 'console' ][ 'log' ](`云组件 [${info.name}] 加载完成!`);
139
+ }
143
140
 
144
- // 返回组件CSJ模块
145
- return {
146
- module,
147
- styleId
148
- };
149
- });
141
+ // 返回组件CSJ模块
142
+ return {
143
+ module,
144
+ styleId,
145
+ isNewVersion
146
+ };
150
147
  }
151
148
 
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { default as CloudComponent, useUnMountCloudComponentStyle } from './cloud-component';
2
+ export { default as ImportCloudComponent, checkDependence, checkDependencies, genCommonJSRuntime } from './import-cloud-component';
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { default as CloudComponent } from './cloud-component';
2
- export { default as ImportCloudComponent } from './import-cloud-component';
1
+ export { default as CloudComponent, useUnMountCloudComponentStyle } from './cloud-component';
2
+ export { default as ImportCloudComponent, checkDependence, checkDependencies, genCommonJSRuntime } from './import-cloud-component';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cqsjjb/jjb-cloud-component",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "前端-云组件",
5
5
  "main": "index.js",
6
6
  "scripts": {