@cqsjjb/jjb-cloud-component 0.0.7 → 0.0.9

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.
@@ -1,176 +1,166 @@
1
- import React from 'react';
2
-
3
- import { tools } from '@cqsjjb/jjb-common-lib';
4
-
5
- import ImportCloudComponent from './import-cloud-component';
6
-
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React from 'react';
3
+ import ReactDOM from 'react-dom';
4
+ import * as jjbCommonLib from '@cqsjjb/jjb-common-lib';
5
+ import ImportCloudComponent from './import-cloud-component';
6
+
7
7
  /**
8
8
  * @description 卸载云组件样式
9
9
  * @param styleId {string} 样式id
10
- */
11
- export function useUnMountCloudComponentStyle(styleId) {
12
- const root = document.querySelector('head');
13
- const styled = root.querySelectorAll(`[data-cloud-component-style-id="${styleId}"]`);
14
- for (const style of styled) {
15
- root.removeChild(style);
16
- }
17
- }
18
-
10
+ */
11
+ export function useUnMountCloudComponentStyle(styleId) {
12
+ const root = document.querySelector('head');
13
+ const styled = root.querySelectorAll(`[data-cloud-component-style-id="${styleId}"]`);
14
+ for (const style of styled) {
15
+ root.removeChild(style);
16
+ }
17
+ }
18
+
19
19
  /**
20
20
  * @description 云组件
21
21
  * @param props {object} 组件props
22
22
  * @param props.dependencies {object} 自定义依赖项,会与默认依赖项合并
23
23
  * @note 默认内置依赖项:react, react-dom, @cqsjjb/jjb-common-lib
24
24
  * @note 用户自定义依赖项会覆盖同名的默认依赖项
25
- */
26
- export default function CloudComponent(props) {
27
- let styleId;
28
- const [ Component, setComponent ] = React.useState(null);
29
- const {
30
- from,
31
- cache,
32
- headers,
33
- dependencies = {},
34
- initialize,
35
- componentRef,
36
- componentKey,
37
- componentProps,
38
- onLoadStart,
39
- onLoadEnd,
40
- onDestroy,
41
- onMounted,
42
- onUpdated
43
- } = props;
44
-
45
- // 默认内置依赖项,所有云组件都可以使用
46
- const defaultDependencies = {
47
- 'react': require('react'),
48
- 'react-dom': require('react-dom'),
49
- '@cqsjjb/jjb-common-lib': require('@cqsjjb/jjb-common-lib')
50
- };
51
-
52
- // 合并默认依赖和用户自定义依赖,用户依赖优先级更高
53
- const mergedDependencies = React.useMemo(() => {
54
- return {
55
- ...defaultDependencies,
56
- ...dependencies
57
- };
58
- }, [dependencies]);
59
-
60
- // 使用 useMemo 来稳定化 mergedDependencies 引用,避免不必要的重新渲染
61
- const stableDependencies = React.useMemo(() => {
62
- return mergedDependencies;
63
- }, [mergedDependencies]);
64
-
65
- // 使用 useRef 来跟踪 dependencies 的变化,避免因对象引用变化导致的重新渲染
66
- const prevDependenciesRef = React.useRef();
67
- const shouldReloadDependencies = React.useMemo(() => {
68
- if (!prevDependenciesRef.current) {
69
- prevDependenciesRef.current = mergedDependencies;
70
- return true;
71
- }
72
-
73
- // 比较 dependencies 的键和值
74
- const prevKeys = Object.keys(prevDependenciesRef.current);
75
- const currentKeys = Object.keys(mergedDependencies);
76
-
77
- if (prevKeys.length !== currentKeys.length) {
78
- prevDependenciesRef.current = mergedDependencies;
79
- return true;
80
- }
81
-
82
- for (const key of currentKeys) {
83
- if (prevDependenciesRef.current[key] !== mergedDependencies[key]) {
84
- prevDependenciesRef.current = mergedDependencies;
85
- return true;
86
- }
87
- }
88
-
89
- return false;
90
- }, [mergedDependencies]);
91
-
92
- // 使用 useRef 来存储回调函数,避免因回调函数重新创建导致的重新渲染
93
- const onLoadStartRef = React.useRef(onLoadStart);
94
- const onLoadEndRef = React.useRef(onLoadEnd);
95
- const onDestroyRef = React.useRef(onDestroy);
96
-
97
- React.useEffect(() => {
98
- onLoadStartRef.current = onLoadStart;
99
- onLoadEndRef.current = onLoadEnd;
100
- onDestroyRef.current = onDestroy;
101
- });
102
-
103
- React.useEffect(() => {
104
- // 只有当 dependencies 真正发生变化时才重新加载
105
- if (!shouldReloadDependencies && prevDependenciesRef.current) {
106
- return;
107
- }
108
-
109
- async function load() {
110
- try {
111
- onLoadStartRef.current && onLoadStartRef.current();
112
- const {
113
- module,
114
- styleId: _styleId,
115
- isNewVersion
116
- } = await ImportCloudComponent({
117
- from,
118
- cache,
119
- headers,
120
- dependencies: stableDependencies
121
- });
122
-
123
- styleId = _styleId;
124
-
125
- setComponent(() => {
126
- onLoadEndRef.current && onLoadEndRef.current();
127
- return isNewVersion
128
- ? module.default({
129
- // 组件引用
130
- ref: componentRef,
131
- // 将依赖项穿透下去,用于在组件内部使用依赖项(支持云组件嵌套云组件)
132
- $$dependencies: stableDependencies
133
- })
134
- : module.default;
135
- });
136
- } catch (error) {
137
- console.error('云组件加载失败:', error);
138
- onLoadEndRef.current && onLoadEndRef.current();
139
- // 可以设置一个错误组件或显示错误信息
140
- setComponent(() => () => React.createElement('div', {
141
- style: { color: 'red', padding: '10px' }
142
- }, `组件加载失败: ${error.message}`));
143
- }
144
- }
145
-
146
- load().then(() => null);
147
-
148
- return () => {
149
- if (styleId) {
150
- useUnMountCloudComponentStyle(styleId);
151
- }
152
- onDestroyRef.current && onDestroyRef.current();
153
- };
154
- }, [from, cache, headers, shouldReloadDependencies]);
155
-
156
- // 使用 useMemo 来稳定化 componentProps,避免因对象重新创建导致的重新渲染
157
- const stableComponentProps = React.useMemo(() => {
158
- return {
159
- detail: { componentKey },
160
- ...tools.toObject(componentProps)
161
- };
162
- }, [componentKey, JSON.stringify(componentProps)]);
163
-
164
- // 使用 useMemo 来稳定化 initialize 函数
165
- const stableInitialize = React.useMemo(() => initialize, [initialize]);
166
-
167
- return Component && (
168
- <Component
169
- initialize={stableInitialize}
170
- {...stableComponentProps}
171
- onMounted={onMounted}
172
- onUpdated={onUpdated}
173
- />
174
- );
175
- }
176
-
25
+ */
26
+ export default function CloudComponent(props) {
27
+ let styleId;
28
+ const [Component, setComponent] = React.useState(null);
29
+ const {
30
+ from,
31
+ cache,
32
+ headers,
33
+ dependencies = {},
34
+ initialize,
35
+ componentRef,
36
+ componentKey,
37
+ componentProps,
38
+ onLoadStart,
39
+ onLoadEnd,
40
+ onDestroy,
41
+ onMounted,
42
+ onUpdated
43
+ } = props;
44
+
45
+ // 默认内置依赖项,所有云组件都可以使用
46
+ const defaultDependencies = {
47
+ 'react': React,
48
+ 'react-dom': ReactDOM,
49
+ 'jjbCommonLib': jjbCommonLib,
50
+ '@cqsjjb/jjb-common-lib': jjbCommonLib
51
+ };
52
+
53
+ // 合并默认依赖和用户自定义依赖,用户依赖优先级更高
54
+ const mergedDependencies = React.useMemo(() => {
55
+ return {
56
+ ...defaultDependencies,
57
+ ...dependencies
58
+ };
59
+ }, [dependencies]);
60
+
61
+ // 使用 useMemo 来稳定化 mergedDependencies 引用,避免不必要的重新渲染
62
+ const stableDependencies = React.useMemo(() => {
63
+ return mergedDependencies;
64
+ }, [mergedDependencies]);
65
+
66
+ // 使用 useRef 来跟踪 dependencies 的变化,避免因对象引用变化导致的重新渲染
67
+ const prevDependenciesRef = React.useRef();
68
+ const shouldReloadDependencies = React.useMemo(() => {
69
+ if (!prevDependenciesRef.current) {
70
+ prevDependenciesRef.current = mergedDependencies;
71
+ return true;
72
+ }
73
+
74
+ // 比较 dependencies 的键和值
75
+ const prevKeys = Object.keys(prevDependenciesRef.current);
76
+ const currentKeys = Object.keys(mergedDependencies);
77
+ if (prevKeys.length !== currentKeys.length) {
78
+ prevDependenciesRef.current = mergedDependencies;
79
+ return true;
80
+ }
81
+ for (const key of currentKeys) {
82
+ if (prevDependenciesRef.current[key] !== mergedDependencies[key]) {
83
+ prevDependenciesRef.current = mergedDependencies;
84
+ return true;
85
+ }
86
+ }
87
+ return false;
88
+ }, [mergedDependencies]);
89
+
90
+ // 使用 useRef 来存储回调函数,避免因回调函数重新创建导致的重新渲染
91
+ const onLoadStartRef = React.useRef(onLoadStart);
92
+ const onLoadEndRef = React.useRef(onLoadEnd);
93
+ const onDestroyRef = React.useRef(onDestroy);
94
+ React.useEffect(() => {
95
+ onLoadStartRef.current = onLoadStart;
96
+ onLoadEndRef.current = onLoadEnd;
97
+ onDestroyRef.current = onDestroy;
98
+ });
99
+ React.useEffect(() => {
100
+ // 只有当 dependencies 真正发生变化时才重新加载
101
+ if (!shouldReloadDependencies && prevDependenciesRef.current) {
102
+ return;
103
+ }
104
+ async function load() {
105
+ try {
106
+ onLoadStartRef.current && onLoadStartRef.current();
107
+ const {
108
+ module,
109
+ styleId: _styleId,
110
+ isNewVersion
111
+ } = await ImportCloudComponent({
112
+ from,
113
+ cache,
114
+ headers,
115
+ dependencies: stableDependencies
116
+ });
117
+ styleId = _styleId;
118
+ setComponent(() => {
119
+ onLoadEndRef.current && onLoadEndRef.current();
120
+ return isNewVersion ? module.default({
121
+ // 组件引用
122
+ ref: componentRef,
123
+ // 将依赖项穿透下去,用于在组件内部使用依赖项(支持云组件嵌套云组件)
124
+ $$dependencies: stableDependencies
125
+ }) : module.default;
126
+ });
127
+ } catch (error) {
128
+ console.error('云组件加载失败:', error);
129
+ onLoadEndRef.current && onLoadEndRef.current();
130
+ // 可以设置一个错误组件或显示错误信息
131
+ setComponent(() => () => /*#__PURE__*/React.createElement('div', {
132
+ style: {
133
+ color: 'red',
134
+ padding: '10px'
135
+ }
136
+ }, `组件加载失败: ${error.message}`));
137
+ }
138
+ }
139
+ load().then(() => null);
140
+ return () => {
141
+ if (styleId) {
142
+ useUnMountCloudComponentStyle(styleId);
143
+ }
144
+ onDestroyRef.current && onDestroyRef.current();
145
+ };
146
+ }, [from, cache, headers, shouldReloadDependencies]);
147
+
148
+ // 使用 useMemo 来稳定化 componentProps,避免因对象重新创建导致的重新渲染
149
+ const stableComponentProps = React.useMemo(() => {
150
+ return {
151
+ detail: {
152
+ componentKey
153
+ },
154
+ ...jjbCommonLib.tools.toObject(componentProps)
155
+ };
156
+ }, [componentKey, JSON.stringify(componentProps)]);
157
+
158
+ // 使用 useMemo 来稳定化 initialize 函数
159
+ const stableInitialize = React.useMemo(() => initialize, [initialize]);
160
+ return Component && /*#__PURE__*/React.createElement(Component, _extends({
161
+ initialize: stableInitialize
162
+ }, stableComponentProps, {
163
+ onMounted: onMounted,
164
+ onUpdated: onUpdated
165
+ }));
166
+ }
@@ -1,35 +1,35 @@
1
- import { tools } from '@cqsjjb/jjb-common-lib';
2
-
1
+ import { tools } from '@cqsjjb/jjb-common-lib';
2
+
3
3
  /**
4
4
  * @description 生成CJS运行环境
5
5
  * @param {string} from 云组件地址
6
6
  * @param {string} code 注入云组件代码
7
- */
8
- export function genCommonJSRuntime({
9
- from
10
- }, code) {
11
- const styleId = tools.createOnlyKey();
12
- return {
13
- styleId,
14
- useModule: new Function(`
15
- /* cloud-component-assets: ${from} */
16
- const module = { exports: null };
17
- const exports = {};
18
- const require = id => {
19
- try {
20
- return arguments[0][id];
21
- } catch (error) {
22
- throw new Error("云组件依赖[" + id + "]不存在!请检查dependencies配置!");
23
- }
24
- };
25
- /* cloud-component-code */
26
- ${code.replace(/\{cloudComponentStyleId\}/g, styleId)}
27
- /* cloud-component-code */
28
- return Object.assign(module.exports, exports);
29
- `)
30
- };
31
- }
32
-
7
+ */
8
+ export function genCommonJSRuntime({
9
+ from
10
+ }, code) {
11
+ const styleId = tools.createOnlyKey();
12
+ return {
13
+ styleId,
14
+ useModule: new Function(`
15
+ /* cloud-component-assets: ${from} */
16
+ const module = { exports: null };
17
+ const exports = {};
18
+ const require = id => {
19
+ try {
20
+ return arguments[0][id];
21
+ } catch (error) {
22
+ throw new Error("云组件依赖[" + id + "]不存在!请检查dependencies配置!");
23
+ }
24
+ };
25
+ /* cloud-component-code */
26
+ ${code.replace(/\{cloudComponentStyleId\}/g, styleId)}
27
+ /* cloud-component-code */
28
+ return Object.assign(module.exports, exports);
29
+ `)
30
+ };
31
+ }
32
+
33
33
  /**
34
34
  * @description 手动加载模块
35
35
  * @param options {{ from: string, cache: string, headers: {} }}
@@ -40,83 +40,73 @@ export function genCommonJSRuntime({
40
40
  * console.log(res);
41
41
  * });
42
42
  * @return {Promise<{ module: { info: {}, default:() => React.Component }, styleId: string }>}
43
- */
44
- export default async function ImportCloudComponent(options) {
45
- const from = options.from;
46
- const dependencies = options.dependencies || {};
47
- const cache = options.cache || 'force-cache';
48
- const headers = tools.toObject(options.headers);
49
-
50
- let isNewVersion = true;
51
-
52
- if (!from) {
53
- throw Error('云组件资源访问地址不能为空!');
54
- }
55
-
56
- let response;
57
- let responseText;
58
-
59
- try {
60
- response = await fetch(from, {
61
- cache,
62
- headers
63
- });
64
-
65
- if (!response.ok) {
66
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
67
- }
68
-
69
- responseText = await response.text();
70
- } catch (error) {
71
- throw new Error(`云组件加载失败: ${error.message}`);
72
- }
73
- const __dependencies = {};
74
-
75
- Object.entries(dependencies).forEach(([key, value]) => {
76
- __dependencies[key] = value;
77
- });
78
-
79
- let module;
80
- let styleId;
81
- let useModule;
82
-
83
- try {
84
- const runtime = genCommonJSRuntime({
85
- from
86
- }, responseText);
87
-
88
- styleId = runtime.styleId;
89
- useModule = runtime.useModule;
90
-
91
- // 获取云组件导出CJS模块
92
- module = useModule(__dependencies);
93
-
94
- if (!module || typeof module !== 'object') {
95
- throw new Error('云组件模块格式错误');
96
- }
97
- } catch (error) {
98
- throw new Error(`云组件解析失败: ${error.message}`);
99
- }
100
-
101
- // 获取云组件info变量
102
- const { info } = module;
103
- // 判断当前云组件是否导出了info变量
104
- if (tools.isUndefined(info)) {
105
- if (process.env.NODE_ENV === 'development') {
106
- console.warn(`云组件 "${from}" 不存在"info"配置,疑似旧版云组件或配置错误`);
107
- }
108
- isNewVersion = false;
109
- } else {
110
- if (process.env.NODE_ENV === 'development') {
111
- console.log(`云组件 [${info.name}] 加载完成!`);
112
- }
113
- }
114
-
115
- // 返回组件CSJ模块
116
- return {
117
- module,
118
- styleId,
119
- isNewVersion
120
- };
121
- }
122
-
43
+ */
44
+ export default async function ImportCloudComponent(options) {
45
+ const from = options.from;
46
+ const dependencies = options.dependencies || {};
47
+ const cache = options.cache || 'force-cache';
48
+ const headers = tools.toObject(options.headers);
49
+ let isNewVersion = true;
50
+ if (!from) {
51
+ throw Error('云组件资源访问地址不能为空!');
52
+ }
53
+ let response;
54
+ let responseText;
55
+ try {
56
+ response = await fetch(from, {
57
+ cache,
58
+ headers
59
+ });
60
+ if (!response.ok) {
61
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
62
+ }
63
+ responseText = await response.text();
64
+ } catch (error) {
65
+ throw new Error(`云组件加载失败: ${error.message}`);
66
+ }
67
+ const __dependencies = {};
68
+ Object.entries(dependencies).forEach(([key, value]) => {
69
+ __dependencies[key] = value;
70
+ });
71
+ let module;
72
+ let styleId;
73
+ let useModule;
74
+ try {
75
+ const runtime = genCommonJSRuntime({
76
+ from
77
+ }, responseText);
78
+ styleId = runtime.styleId;
79
+ useModule = runtime.useModule;
80
+
81
+ // 获取云组件导出CJS模块
82
+ module = useModule(__dependencies);
83
+ if (!module || typeof module !== 'object') {
84
+ throw new Error('云组件模块格式错误');
85
+ }
86
+ } catch (error) {
87
+ throw new Error(`云组件解析失败: ${error.message}`);
88
+ }
89
+
90
+ // 获取云组件info变量
91
+ const {
92
+ info
93
+ } = module;
94
+ // 判断当前云组件是否导出了info变量
95
+ if (tools.isUndefined(info)) {
96
+ if (process.env.NODE_ENV === 'development') {
97
+ console.warn(`云组件 "${from}" 不存在"info"配置,疑似旧版云组件或配置错误`);
98
+ }
99
+ isNewVersion = false;
100
+ } else {
101
+ if (process.env.NODE_ENV === 'development') {
102
+ console.log(`云组件 [${info.name}] 加载完成!`);
103
+ }
104
+ }
105
+
106
+ // 返回组件CSJ模块
107
+ return {
108
+ module,
109
+ styleId,
110
+ isNewVersion
111
+ };
112
+ }
package/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { default as CloudComponent, useUnMountCloudComponentStyle } from './cloud-component';
2
- export { default as ImportCloudComponent, genCommonJSRuntime } from './import-cloud-component';
1
+ export { default as CloudComponent, useUnMountCloudComponentStyle } from './cloud-component';
2
+ export { default as ImportCloudComponent, 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.7",
3
+ "version": "0.0.9",
4
4
  "description": "前端-云组件",
5
5
  "main": "index.js",
6
6
  "scripts": {