@modern-js/plugin-garfish 2.68.13-alpha.0 → 2.68.13-alpha.2

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.
@@ -29,7 +29,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  var apps_exports = {};
30
30
  __export(apps_exports, {
31
31
  generateApps: () => generateApps,
32
- pathJoin: () => pathJoin
32
+ pathJoin: () => pathJoin,
33
+ useMicroAppMountStatus: () => useMicroAppMountStatus
33
34
  });
34
35
  module.exports = __toCommonJS(apps_exports);
35
36
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -38,6 +39,13 @@ var import_garfish = __toESM(require("garfish"));
38
39
  var import_react = require("react");
39
40
  var import_util = require("../../util");
40
41
  var import_loadable = require("../loadable");
42
+ const MicroAppMountContext = /* @__PURE__ */ (0, import_react.createContext)({
43
+ isMounted: true
44
+ });
45
+ const useMicroAppMountStatus = () => {
46
+ const { isMounted } = (0, import_react.useContext)(MicroAppMountContext);
47
+ return isMounted;
48
+ };
41
49
  function pathJoin(...args) {
42
50
  const res = args.reduce((res2, path) => {
43
51
  let nPath = path;
@@ -65,6 +73,8 @@ function getAppInstance(options, appInfo, manifest) {
65
73
  component: null
66
74
  });
67
75
  const destroyRef = (0, import_react.useRef)(null);
76
+ const isMountedRef = (0, import_react.useRef)(true);
77
+ const abortControllerRef = (0, import_react.useRef)(null);
68
78
  const context = (0, import_react.useContext)(import_runtime.RuntimeReactContext);
69
79
  var _props_useRouteMatch;
70
80
  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;
@@ -128,6 +138,13 @@ or directly pass the "basename":
128
138
  ]);
129
139
  (0, import_react.useEffect)(() => {
130
140
  const { setLoadingState, ...userProps } = props;
141
+ abortControllerRef.current = new AbortController();
142
+ const safeSetLoadingState = (state) => {
143
+ var _abortControllerRef_current;
144
+ if (isMountedRef.current && !((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted)) {
145
+ setLoadingState(state);
146
+ }
147
+ };
131
148
  const loadAppOptions = {
132
149
  cache: true,
133
150
  insulationVariable: [
@@ -168,9 +185,11 @@ or directly pass the "basename":
168
185
  return {
169
186
  mount: (...props2) => {
170
187
  if (componetRenderMode && SubComponent) {
171
- setSubModuleComponent({
172
- component: SubComponent
173
- });
188
+ if (isMountedRef.current) {
189
+ setSubModuleComponent({
190
+ component: SubComponent
191
+ });
192
+ }
174
193
  return void 0;
175
194
  } else {
176
195
  (0, import_util.logger)("MicroApp customer render", props2);
@@ -187,7 +206,7 @@ or directly pass the "basename":
187
206
  };
188
207
  }
189
208
  };
190
- setLoadingState({
209
+ safeSetLoadingState({
191
210
  isLoading: true,
192
211
  error: null
193
212
  });
@@ -196,12 +215,19 @@ or directly pass the "basename":
196
215
  });
197
216
  async function renderApp() {
198
217
  try {
218
+ var _abortControllerRef_current, _abortControllerRef_current1;
219
+ if ((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted) {
220
+ return;
221
+ }
199
222
  const appInstance = await import_garfish.default.loadApp(appInfo.name, loadAppOptions);
223
+ if ((_abortControllerRef_current1 = abortControllerRef.current) === null || _abortControllerRef_current1 === void 0 ? void 0 : _abortControllerRef_current1.signal.aborted) {
224
+ return;
225
+ }
200
226
  if (!appInstance) {
201
227
  throw new Error(`MicroApp Garfish.loadApp "${appInfo.name}" result is null`);
202
228
  }
203
229
  appRef.current = appInstance;
204
- setLoadingState({
230
+ safeSetLoadingState({
205
231
  isLoading: false
206
232
  });
207
233
  if (appInstance.mounted && appInstance.appInfo.cache) {
@@ -218,14 +244,21 @@ or directly pass the "basename":
218
244
  await (appInstance === null || appInstance === void 0 ? void 0 : appInstance.mount());
219
245
  }
220
246
  } catch (error) {
221
- setLoadingState({
222
- isLoading: true,
223
- error
224
- });
247
+ var _abortControllerRef_current2;
248
+ if (!((_abortControllerRef_current2 = abortControllerRef.current) === null || _abortControllerRef_current2 === void 0 ? void 0 : _abortControllerRef_current2.signal.aborted)) {
249
+ safeSetLoadingState({
250
+ isLoading: true,
251
+ error
252
+ });
253
+ }
225
254
  }
226
255
  }
227
256
  renderApp();
228
257
  return () => {
258
+ isMountedRef.current = false;
259
+ if (abortControllerRef.current) {
260
+ abortControllerRef.current.abort();
261
+ }
229
262
  if (appRef.current) {
230
263
  const { appInfo: appInfo2 } = appRef.current;
231
264
  if (appInfo2.cache) {
@@ -242,7 +275,7 @@ or directly pass the "basename":
242
275
  }, []);
243
276
  (0, import_react.useEffect)(() => {
244
277
  return () => {
245
- if (SubModuleComponent && destroyRef.current) {
278
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
246
279
  (0, import_util.logger)("MicroApp SubModuleComponent cleanup");
247
280
  try {
248
281
  destroyRef.current();
@@ -254,12 +287,26 @@ or directly pass the "basename":
254
287
  }, [
255
288
  SubModuleComponent
256
289
  ]);
290
+ const SafeSubModuleComponent = (0, import_react.useCallback)(() => {
291
+ if (!SubModuleComponent || !isMountedRef.current) {
292
+ return null;
293
+ }
294
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MicroAppMountContext.Provider, {
295
+ value: {
296
+ isMounted: isMountedRef.current
297
+ },
298
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SubModuleComponent, {
299
+ ...props
300
+ })
301
+ });
302
+ }, [
303
+ SubModuleComponent,
304
+ props
305
+ ]);
257
306
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {
258
307
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
259
308
  id: domId,
260
- children: SubModuleComponent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SubModuleComponent, {
261
- ...props
262
- })
309
+ children: SubModuleComponent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SafeSubModuleComponent, {})
263
310
  })
264
311
  });
265
312
  }
@@ -281,5 +328,6 @@ function generateApps(options, manifest) {
281
328
  // Annotate the CommonJS export names for ESM import in node:
282
329
  0 && (module.exports = {
283
330
  generateApps,
284
- pathJoin
331
+ pathJoin,
332
+ useMicroAppMountStatus
285
333
  });
@@ -8,9 +8,16 @@ import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
8
8
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
9
9
  import { RuntimeReactContext } from "@meta/runtime";
10
10
  import Garfish from "garfish";
11
- import { useContext, useEffect, useRef, useState } from "react";
11
+ import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
12
12
  import { generateSubAppContainerKey, logger } from "../../util";
13
13
  import { Loadable } from "../loadable";
14
+ var MicroAppMountContext = /* @__PURE__ */ createContext({
15
+ isMounted: true
16
+ });
17
+ var useMicroAppMountStatus = function() {
18
+ var isMounted = useContext(MicroAppMountContext).isMounted;
19
+ return isMounted;
20
+ };
14
21
  function pathJoin() {
15
22
  for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
16
23
  args[_key] = arguments[_key];
@@ -41,6 +48,8 @@ function getAppInstance(options, appInfo, manifest) {
41
48
  component: null
42
49
  }), 2), _useState_ = _useState[0], SubModuleComponent = _useState_.component, setSubModuleComponent = _useState[1];
43
50
  var destroyRef = useRef(null);
51
+ var isMountedRef = useRef(true);
52
+ var abortControllerRef = useRef(null);
44
53
  var context = useContext(RuntimeReactContext);
45
54
  var _props_useRouteMatch;
46
55
  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;
@@ -107,6 +116,13 @@ or directly pass the "basename":
107
116
  var setLoadingState = props.setLoadingState, userProps = _object_without_properties(props, [
108
117
  "setLoadingState"
109
118
  ]);
119
+ abortControllerRef.current = new AbortController();
120
+ var safeSetLoadingState = function(state) {
121
+ var _abortControllerRef_current;
122
+ if (isMountedRef.current && !((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted)) {
123
+ setLoadingState(state);
124
+ }
125
+ };
110
126
  var loadAppOptions = _object_spread_props(_object_spread({
111
127
  cache: true,
112
128
  insulationVariable: _to_consumable_array(appInfo.insulationVariable || []).concat([
@@ -143,9 +159,11 @@ or directly pass the "basename":
143
159
  _$props[_key] = arguments[_key];
144
160
  }
145
161
  if (componetRenderMode && SubComponent) {
146
- setSubModuleComponent({
147
- component: SubComponent
148
- });
162
+ if (isMountedRef.current) {
163
+ setSubModuleComponent({
164
+ component: SubComponent
165
+ });
166
+ }
149
167
  return void 0;
150
168
  } else {
151
169
  logger("MicroApp customer render", _$props);
@@ -165,7 +183,7 @@ or directly pass the "basename":
165
183
  };
166
184
  }
167
185
  });
168
- setLoadingState({
186
+ safeSetLoadingState({
169
187
  isLoading: true,
170
188
  error: null
171
189
  });
@@ -174,7 +192,7 @@ or directly pass the "basename":
174
192
  });
175
193
  function _renderApp() {
176
194
  _renderApp = _async_to_generator(function() {
177
- var appInstance, error;
195
+ var _abortControllerRef_current, _abortControllerRef_current1, appInstance, error, _abortControllerRef_current2;
178
196
  return _ts_generator(this, function(_state) {
179
197
  switch (_state.label) {
180
198
  case 0:
@@ -184,17 +202,27 @@ or directly pass the "basename":
184
202
  ,
185
203
  7
186
204
  ]);
205
+ if ((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted) {
206
+ return [
207
+ 2
208
+ ];
209
+ }
187
210
  return [
188
211
  4,
189
212
  Garfish.loadApp(appInfo.name, loadAppOptions)
190
213
  ];
191
214
  case 1:
192
215
  appInstance = _state.sent();
216
+ if ((_abortControllerRef_current1 = abortControllerRef.current) === null || _abortControllerRef_current1 === void 0 ? void 0 : _abortControllerRef_current1.signal.aborted) {
217
+ return [
218
+ 2
219
+ ];
220
+ }
193
221
  if (!appInstance) {
194
222
  throw new Error('MicroApp Garfish.loadApp "'.concat(appInfo.name, '" result is null'));
195
223
  }
196
224
  appRef.current = appInstance;
197
- setLoadingState({
225
+ safeSetLoadingState({
198
226
  isLoading: false
199
227
  });
200
228
  if (!(appInstance.mounted && appInstance.appInfo.cache))
@@ -235,10 +263,12 @@ or directly pass the "basename":
235
263
  ];
236
264
  case 6:
237
265
  error = _state.sent();
238
- setLoadingState({
239
- isLoading: true,
240
- error
241
- });
266
+ if (!((_abortControllerRef_current2 = abortControllerRef.current) === null || _abortControllerRef_current2 === void 0 ? void 0 : _abortControllerRef_current2.signal.aborted)) {
267
+ safeSetLoadingState({
268
+ isLoading: true,
269
+ error
270
+ });
271
+ }
242
272
  return [
243
273
  3,
244
274
  7
@@ -254,6 +284,10 @@ or directly pass the "basename":
254
284
  }
255
285
  renderApp();
256
286
  return function() {
287
+ isMountedRef.current = false;
288
+ if (abortControllerRef.current) {
289
+ abortControllerRef.current.abort();
290
+ }
257
291
  if (appRef.current) {
258
292
  var _$appInfo = appRef.current.appInfo;
259
293
  if (_$appInfo.cache) {
@@ -270,7 +304,7 @@ or directly pass the "basename":
270
304
  }, []);
271
305
  useEffect(function() {
272
306
  return function() {
273
- if (SubModuleComponent && destroyRef.current) {
307
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
274
308
  logger("MicroApp SubModuleComponent cleanup");
275
309
  try {
276
310
  destroyRef.current();
@@ -282,10 +316,24 @@ or directly pass the "basename":
282
316
  }, [
283
317
  SubModuleComponent
284
318
  ]);
319
+ var SafeSubModuleComponent = useCallback(function() {
320
+ if (!SubModuleComponent || !isMountedRef.current) {
321
+ return null;
322
+ }
323
+ return /* @__PURE__ */ _jsx(MicroAppMountContext.Provider, {
324
+ value: {
325
+ isMounted: isMountedRef.current
326
+ },
327
+ children: /* @__PURE__ */ _jsx(SubModuleComponent, _object_spread({}, props))
328
+ });
329
+ }, [
330
+ SubModuleComponent,
331
+ props
332
+ ]);
285
333
  return /* @__PURE__ */ _jsx(_Fragment, {
286
334
  children: /* @__PURE__ */ _jsx("div", {
287
335
  id: domId,
288
- children: SubModuleComponent && /* @__PURE__ */ _jsx(SubModuleComponent, _object_spread({}, props))
336
+ children: SubModuleComponent && /* @__PURE__ */ _jsx(SafeSubModuleComponent, {})
289
337
  })
290
338
  });
291
339
  }
@@ -306,5 +354,6 @@ function generateApps(options, manifest) {
306
354
  }
307
355
  export {
308
356
  generateApps,
309
- pathJoin
357
+ pathJoin,
358
+ useMicroAppMountStatus
310
359
  };
@@ -1,9 +1,16 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { RuntimeReactContext } from "@meta/runtime";
3
3
  import Garfish from "garfish";
4
- import { useContext, useEffect, useRef, useState } from "react";
4
+ import { createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
5
5
  import { generateSubAppContainerKey, logger } from "../../util";
6
6
  import { Loadable } from "../loadable";
7
+ const MicroAppMountContext = /* @__PURE__ */ createContext({
8
+ isMounted: true
9
+ });
10
+ const useMicroAppMountStatus = () => {
11
+ const { isMounted } = useContext(MicroAppMountContext);
12
+ return isMounted;
13
+ };
7
14
  function pathJoin(...args) {
8
15
  const res = args.reduce((res2, path) => {
9
16
  let nPath = path;
@@ -31,6 +38,8 @@ function getAppInstance(options, appInfo, manifest) {
31
38
  component: null
32
39
  });
33
40
  const destroyRef = useRef(null);
41
+ const isMountedRef = useRef(true);
42
+ const abortControllerRef = useRef(null);
34
43
  const context = useContext(RuntimeReactContext);
35
44
  var _props_useRouteMatch;
36
45
  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;
@@ -94,6 +103,13 @@ or directly pass the "basename":
94
103
  ]);
95
104
  useEffect(() => {
96
105
  const { setLoadingState, ...userProps } = props;
106
+ abortControllerRef.current = new AbortController();
107
+ const safeSetLoadingState = (state) => {
108
+ var _abortControllerRef_current;
109
+ if (isMountedRef.current && !((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted)) {
110
+ setLoadingState(state);
111
+ }
112
+ };
97
113
  const loadAppOptions = {
98
114
  cache: true,
99
115
  insulationVariable: [
@@ -134,9 +150,11 @@ or directly pass the "basename":
134
150
  return {
135
151
  mount: (...props2) => {
136
152
  if (componetRenderMode && SubComponent) {
137
- setSubModuleComponent({
138
- component: SubComponent
139
- });
153
+ if (isMountedRef.current) {
154
+ setSubModuleComponent({
155
+ component: SubComponent
156
+ });
157
+ }
140
158
  return void 0;
141
159
  } else {
142
160
  logger("MicroApp customer render", props2);
@@ -153,7 +171,7 @@ or directly pass the "basename":
153
171
  };
154
172
  }
155
173
  };
156
- setLoadingState({
174
+ safeSetLoadingState({
157
175
  isLoading: true,
158
176
  error: null
159
177
  });
@@ -162,12 +180,19 @@ or directly pass the "basename":
162
180
  });
163
181
  async function renderApp() {
164
182
  try {
183
+ var _abortControllerRef_current, _abortControllerRef_current1;
184
+ if ((_abortControllerRef_current = abortControllerRef.current) === null || _abortControllerRef_current === void 0 ? void 0 : _abortControllerRef_current.signal.aborted) {
185
+ return;
186
+ }
165
187
  const appInstance = await Garfish.loadApp(appInfo.name, loadAppOptions);
188
+ if ((_abortControllerRef_current1 = abortControllerRef.current) === null || _abortControllerRef_current1 === void 0 ? void 0 : _abortControllerRef_current1.signal.aborted) {
189
+ return;
190
+ }
166
191
  if (!appInstance) {
167
192
  throw new Error(`MicroApp Garfish.loadApp "${appInfo.name}" result is null`);
168
193
  }
169
194
  appRef.current = appInstance;
170
- setLoadingState({
195
+ safeSetLoadingState({
171
196
  isLoading: false
172
197
  });
173
198
  if (appInstance.mounted && appInstance.appInfo.cache) {
@@ -184,14 +209,21 @@ or directly pass the "basename":
184
209
  await (appInstance === null || appInstance === void 0 ? void 0 : appInstance.mount());
185
210
  }
186
211
  } catch (error) {
187
- setLoadingState({
188
- isLoading: true,
189
- error
190
- });
212
+ var _abortControllerRef_current2;
213
+ if (!((_abortControllerRef_current2 = abortControllerRef.current) === null || _abortControllerRef_current2 === void 0 ? void 0 : _abortControllerRef_current2.signal.aborted)) {
214
+ safeSetLoadingState({
215
+ isLoading: true,
216
+ error
217
+ });
218
+ }
191
219
  }
192
220
  }
193
221
  renderApp();
194
222
  return () => {
223
+ isMountedRef.current = false;
224
+ if (abortControllerRef.current) {
225
+ abortControllerRef.current.abort();
226
+ }
195
227
  if (appRef.current) {
196
228
  const { appInfo: appInfo2 } = appRef.current;
197
229
  if (appInfo2.cache) {
@@ -208,7 +240,7 @@ or directly pass the "basename":
208
240
  }, []);
209
241
  useEffect(() => {
210
242
  return () => {
211
- if (SubModuleComponent && destroyRef.current) {
243
+ if (SubModuleComponent && destroyRef.current && isMountedRef.current) {
212
244
  logger("MicroApp SubModuleComponent cleanup");
213
245
  try {
214
246
  destroyRef.current();
@@ -220,12 +252,26 @@ or directly pass the "basename":
220
252
  }, [
221
253
  SubModuleComponent
222
254
  ]);
255
+ const SafeSubModuleComponent = useCallback(() => {
256
+ if (!SubModuleComponent || !isMountedRef.current) {
257
+ return null;
258
+ }
259
+ return /* @__PURE__ */ _jsx(MicroAppMountContext.Provider, {
260
+ value: {
261
+ isMounted: isMountedRef.current
262
+ },
263
+ children: /* @__PURE__ */ _jsx(SubModuleComponent, {
264
+ ...props
265
+ })
266
+ });
267
+ }, [
268
+ SubModuleComponent,
269
+ props
270
+ ]);
223
271
  return /* @__PURE__ */ _jsx(_Fragment, {
224
272
  children: /* @__PURE__ */ _jsx("div", {
225
273
  id: domId,
226
- children: SubModuleComponent && /* @__PURE__ */ _jsx(SubModuleComponent, {
227
- ...props
228
- })
274
+ children: SubModuleComponent && /* @__PURE__ */ _jsx(SafeSubModuleComponent, {})
229
275
  })
230
276
  });
231
277
  }
@@ -246,5 +292,6 @@ function generateApps(options, manifest) {
246
292
  }
247
293
  export {
248
294
  generateApps,
249
- pathJoin
295
+ pathJoin,
296
+ useMicroAppMountStatus
250
297
  };
@@ -5,6 +5,7 @@ export interface Provider extends interfaces.Provider {
5
5
  SubModuleComponent?: React.ComponentType<any>;
6
6
  jupiter_submodule_app_key?: React.ComponentType<any>;
7
7
  }
8
+ export declare const useMicroAppMountStatus: () => boolean;
8
9
  export interface AppMap {
9
10
  [key: string]: React.FC<MicroComponentProps>;
10
11
  }
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "modern",
16
16
  "modern.js"
17
17
  ],
18
- "version": "2.68.13-alpha.0",
18
+ "version": "2.68.13-alpha.2",
19
19
  "jsnext:source": "./src/cli/index.ts",
20
20
  "types": "./dist/types/cli/index.d.ts",
21
21
  "typesVersions": {
@@ -69,8 +69,8 @@
69
69
  "debug": "4.3.7",
70
70
  "garfish": "^1.8.1",
71
71
  "react-loadable": "^5.5.0",
72
- "@modern-js/plugin-v2": "2.68.12",
73
72
  "@modern-js/runtime-utils": "2.68.12",
73
+ "@modern-js/plugin-v2": "2.68.12",
74
74
  "@modern-js/utils": "2.68.12"
75
75
  },
76
76
  "peerDependencies": {
@@ -94,11 +94,11 @@
94
94
  "react-router-dom": "6.27.0",
95
95
  "typescript": "^5",
96
96
  "@modern-js/app-tools": "2.68.12",
97
- "@modern-js/core": "2.68.12",
98
97
  "@scripts/build": "2.66.0",
98
+ "@modern-js/core": "2.68.12",
99
99
  "@modern-js/plugin-router-v5": "2.68.12",
100
- "@modern-js/runtime": "2.68.12",
101
100
  "@modern-js/types": "2.68.12",
101
+ "@modern-js/runtime": "2.68.12",
102
102
  "@scripts/jest-config": "2.66.0"
103
103
  },
104
104
  "sideEffects": false,