@modern-js/plugin-garfish 2.68.12 → 2.68.13-alpha.1

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.
@@ -41,6 +41,7 @@ const ENTRY_BOOTSTRAP_FILE_NAME = "bootstrap.jsx";
41
41
  const generateCode = async (entrypoints, appContext, config, hooks) => {
42
42
  const { mountId } = config.html;
43
43
  const { enableAsyncEntry } = config.source;
44
+ const { disableComponentCompat } = typeof config.deploy.microFrontend === "object" ? config.deploy.microFrontend : {};
44
45
  const { internalDirectory, internalSrcAlias, metaName, srcDirectory } = appContext;
45
46
  await Promise.all(entrypoints.map(async (entrypoint) => {
46
47
  const { entryName, isAutoMount, entry, customEntry, customBootstrap } = entrypoint;
@@ -58,7 +59,8 @@ const generateCode = async (entrypoints, appContext, config, hooks) => {
58
59
  customEntry,
59
60
  customBootstrap,
60
61
  mountId,
61
- appendCode
62
+ appendCode,
63
+ disableComponentCompat
62
64
  });
63
65
  const indexFile = import_path.default.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
64
66
  import_utils.fs.outputFileSync(indexFile, indexCode, "utf8");
@@ -22,7 +22,7 @@ __export(template_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(template_exports);
24
24
  var import_utils = require("@modern-js/utils");
25
- const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId }) => customEntry ? `import '${(0, import_utils.formatImportPath)(entry.replace(srcDirectory, internalSrcAlias))}'
25
+ const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId, disableComponentCompat }) => customEntry ? `import '${(0, import_utils.formatImportPath)(entry.replace(srcDirectory, internalSrcAlias))}'
26
26
  export * from '${(0, import_utils.formatImportPath)(entry.replace(srcDirectory, internalSrcAlias))}'` : `import { createRoot } from '@${metaName}/runtime/react';
27
27
  import { render } from '@${metaName}/runtime/browser';
28
28
  import { isRenderGarfish, createProvider } from '@${metaName}/plugin-garfish/tools';
@@ -32,9 +32,9 @@ if (!isRenderGarfish()) {
32
32
  ${customBootstrap ? `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));` : `render(<ModernRoot />, '${mountId || "root"}');`};
33
33
  }
34
34
 
35
- export const provider = createProvider('${mountId || "root"}', { customBootstrap });
35
+ export const provider = createProvider('${mountId || "root"}', { customBootstrap, disableComponentCompat: ${disableComponentCompat} });
36
36
  `;
37
- const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode = [] }) => `import '@${metaName}/runtime/registry/${entryName}';
37
+ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode = [], disableComponentCompat }) => `import '@${metaName}/runtime/registry/${entryName}';
38
38
  ${genRenderCode({
39
39
  srcDirectory,
40
40
  internalSrcAlias,
@@ -42,7 +42,8 @@ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, cus
42
42
  entry,
43
43
  customEntry,
44
44
  customBootstrap,
45
- mountId
45
+ mountId,
46
+ disableComponentCompat
46
47
  })}
47
48
  ${appendCode.join("\n")}
48
49
  `;
@@ -29,9 +29,23 @@ function generateRootDom(dom, id) {
29
29
  const mountNode = dom ? dom.querySelector(`#${id}`) || dom : document.getElementById(id);
30
30
  return mountNode;
31
31
  }
32
- function createProvider(id, { customBootstrap, beforeRender } = {}) {
32
+ function createProvider(id, { customBootstrap, beforeRender, disableComponentCompat } = {}) {
33
33
  return ({ basename, dom }) => {
34
34
  let root = null;
35
+ const SubModuleComponent = disableComponentCompat ? null : (props) => {
36
+ const ModernRoot = (0, import_react.createRoot)(null);
37
+ return /* @__PURE__ */ (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModernRoot, {
38
+ basename,
39
+ ...props
40
+ }), dom.querySelector(`#${id || "root"}`) || dom);
41
+ };
42
+ const jupiter_submodule_app_key = disableComponentCompat ? null : (props) => {
43
+ const ModernRoot = (0, import_react.createRoot)(null);
44
+ return /* @__PURE__ */ (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModernRoot, {
45
+ basename,
46
+ ...props
47
+ }), dom.querySelector(`#${id || "root"}`) || dom);
48
+ };
35
49
  return {
36
50
  async render({ basename: basename2, dom: dom2, props, appName }) {
37
51
  const ModernRoot = (0, import_react.createRoot)(null);
@@ -68,20 +82,8 @@ function createProvider(id, { customBootstrap, beforeRender } = {}) {
68
82
  }
69
83
  },
70
84
  // 兼容旧版本
71
- SubModuleComponent: (props) => {
72
- const ModernRoot = (0, import_react.createRoot)(null);
73
- return /* @__PURE__ */ (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModernRoot, {
74
- basename,
75
- ...props
76
- }), dom.querySelector(`#${id || "root"}`) || dom);
77
- },
78
- jupiter_submodule_app_key: (props) => {
79
- const ModernRoot = (0, import_react.createRoot)(null);
80
- return /* @__PURE__ */ (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ModernRoot, {
81
- basename,
82
- ...props
83
- }), dom.querySelector(`#${id || "root"}`) || dom);
84
- }
85
+ SubModuleComponent,
86
+ jupiter_submodule_app_key
85
87
  };
86
88
  };
87
89
  }
@@ -64,6 +64,8 @@ function getAppInstance(options, appInfo, manifest) {
64
64
  const [{ component: SubModuleComponent }, setSubModuleComponent] = (0, import_react.useState)({
65
65
  component: null
66
66
  });
67
+ const destroyRef = (0, import_react.useRef)(null);
68
+ const isMountedRef = (0, import_react.useRef)(true);
67
69
  const context = (0, import_react.useContext)(import_runtime.RuntimeReactContext);
68
70
  var _props_useRouteMatch;
69
71
  const useRouteMatch = (_props_useRouteMatch = props.useRouteMatch) !== null && _props_useRouteMatch !== void 0 ? _props_useRouteMatch : context === null || context === void 0 ? void 0 : (_context_router = context.router) === null || _context_router === void 0 ? void 0 : _context_router.useRouteMatch;
@@ -127,6 +129,11 @@ or directly pass the "basename":
127
129
  ]);
128
130
  (0, import_react.useEffect)(() => {
129
131
  const { setLoadingState, ...userProps } = props;
132
+ const safeSetLoadingState = (state) => {
133
+ if (isMountedRef.current) {
134
+ setLoadingState(state);
135
+ }
136
+ };
130
137
  const loadAppOptions = {
131
138
  cache: true,
132
139
  insulationVariable: [
@@ -144,6 +151,26 @@ or directly pass the "basename":
144
151
  const { render, destroy, SubModuleComponent: SubModuleComponent2, jupiter_submodule_app_key } = provider;
145
152
  const SubComponent = SubModuleComponent2 || jupiter_submodule_app_key;
146
153
  const componetRenderMode = manifest === null || manifest === void 0 ? void 0 : manifest.componentRender;
154
+ if (destroy) {
155
+ destroyRef.current = () => {
156
+ const dom = document.getElementById(domId);
157
+ if (dom) {
158
+ const destroyProps = {
159
+ dom,
160
+ basename,
161
+ appName: appInfo.name,
162
+ appRenderInfo: {},
163
+ props: {
164
+ ...appInfo.props,
165
+ ...userProps
166
+ }
167
+ };
168
+ destroy.apply(provider, [
169
+ destroyProps
170
+ ]);
171
+ }
172
+ };
173
+ }
147
174
  return {
148
175
  mount: (...props2) => {
149
176
  if (componetRenderMode && SubComponent) {
@@ -166,7 +193,7 @@ or directly pass the "basename":
166
193
  };
167
194
  }
168
195
  };
169
- setLoadingState({
196
+ safeSetLoadingState({
170
197
  isLoading: true,
171
198
  error: null
172
199
  });
@@ -180,7 +207,7 @@ or directly pass the "basename":
180
207
  throw new Error(`MicroApp Garfish.loadApp "${appInfo.name}" result is null`);
181
208
  }
182
209
  appRef.current = appInstance;
183
- setLoadingState({
210
+ safeSetLoadingState({
184
211
  isLoading: false
185
212
  });
186
213
  if (appInstance.mounted && appInstance.appInfo.cache) {
@@ -197,7 +224,7 @@ or directly pass the "basename":
197
224
  await (appInstance === null || appInstance === void 0 ? void 0 : appInstance.mount());
198
225
  }
199
226
  } catch (error) {
200
- setLoadingState({
227
+ safeSetLoadingState({
201
228
  isLoading: true,
202
229
  error
203
230
  });
@@ -205,6 +232,7 @@ or directly pass the "basename":
205
232
  }
206
233
  renderApp();
207
234
  return () => {
235
+ isMountedRef.current = false;
208
236
  if (appRef.current) {
209
237
  const { appInfo: appInfo2 } = appRef.current;
210
238
  if (appInfo2.cache) {
@@ -219,6 +247,20 @@ or directly pass the "basename":
219
247
  }
220
248
  };
221
249
  }, []);
250
+ (0, import_react.useEffect)(() => {
251
+ return () => {
252
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
253
+ (0, import_util.logger)("MicroApp SubModuleComponent cleanup");
254
+ try {
255
+ destroyRef.current();
256
+ } catch (error) {
257
+ (0, import_util.logger)("Error during SubModuleComponent cleanup:", error);
258
+ }
259
+ }
260
+ };
261
+ }, [
262
+ SubModuleComponent
263
+ ]);
222
264
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
223
265
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
224
266
  id: domId,
@@ -1,4 +1,5 @@
1
1
  import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
2
+ import { _ as _type_of } from "@swc/helpers/_/_type_of";
2
3
  import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
3
4
  import path from "path";
4
5
  import { fs } from "@modern-js/utils";
@@ -8,12 +9,13 @@ var ENTRY_POINT_FILE_NAME = "index.jsx";
8
9
  var ENTRY_BOOTSTRAP_FILE_NAME = "bootstrap.jsx";
9
10
  var generateCode = function() {
10
11
  var _ref = _async_to_generator(function(entrypoints, appContext, config, hooks) {
11
- var mountId, enableAsyncEntry, internalDirectory, internalSrcAlias, metaName, srcDirectory;
12
+ var mountId, enableAsyncEntry, disableComponentCompat, internalDirectory, internalSrcAlias, metaName, srcDirectory;
12
13
  return _ts_generator(this, function(_state) {
13
14
  switch (_state.label) {
14
15
  case 0:
15
16
  mountId = config.html.mountId;
16
17
  enableAsyncEntry = config.source.enableAsyncEntry;
18
+ disableComponentCompat = (_type_of(config.deploy.microFrontend) === "object" ? config.deploy.microFrontend : {}).disableComponentCompat;
17
19
  internalDirectory = appContext.internalDirectory, internalSrcAlias = appContext.internalSrcAlias, metaName = appContext.metaName, srcDirectory = appContext.srcDirectory;
18
20
  return [
19
21
  4,
@@ -43,7 +45,8 @@ var generateCode = function() {
43
45
  customEntry,
44
46
  customBootstrap,
45
47
  mountId,
46
- appendCode
48
+ appendCode,
49
+ disableComponentCompat
47
50
  });
48
51
  indexFile = path.resolve(internalDirectory, "./".concat(entryName, "/").concat(ENTRY_POINT_FILE_NAME));
49
52
  fs.outputFileSync(indexFile, indexCode, "utf8");
@@ -1,10 +1,10 @@
1
1
  import { formatImportPath } from "@modern-js/utils";
2
2
  var genRenderCode = function(param) {
3
- var srcDirectory = param.srcDirectory, internalSrcAlias = param.internalSrcAlias, metaName = param.metaName, entry = param.entry, customEntry = param.customEntry, customBootstrap = param.customBootstrap, mountId = param.mountId;
4
- return customEntry ? "import '".concat(formatImportPath(entry.replace(srcDirectory, internalSrcAlias)), "'\nexport * from '").concat(formatImportPath(entry.replace(srcDirectory, internalSrcAlias)), "'") : "import { createRoot } from '@".concat(metaName, "/runtime/react';\nimport { render } from '@").concat(metaName, "/runtime/browser';\nimport { isRenderGarfish, createProvider } from '@").concat(metaName, "/plugin-garfish/tools';\n").concat(customBootstrap ? "import customBootstrap from '".concat(formatImportPath(customBootstrap.replace(srcDirectory, internalSrcAlias)), "';") : "let customBootstrap;", "\nif (!isRenderGarfish()) {\n const ModernRoot = createRoot();\n ").concat(customBootstrap ? "customBootstrap(ModernRoot, () => render(<ModernRoot />, '".concat(mountId || "root", "'));") : "render(<ModernRoot />, '".concat(mountId || "root", "');"), ";\n}\n\nexport const provider = createProvider('").concat(mountId || "root", "', { customBootstrap });\n");
3
+ var srcDirectory = param.srcDirectory, internalSrcAlias = param.internalSrcAlias, metaName = param.metaName, entry = param.entry, customEntry = param.customEntry, customBootstrap = param.customBootstrap, mountId = param.mountId, disableComponentCompat = param.disableComponentCompat;
4
+ return customEntry ? "import '".concat(formatImportPath(entry.replace(srcDirectory, internalSrcAlias)), "'\nexport * from '").concat(formatImportPath(entry.replace(srcDirectory, internalSrcAlias)), "'") : "import { createRoot } from '@".concat(metaName, "/runtime/react';\nimport { render } from '@").concat(metaName, "/runtime/browser';\nimport { isRenderGarfish, createProvider } from '@").concat(metaName, "/plugin-garfish/tools';\n").concat(customBootstrap ? "import customBootstrap from '".concat(formatImportPath(customBootstrap.replace(srcDirectory, internalSrcAlias)), "';") : "let customBootstrap;", "\nif (!isRenderGarfish()) {\n const ModernRoot = createRoot();\n ").concat(customBootstrap ? "customBootstrap(ModernRoot, () => render(<ModernRoot />, '".concat(mountId || "root", "'));") : "render(<ModernRoot />, '".concat(mountId || "root", "');"), ";\n}\n\nexport const provider = createProvider('").concat(mountId || "root", "', { customBootstrap, disableComponentCompat: ").concat(disableComponentCompat, " });\n");
5
5
  };
6
6
  var index = function(param) {
7
- var srcDirectory = param.srcDirectory, internalSrcAlias = param.internalSrcAlias, metaName = param.metaName, entry = param.entry, entryName = param.entryName, customEntry = param.customEntry, customBootstrap = param.customBootstrap, mountId = param.mountId, _param_appendCode = param.appendCode, appendCode = _param_appendCode === void 0 ? [] : _param_appendCode;
7
+ var srcDirectory = param.srcDirectory, internalSrcAlias = param.internalSrcAlias, metaName = param.metaName, entry = param.entry, entryName = param.entryName, customEntry = param.customEntry, customBootstrap = param.customBootstrap, mountId = param.mountId, _param_appendCode = param.appendCode, appendCode = _param_appendCode === void 0 ? [] : _param_appendCode, disableComponentCompat = param.disableComponentCompat;
8
8
  return "import '@".concat(metaName, "/runtime/registry/").concat(entryName, "';\n ").concat(genRenderCode({
9
9
  srcDirectory,
10
10
  internalSrcAlias,
@@ -12,7 +12,8 @@ var index = function(param) {
12
12
  entry,
13
13
  customEntry,
14
14
  customBootstrap,
15
- mountId
15
+ mountId,
16
+ disableComponentCompat
16
17
  }), "\n ").concat(appendCode.join("\n"), "\n ");
17
18
  };
18
19
  export {
@@ -10,10 +10,22 @@ function generateRootDom(dom, id) {
10
10
  return mountNode;
11
11
  }
12
12
  function createProvider(id) {
13
- var _ref = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, customBootstrap = _ref.customBootstrap, beforeRender = _ref.beforeRender;
13
+ var _ref = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {}, customBootstrap = _ref.customBootstrap, beforeRender = _ref.beforeRender, disableComponentCompat = _ref.disableComponentCompat;
14
14
  return function(param) {
15
15
  var basename = param.basename, dom = param.dom;
16
16
  var root = null;
17
+ var SubModuleComponent = disableComponentCompat ? null : function(props) {
18
+ var ModernRoot = createRoot(null);
19
+ return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, _object_spread({
20
+ basename
21
+ }, props)), dom.querySelector("#".concat(id || "root")) || dom);
22
+ };
23
+ var jupiter_submodule_app_key = disableComponentCompat ? null : function(props) {
24
+ var ModernRoot = createRoot(null);
25
+ return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, _object_spread({
26
+ basename
27
+ }, props)), dom.querySelector("#".concat(id || "root")) || dom);
28
+ };
17
29
  return {
18
30
  render: function render1(param2) {
19
31
  var basename2 = param2.basename, dom2 = param2.dom, props = param2.props, appName = param2.appName;
@@ -91,18 +103,8 @@ function createProvider(id) {
91
103
  }
92
104
  },
93
105
  // 兼容旧版本
94
- SubModuleComponent: function(props) {
95
- var ModernRoot = createRoot(null);
96
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, _object_spread({
97
- basename
98
- }, props)), dom.querySelector("#".concat(id || "root")) || dom);
99
- },
100
- jupiter_submodule_app_key: function(props) {
101
- var ModernRoot = createRoot(null);
102
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, _object_spread({
103
- basename
104
- }, props)), dom.querySelector("#".concat(id || "root")) || dom);
105
- }
106
+ SubModuleComponent,
107
+ jupiter_submodule_app_key
106
108
  };
107
109
  };
108
110
  }
@@ -40,6 +40,8 @@ function getAppInstance(options, appInfo, manifest) {
40
40
  var _useState = _sliced_to_array(useState({
41
41
  component: null
42
42
  }), 2), _useState_ = _useState[0], SubModuleComponent = _useState_.component, setSubModuleComponent = _useState[1];
43
+ var destroyRef = useRef(null);
44
+ var isMountedRef = useRef(true);
43
45
  var context = useContext(RuntimeReactContext);
44
46
  var _props_useRouteMatch;
45
47
  var useRouteMatch = (_props_useRouteMatch = props.useRouteMatch) !== null && _props_useRouteMatch !== void 0 ? _props_useRouteMatch : context === null || context === void 0 ? void 0 : (_context_router = context.router) === null || _context_router === void 0 ? void 0 : _context_router.useRouteMatch;
@@ -106,6 +108,11 @@ or directly pass the "basename":
106
108
  var setLoadingState = props.setLoadingState, userProps = _object_without_properties(props, [
107
109
  "setLoadingState"
108
110
  ]);
111
+ var safeSetLoadingState = function(state) {
112
+ if (isMountedRef.current) {
113
+ setLoadingState(state);
114
+ }
115
+ };
109
116
  var loadAppOptions = _object_spread_props(_object_spread({
110
117
  cache: true,
111
118
  insulationVariable: _to_consumable_array(appInfo.insulationVariable || []).concat([
@@ -119,6 +126,23 @@ or directly pass the "basename":
119
126
  var render = provider.render, destroy = provider.destroy, SubModuleComponent2 = provider.SubModuleComponent, jupiter_submodule_app_key = provider.jupiter_submodule_app_key;
120
127
  var SubComponent = SubModuleComponent2 || jupiter_submodule_app_key;
121
128
  var componetRenderMode = manifest === null || manifest === void 0 ? void 0 : manifest.componentRender;
129
+ if (destroy) {
130
+ destroyRef.current = function() {
131
+ var dom = document.getElementById(domId);
132
+ if (dom) {
133
+ var destroyProps = {
134
+ dom,
135
+ basename,
136
+ appName: appInfo.name,
137
+ appRenderInfo: {},
138
+ props: _object_spread({}, appInfo.props, userProps)
139
+ };
140
+ destroy.apply(provider, [
141
+ destroyProps
142
+ ]);
143
+ }
144
+ };
145
+ }
122
146
  return {
123
147
  mount: function() {
124
148
  for (var _len = arguments.length, _$props = new Array(_len), _key = 0; _key < _len; _key++) {
@@ -147,7 +171,7 @@ or directly pass the "basename":
147
171
  };
148
172
  }
149
173
  });
150
- setLoadingState({
174
+ safeSetLoadingState({
151
175
  isLoading: true,
152
176
  error: null
153
177
  });
@@ -176,7 +200,7 @@ or directly pass the "basename":
176
200
  throw new Error('MicroApp Garfish.loadApp "'.concat(appInfo.name, '" result is null'));
177
201
  }
178
202
  appRef.current = appInstance;
179
- setLoadingState({
203
+ safeSetLoadingState({
180
204
  isLoading: false
181
205
  });
182
206
  if (!(appInstance.mounted && appInstance.appInfo.cache))
@@ -217,7 +241,7 @@ or directly pass the "basename":
217
241
  ];
218
242
  case 6:
219
243
  error = _state.sent();
220
- setLoadingState({
244
+ safeSetLoadingState({
221
245
  isLoading: true,
222
246
  error
223
247
  });
@@ -236,6 +260,7 @@ or directly pass the "basename":
236
260
  }
237
261
  renderApp();
238
262
  return function() {
263
+ isMountedRef.current = false;
239
264
  if (appRef.current) {
240
265
  var _$appInfo = appRef.current.appInfo;
241
266
  if (_$appInfo.cache) {
@@ -250,6 +275,20 @@ or directly pass the "basename":
250
275
  }
251
276
  };
252
277
  }, []);
278
+ useEffect(function() {
279
+ return function() {
280
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
281
+ logger("MicroApp SubModuleComponent cleanup");
282
+ try {
283
+ destroyRef.current();
284
+ } catch (error) {
285
+ logger("Error during SubModuleComponent cleanup:", error);
286
+ }
287
+ }
288
+ };
289
+ }, [
290
+ SubModuleComponent
291
+ ]);
253
292
  return /* @__PURE__ */ _jsx(_Fragment, {
254
293
  children: /* @__PURE__ */ _jsx("div", {
255
294
  id: domId,
@@ -7,6 +7,7 @@ const ENTRY_BOOTSTRAP_FILE_NAME = "bootstrap.jsx";
7
7
  const generateCode = async (entrypoints, appContext, config, hooks) => {
8
8
  const { mountId } = config.html;
9
9
  const { enableAsyncEntry } = config.source;
10
+ const { disableComponentCompat } = typeof config.deploy.microFrontend === "object" ? config.deploy.microFrontend : {};
10
11
  const { internalDirectory, internalSrcAlias, metaName, srcDirectory } = appContext;
11
12
  await Promise.all(entrypoints.map(async (entrypoint) => {
12
13
  const { entryName, isAutoMount, entry, customEntry, customBootstrap } = entrypoint;
@@ -24,7 +25,8 @@ const generateCode = async (entrypoints, appContext, config, hooks) => {
24
25
  customEntry,
25
26
  customBootstrap,
26
27
  mountId,
27
- appendCode
28
+ appendCode,
29
+ disableComponentCompat
28
30
  });
29
31
  const indexFile = path.resolve(internalDirectory, `./${entryName}/${ENTRY_POINT_FILE_NAME}`);
30
32
  fs.outputFileSync(indexFile, indexCode, "utf8");
@@ -1,5 +1,5 @@
1
1
  import { formatImportPath } from "@modern-js/utils";
2
- const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId }) => customEntry ? `import '${formatImportPath(entry.replace(srcDirectory, internalSrcAlias))}'
2
+ const genRenderCode = ({ srcDirectory, internalSrcAlias, metaName, entry, customEntry, customBootstrap, mountId, disableComponentCompat }) => customEntry ? `import '${formatImportPath(entry.replace(srcDirectory, internalSrcAlias))}'
3
3
  export * from '${formatImportPath(entry.replace(srcDirectory, internalSrcAlias))}'` : `import { createRoot } from '@${metaName}/runtime/react';
4
4
  import { render } from '@${metaName}/runtime/browser';
5
5
  import { isRenderGarfish, createProvider } from '@${metaName}/plugin-garfish/tools';
@@ -9,9 +9,9 @@ if (!isRenderGarfish()) {
9
9
  ${customBootstrap ? `customBootstrap(ModernRoot, () => render(<ModernRoot />, '${mountId || "root"}'));` : `render(<ModernRoot />, '${mountId || "root"}');`};
10
10
  }
11
11
 
12
- export const provider = createProvider('${mountId || "root"}', { customBootstrap });
12
+ export const provider = createProvider('${mountId || "root"}', { customBootstrap, disableComponentCompat: ${disableComponentCompat} });
13
13
  `;
14
- const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode = [] }) => `import '@${metaName}/runtime/registry/${entryName}';
14
+ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode = [], disableComponentCompat }) => `import '@${metaName}/runtime/registry/${entryName}';
15
15
  ${genRenderCode({
16
16
  srcDirectory,
17
17
  internalSrcAlias,
@@ -19,7 +19,8 @@ const index = ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, cus
19
19
  entry,
20
20
  customEntry,
21
21
  customBootstrap,
22
- mountId
22
+ mountId,
23
+ disableComponentCompat
23
24
  })}
24
25
  ${appendCode.join("\n")}
25
26
  `;
@@ -6,9 +6,23 @@ function generateRootDom(dom, id) {
6
6
  const mountNode = dom ? dom.querySelector(`#${id}`) || dom : document.getElementById(id);
7
7
  return mountNode;
8
8
  }
9
- function createProvider(id, { customBootstrap, beforeRender } = {}) {
9
+ function createProvider(id, { customBootstrap, beforeRender, disableComponentCompat } = {}) {
10
10
  return ({ basename, dom }) => {
11
11
  let root = null;
12
+ const SubModuleComponent = disableComponentCompat ? null : (props) => {
13
+ const ModernRoot = createRoot(null);
14
+ return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, {
15
+ basename,
16
+ ...props
17
+ }), dom.querySelector(`#${id || "root"}`) || dom);
18
+ };
19
+ const jupiter_submodule_app_key = disableComponentCompat ? null : (props) => {
20
+ const ModernRoot = createRoot(null);
21
+ return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, {
22
+ basename,
23
+ ...props
24
+ }), dom.querySelector(`#${id || "root"}`) || dom);
25
+ };
12
26
  return {
13
27
  async render({ basename: basename2, dom: dom2, props, appName }) {
14
28
  const ModernRoot = createRoot(null);
@@ -45,20 +59,8 @@ function createProvider(id, { customBootstrap, beforeRender } = {}) {
45
59
  }
46
60
  },
47
61
  // 兼容旧版本
48
- SubModuleComponent: (props) => {
49
- const ModernRoot = createRoot(null);
50
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, {
51
- basename,
52
- ...props
53
- }), dom.querySelector(`#${id || "root"}`) || dom);
54
- },
55
- jupiter_submodule_app_key: (props) => {
56
- const ModernRoot = createRoot(null);
57
- return /* @__PURE__ */ createPortal(/* @__PURE__ */ _jsx(ModernRoot, {
58
- basename,
59
- ...props
60
- }), dom.querySelector(`#${id || "root"}`) || dom);
61
- }
62
+ SubModuleComponent,
63
+ jupiter_submodule_app_key
62
64
  };
63
65
  };
64
66
  }
@@ -30,6 +30,8 @@ function getAppInstance(options, appInfo, manifest) {
30
30
  const [{ component: SubModuleComponent }, setSubModuleComponent] = useState({
31
31
  component: null
32
32
  });
33
+ const destroyRef = useRef(null);
34
+ const isMountedRef = useRef(true);
33
35
  const context = useContext(RuntimeReactContext);
34
36
  var _props_useRouteMatch;
35
37
  const useRouteMatch = (_props_useRouteMatch = props.useRouteMatch) !== null && _props_useRouteMatch !== void 0 ? _props_useRouteMatch : context === null || context === void 0 ? void 0 : (_context_router = context.router) === null || _context_router === void 0 ? void 0 : _context_router.useRouteMatch;
@@ -93,6 +95,11 @@ or directly pass the "basename":
93
95
  ]);
94
96
  useEffect(() => {
95
97
  const { setLoadingState, ...userProps } = props;
98
+ const safeSetLoadingState = (state) => {
99
+ if (isMountedRef.current) {
100
+ setLoadingState(state);
101
+ }
102
+ };
96
103
  const loadAppOptions = {
97
104
  cache: true,
98
105
  insulationVariable: [
@@ -110,6 +117,26 @@ or directly pass the "basename":
110
117
  const { render, destroy, SubModuleComponent: SubModuleComponent2, jupiter_submodule_app_key } = provider;
111
118
  const SubComponent = SubModuleComponent2 || jupiter_submodule_app_key;
112
119
  const componetRenderMode = manifest === null || manifest === void 0 ? void 0 : manifest.componentRender;
120
+ if (destroy) {
121
+ destroyRef.current = () => {
122
+ const dom = document.getElementById(domId);
123
+ if (dom) {
124
+ const destroyProps = {
125
+ dom,
126
+ basename,
127
+ appName: appInfo.name,
128
+ appRenderInfo: {},
129
+ props: {
130
+ ...appInfo.props,
131
+ ...userProps
132
+ }
133
+ };
134
+ destroy.apply(provider, [
135
+ destroyProps
136
+ ]);
137
+ }
138
+ };
139
+ }
113
140
  return {
114
141
  mount: (...props2) => {
115
142
  if (componetRenderMode && SubComponent) {
@@ -132,7 +159,7 @@ or directly pass the "basename":
132
159
  };
133
160
  }
134
161
  };
135
- setLoadingState({
162
+ safeSetLoadingState({
136
163
  isLoading: true,
137
164
  error: null
138
165
  });
@@ -146,7 +173,7 @@ or directly pass the "basename":
146
173
  throw new Error(`MicroApp Garfish.loadApp "${appInfo.name}" result is null`);
147
174
  }
148
175
  appRef.current = appInstance;
149
- setLoadingState({
176
+ safeSetLoadingState({
150
177
  isLoading: false
151
178
  });
152
179
  if (appInstance.mounted && appInstance.appInfo.cache) {
@@ -163,7 +190,7 @@ or directly pass the "basename":
163
190
  await (appInstance === null || appInstance === void 0 ? void 0 : appInstance.mount());
164
191
  }
165
192
  } catch (error) {
166
- setLoadingState({
193
+ safeSetLoadingState({
167
194
  isLoading: true,
168
195
  error
169
196
  });
@@ -171,6 +198,7 @@ or directly pass the "basename":
171
198
  }
172
199
  renderApp();
173
200
  return () => {
201
+ isMountedRef.current = false;
174
202
  if (appRef.current) {
175
203
  const { appInfo: appInfo2 } = appRef.current;
176
204
  if (appInfo2.cache) {
@@ -185,6 +213,20 @@ or directly pass the "basename":
185
213
  }
186
214
  };
187
215
  }, []);
216
+ useEffect(() => {
217
+ return () => {
218
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
219
+ logger("MicroApp SubModuleComponent cleanup");
220
+ try {
221
+ destroyRef.current();
222
+ } catch (error) {
223
+ logger("Error during SubModuleComponent cleanup:", error);
224
+ }
225
+ }
226
+ };
227
+ }, [
228
+ SubModuleComponent
229
+ ]);
188
230
  return /* @__PURE__ */ _jsx(_Fragment, {
189
231
  children: /* @__PURE__ */ _jsx("div", {
190
232
  id: domId,
@@ -1,4 +1,4 @@
1
- export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode, }: {
1
+ export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry, entryName, customEntry, customBootstrap, mountId, appendCode, disableComponentCompat, }: {
2
2
  srcDirectory: string;
3
3
  internalSrcAlias: string;
4
4
  metaName: string;
@@ -8,4 +8,5 @@ export declare const index: ({ srcDirectory, internalSrcAlias, metaName, entry,
8
8
  customBootstrap?: string | false;
9
9
  mountId?: string;
10
10
  appendCode?: string[];
11
+ disableComponentCompat?: boolean;
11
12
  }) => string;
@@ -1,8 +1,9 @@
1
1
  import { type RenderFunc } from '@meta/runtime/browser';
2
2
  import type { Root } from 'react-dom/client';
3
- export declare function createProvider(id?: string, { customBootstrap, beforeRender, }?: {
3
+ export declare function createProvider(id?: string, { customBootstrap, beforeRender, disableComponentCompat, }?: {
4
4
  customBootstrap?: (App: React.ComponentType, render: RenderFunc) => Promise<HTMLElement | Root>;
5
5
  beforeRender?: (App: React.ComponentType, props?: Record<string, any>) => Promise<any>;
6
+ disableComponentCompat?: boolean;
6
7
  }): ({ basename, dom }: {
7
8
  basename: string;
8
9
  dom: HTMLElement;
@@ -16,6 +17,6 @@ export declare function createProvider(id?: string, { customBootstrap, beforeRen
16
17
  destroy({ dom }: {
17
18
  dom: HTMLElement;
18
19
  }): void;
19
- SubModuleComponent: (props: any) => import("react").ReactPortal;
20
- jupiter_submodule_app_key: (props: any) => import("react").ReactPortal;
20
+ SubModuleComponent: ((props: any) => import("react").ReactPortal) | null;
21
+ jupiter_submodule_app_key: ((props: any) => import("react").ReactPortal) | null;
21
22
  };
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.68.12",
18
+ "version": "2.68.13-alpha.1",
19
19
  "jsnext:source": "./src/cli/index.ts",
20
20
  "types": "./dist/types/cli/index.d.ts",
21
21
  "typesVersions": {
@@ -93,13 +93,13 @@
93
93
  "react-dom": "^18.3.1",
94
94
  "react-router-dom": "6.27.0",
95
95
  "typescript": "^5",
96
- "@modern-js/app-tools": "2.68.12",
97
- "@modern-js/core": "2.68.12",
98
96
  "@modern-js/runtime": "2.68.12",
99
- "@modern-js/plugin-router-v5": "2.68.12",
100
- "@modern-js/types": "2.68.12",
101
97
  "@scripts/build": "2.66.0",
102
- "@scripts/jest-config": "2.66.0"
98
+ "@modern-js/types": "2.68.12",
99
+ "@modern-js/app-tools": "2.68.12",
100
+ "@scripts/jest-config": "2.66.0",
101
+ "@modern-js/plugin-router-v5": "2.68.12",
102
+ "@modern-js/core": "2.68.12"
103
103
  },
104
104
  "sideEffects": false,
105
105
  "publishConfig": {