@alicloud/alfa-react 1.7.0-alpha.0 → 1.7.1-alpha.0

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.
@@ -4,10 +4,8 @@ export default function getLoading(_ref) {
4
4
  var loading = _ref.loading;
5
5
  if (loading === false) {
6
6
  return null;
7
- } else if (loading && /*#__PURE__*/React.isValidElement(loading)) {
8
- return loading;
9
7
  }
10
- return /*#__PURE__*/React.createElement(Skeleton, {
8
+ return loading && /*#__PURE__*/React.isValidElement(loading) ? loading : /*#__PURE__*/React.createElement(Skeleton, {
11
9
  active: true
12
10
  });
13
11
  }
@@ -141,6 +141,14 @@ function createAlfaWidget(option) {
141
141
  })));
142
142
  };
143
143
  }
144
+ export function createAlfaWidgetSingleton(option) {
145
+ return createAlfaWidget(_objectSpread(_objectSpread({}, option), {}, {
146
+ noCache: true,
147
+ sandbox: {
148
+ sandBoxUrl: 'about:blank'
149
+ }
150
+ }));
151
+ }
144
152
 
145
153
  /**
146
154
  * create memorized app in react function component, just create App after first mounted
@@ -5,65 +5,22 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
5
5
  import _regeneratorRuntime from "@babel/runtime/regenerator";
6
6
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
7
7
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
8
- import React, { useRef, useEffect, useState, useMemo, useContext } from 'react';
8
+ import React, { useRef, useEffect, useState, useMemo, useContext, useCallback } from 'react';
9
9
  import { createEventBus } from '@alicloud/alfa-core';
10
10
  import { ConsoleRegion, ConsoleResourceGroup, ConsoleContext } from '@alicloud/xconsole-context';
11
11
  import { forApp } from '@alicloud/console-base-messenger';
12
+ import { forceCheck } from 'react-lazyload';
12
13
  import Loading from './components/Loading';
13
- import { normalizeName, setNativeProperty } from './utils';
14
+ import { normalizeName, setNativeProperty, peelPath, getHistoryState, stripBasename, addBasename, addLeftSlash } from './utils';
15
+ import { useCallbackRef } from './hooks';
14
16
  import { countRegister } from './utils/counter';
15
17
  import { version as loaderVersion } from './version';
16
- import { forceCheck } from 'react-lazyload';
17
18
  var eventBus = createEventBus();
18
- var resolvePath = function resolvePath() {
19
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
20
- args[_key] = arguments[_key];
21
- }
22
- return "/".concat(args.join('/')).replace(/\/+/g, '/');
23
- };
24
-
25
- /**
26
- * 去掉 location.origin 的路径
27
- */
28
- var peelPath = function peelPath(location) {
29
- return location.pathname + location.search + location.hash;
30
- };
31
- var addBasename = function addBasename(path, basename) {
32
- if (!basename) return path;
33
- return resolvePath(basename, path);
34
- };
35
- var addLeftSlash = function addLeftSlash(path) {
36
- return path.charAt(0) === '/' ? path : "/".concat(path);
37
- };
38
-
39
- /**
40
- * 从 path 移除 basename 部分
41
- * @param path
42
- * @param basename
43
- * @returns string
44
- */
45
- var stripBasename = function stripBasename(path, basename) {
46
- if (!basename) return path;
47
- var _path = resolvePath(path);
48
- var _basename = resolvePath(basename);
49
- if (_path === _basename) return '/';
50
- // escape all possible regex special characters
51
- return _path.replace(new RegExp("^".concat(_basename.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')), 'ig'), '');
52
- };
53
-
54
- /**
55
- * fix Error (we do not know why):
56
- * Failed to read the 'state' property from 'History':
57
- * May not use a History object associated with a Document that is not fully active
58
- * @returns any
59
- */
60
- var getHistoryState = function getHistoryState() {
61
- try {
62
- var _window;
63
- return (_window = window) === null || _window === void 0 ? void 0 : _window.history.state;
64
- } catch (e) {
65
- return null;
66
- }
19
+ var dispatchFramePopstate = function dispatchFramePopstate(App) {
20
+ var _App$context$baseFram, _App$context$baseFram2;
21
+ var popstateEvent = new Event('popstate');
22
+ popstateEvent.state = getHistoryState() || {};
23
+ App === null || App === void 0 ? void 0 : (_App$context$baseFram = App.context.baseFrame) === null || _App$context$baseFram === void 0 ? void 0 : (_App$context$baseFram2 = _App$context$baseFram.contentWindow) === null || _App$context$baseFram2 === void 0 ? void 0 : _App$context$baseFram2.dispatchEvent(popstateEvent);
67
24
  };
68
25
 
69
26
  /**
@@ -100,7 +57,6 @@ export default function createApplication(loader) {
100
57
  syncResourceGroup = props.syncResourceGroup,
101
58
  basename = props.basename,
102
59
  channel = props.channel,
103
- onSyncHistory = props.onSyncHistory,
104
60
  delayPromise = props.delayPromise,
105
61
  preLoader = props.preLoader;
106
62
  var handleExternalLink = customProps.handleExternalLink;
@@ -122,6 +78,12 @@ export default function createApplication(loader) {
122
78
  _useState6 = _slicedToArray(_useState5, 2),
123
79
  releaseVersion = _useState6[0],
124
80
  setReleaseVersion = _useState6[1];
81
+ var initOptions = useRef({
82
+ delayPromise: delayPromise,
83
+ preLoader: preLoader,
84
+ container: container
85
+ });
86
+ var onSyncHistory = useCallbackRef(props.onSyncHistory || function () {});
125
87
  $syncHistory.current = syncHistory;
126
88
  $basename.current = basename;
127
89
 
@@ -211,7 +173,6 @@ export default function createApplication(loader) {
211
173
  name: name,
212
174
  version: version,
213
175
  manifest: manifest,
214
- container: container,
215
176
  props: customProps,
216
177
  sandbox: sandbox,
217
178
  logger: customLogger,
@@ -229,18 +190,15 @@ export default function createApplication(loader) {
229
190
  channel: channel
230
191
  };
231
192
  }, []);
193
+ var getFakeBody = useCallback(function () {
194
+ return initOptions.current.container || appRef.current || document.body;
195
+ }, []);
232
196
  useEffect(function () {
233
197
  var isUnmounted = false;
234
198
  var App;
235
199
  var originalPushState;
236
200
  var originalReplaceState;
237
201
  var originalGo;
238
- var dispatchFramePopstate = function dispatchFramePopstate() {
239
- var _App, _App$context$baseFram, _App$context$baseFram2;
240
- var popstateEvent = new Event('popstate');
241
- popstateEvent.state = getHistoryState() || {};
242
- (_App = App) === null || _App === void 0 ? void 0 : (_App$context$baseFram = _App.context.baseFrame) === null || _App$context$baseFram === void 0 ? void 0 : (_App$context$baseFram2 = _App$context$baseFram.contentWindow) === null || _App$context$baseFram2 === void 0 ? void 0 : _App$context$baseFram2.dispatchEvent(popstateEvent);
243
- };
244
202
 
245
203
  /**
246
204
  * 因为要兼容历史逻辑,所以这段逻辑并不会执行
@@ -258,7 +216,7 @@ export default function createApplication(loader) {
258
216
  if (nextPath !== stripBasename(peelPath(window.location), $basename.current)) {
259
217
  if (originalReplaceState) {
260
218
  originalReplaceState(getHistoryState(), '', stripBasename(peelPath(window.location), $basename.current));
261
- dispatchFramePopstate();
219
+ dispatchFramePopstate(App);
262
220
  }
263
221
  }
264
222
  }
@@ -273,20 +231,20 @@ export default function createApplication(loader) {
273
231
  while (1) switch (_context.prev = _context.next) {
274
232
  case 0:
275
233
  countRegister(memoOptions.name);
276
- fakeBody = memoOptions.container || appRef.current || document.body;
277
- if (!delayPromise) {
234
+ fakeBody = getFakeBody();
235
+ if (!initOptions.current.delayPromise) {
278
236
  _context.next = 5;
279
237
  break;
280
238
  }
281
239
  _context.next = 5;
282
- return delayPromise;
240
+ return initOptions.current.delayPromise;
283
241
  case 5:
284
- if (!preLoader) {
242
+ if (!initOptions.current.preLoader) {
285
243
  _context.next = 11;
286
244
  break;
287
245
  }
288
246
  _context.next = 8;
289
- return preLoader(_objectSpread(_objectSpread({}, memoOptions), {}, {
247
+ return initOptions.current.preLoader(_objectSpread(_objectSpread({}, memoOptions), {}, {
290
248
  container: fakeBody
291
249
  }));
292
250
  case 8:
@@ -348,7 +306,7 @@ export default function createApplication(loader) {
348
306
  var nextPath = addBasename((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
349
307
  if ("".concat(nextPath) !== peelPath(window.location)) {
350
308
  window.history.pushState(data, unused, nextPath);
351
- onSyncHistory && onSyncHistory('push', nextPath, data);
309
+ onSyncHistory('push', nextPath, data);
352
310
  }
353
311
  originalReplaceState(data, unused, _url);
354
312
  } else {
@@ -359,7 +317,7 @@ export default function createApplication(loader) {
359
317
  var nextPath = addBasename((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
360
318
  if ($syncHistory.current) {
361
319
  window.history.replaceState(data, unused, nextPath);
362
- onSyncHistory && onSyncHistory('replace', nextPath, data);
320
+ onSyncHistory('replace', nextPath, data);
363
321
  }
364
322
  originalReplaceState(data, unused, _url);
365
323
  };
@@ -369,35 +327,16 @@ export default function createApplication(loader) {
369
327
  window.history.go(n);
370
328
  });
371
329
  }
372
- _context.next = 32;
373
- return app.mount(fakeBody, {
374
- customProps: customProps
375
- });
376
- case 32:
377
- if (!isUnmounted) {
378
- _context.next = 34;
379
- break;
380
- }
381
- return _context.abrupt("return");
382
- case 34:
383
- // 降低优先级
384
- setTimeout(function () {
385
- forceCheck();
386
- }, 0);
387
330
  (logger === null || logger === void 0 ? void 0 : logger.record) && (logger === null || logger === void 0 ? void 0 : logger.record({
388
331
  REQUEST_VERSION: memoOptions.version,
389
332
  RESPONSE_VERSION: realVersion,
390
333
  END_TIME: Date.now()
391
334
  }));
392
335
  (logger === null || logger === void 0 ? void 0 : logger.send) && (logger === null || logger === void 0 ? void 0 : logger.send());
393
- if (frameWindow) {
394
- // 每次挂载后主动触发子应用内的 popstate 事件,借此触发 react-router history 的检查逻辑
395
- dispatchFramePopstate();
396
- }
397
336
 
398
337
  // just run once
399
338
  setAppInstance(app);
400
- case 39:
339
+ case 33:
401
340
  case "end":
402
341
  return _context.stop();
403
342
  }
@@ -422,12 +361,10 @@ export default function createApplication(loader) {
422
361
  setNativeProperty(frameHistory, 'go', originalGo);
423
362
  }
424
363
  }
425
- App.unmount();
426
-
427
364
  // TODO: 在沙箱中嵌套时,unmount 必须销毁沙箱实例,避免在其它微应用中复用该沙箱,导致环境变量污染
428
365
  // if (isOsContext()) App.destroy();
429
366
  };
430
- }, [memoOptions]);
367
+ }, [memoOptions, getFakeBody, onSyncHistory]);
431
368
  useEffect(function () {
432
369
  var _handleExternalLink = function _handleExternalLink(href) {
433
370
  handleExternalLink === null || handleExternalLink === void 0 ? void 0 : handleExternalLink(href);
@@ -437,6 +374,36 @@ export default function createApplication(loader) {
437
374
  eventBus.removeListener("".concat(normalizeName(name), ":external-router"), _handleExternalLink);
438
375
  };
439
376
  }, [handleExternalLink, name]);
377
+ useEffect(function () {
378
+ var isUnmounted = false;
379
+ // 等待加载完成并更新了视图后再挂载
380
+ if (!appInstance) return;
381
+ appInstance.mount(getFakeBody(), {
382
+ customProps: customProps
383
+ }).then(function () {
384
+ var _appInstance$context$;
385
+ if (isUnmounted) return;
386
+
387
+ // 每次挂载后检查是否还有 lazyload 组件未加载
388
+ setTimeout(function () {
389
+ forceCheck();
390
+ }, 0);
391
+ if ((_appInstance$context$ = appInstance.context.baseFrame) !== null && _appInstance$context$ !== void 0 && _appInstance$context$.contentWindow) {
392
+ // 每次挂载后主动触发子应用内的 popstate 事件,借此触发 react-router history 的检查逻辑
393
+ dispatchFramePopstate(appInstance);
394
+ }
395
+ }).catch(function (e) {
396
+ setError(function () {
397
+ throw e;
398
+ });
399
+ });
400
+
401
+ // 手动销毁
402
+ return function () {
403
+ isUnmounted = true;
404
+ appInstance.unmount();
405
+ };
406
+ }, [appInstance, getFakeBody]);
440
407
  if (appInstance) {
441
408
  appInstance.update(customProps);
442
409
  }
@@ -449,16 +416,18 @@ export default function createApplication(loader) {
449
416
  // 实际线上版本
450
417
  'data-release-version': releaseVersion
451
418
  };
452
- return /*#__PURE__*/React.createElement(React.Fragment, null, !appInstance ? /*#__PURE__*/React.createElement(Loading, {
453
- loading: loading
454
- }) : null, sandbox && sandbox.disableFakeBody ? /*#__PURE__*/React.createElement(tagName, _objectSpread({
419
+ return /*#__PURE__*/React.createElement(React.Fragment, null, sandbox !== null && sandbox !== void 0 && sandbox.disableFakeBody ? /*#__PURE__*/React.createElement(tagName, _objectSpread({
455
420
  style: style,
456
421
  className: className,
457
422
  ref: appRef
458
- }, dataAttrs)) : /*#__PURE__*/React.createElement(tagName, _objectSpread({}, dataAttrs), /*#__PURE__*/React.createElement('div', {
423
+ }, dataAttrs), /*#__PURE__*/React.createElement(Loading, {
424
+ loading: !appInstance && loading
425
+ })) : /*#__PURE__*/React.createElement(tagName, _objectSpread({}, dataAttrs), /*#__PURE__*/React.createElement('div', {
459
426
  ref: appRef,
460
427
  style: style,
461
428
  className: className
462
- })));
429
+ }, /*#__PURE__*/React.createElement(Loading, {
430
+ loading: !appInstance && loading
431
+ }))));
463
432
  };
464
433
  }
package/es/hooks/index.js CHANGED
@@ -13,4 +13,5 @@ export function useLoaderEvent(eventName, cb) {
13
13
  emitter.off(eventName, listener);
14
14
  };
15
15
  }, [eventName]);
16
- }
16
+ }
17
+ export * from './useCallbackRef';
@@ -0,0 +1,10 @@
1
+ import { useCallback, useRef, useEffect } from 'react';
2
+ export function useCallbackRef(callback) {
3
+ var ref = useRef(callback);
4
+ useEffect(function () {
5
+ ref.current = callback;
6
+ }, [callback]);
7
+ return useCallback(function () {
8
+ return ref.current.apply(ref, arguments);
9
+ }, []);
10
+ }
package/es/utils/index.js CHANGED
@@ -33,4 +33,54 @@ export var setNativeProperty = function setNativeProperty(obj, propertyName, val
33
33
  if (desc && typeof desc.set === 'undefined') return;
34
34
  obj[propertyName] = value;
35
35
  };
36
- export var IS_SSR = typeof document === 'undefined';
36
+ export var IS_SSR = typeof document === 'undefined';
37
+
38
+ /**
39
+ * 去掉 location.origin 的路径
40
+ */
41
+ export var peelPath = function peelPath(location) {
42
+ return location.pathname + location.search + location.hash;
43
+ };
44
+ export var resolvePath = function resolvePath() {
45
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
46
+ args[_key] = arguments[_key];
47
+ }
48
+ return "/".concat(args.join('/')).replace(/\/+/g, '/');
49
+ };
50
+ export var addBasename = function addBasename(path, basename) {
51
+ if (!basename) return path;
52
+ return resolvePath(basename, path);
53
+ };
54
+ export var addLeftSlash = function addLeftSlash(path) {
55
+ return path.charAt(0) === '/' ? path : "/".concat(path);
56
+ };
57
+
58
+ /**
59
+ * 从 path 移除 basename 部分
60
+ * @param path
61
+ * @param basename
62
+ * @returns string
63
+ */
64
+ export var stripBasename = function stripBasename(path, basename) {
65
+ if (!basename) return path;
66
+ var _path = resolvePath(path);
67
+ var _basename = resolvePath(basename);
68
+ if (_path === _basename) return '/';
69
+ // escape all possible regex special characters
70
+ return _path.replace(new RegExp("^".concat(_basename.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')), 'ig'), '');
71
+ };
72
+
73
+ /**
74
+ * fix Error (we do not know why):
75
+ * Failed to read the 'state' property from 'History':
76
+ * May not use a History object associated with a Document that is not fully active
77
+ * @returns any
78
+ */
79
+ export var getHistoryState = function getHistoryState() {
80
+ try {
81
+ var _window;
82
+ return (_window = window) === null || _window === void 0 ? void 0 : _window.history.state;
83
+ } catch (e) {
84
+ return null;
85
+ }
86
+ };
package/es/version.js CHANGED
@@ -1 +1 @@
1
- export var version = '1.7.0-alpha.0';
1
+ export var version = '1.7.1-alpha.0';
@@ -11,10 +11,8 @@ function getLoading(_ref) {
11
11
  var loading = _ref.loading;
12
12
  if (loading === false) {
13
13
  return null;
14
- } else if (loading && /*#__PURE__*/_react.default.isValidElement(loading)) {
15
- return loading;
16
14
  }
17
- return /*#__PURE__*/_react.default.createElement(_Skeleton.default, {
15
+ return loading && /*#__PURE__*/_react.default.isValidElement(loading) ? loading : /*#__PURE__*/_react.default.createElement(_Skeleton.default, {
18
16
  active: true
19
17
  });
20
18
  }
@@ -5,6 +5,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
+ exports.createAlfaWidgetSingleton = createAlfaWidgetSingleton;
8
9
  exports.default = void 0;
9
10
  exports.useAlfaWidget = useAlfaWidget;
10
11
  var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
@@ -152,6 +153,14 @@ function createAlfaWidget(option) {
152
153
  })));
153
154
  };
154
155
  }
156
+ function createAlfaWidgetSingleton(option) {
157
+ return createAlfaWidget(_objectSpread(_objectSpread({}, option), {}, {
158
+ noCache: true,
159
+ sandbox: {
160
+ sandBoxUrl: 'about:blank'
161
+ }
162
+ }));
163
+ }
155
164
 
156
165
  /**
157
166
  * create memorized app in react function component, just create App after first mounted
@@ -15,65 +15,22 @@ var _react = _interopRequireWildcard(require("react"));
15
15
  var _alfaCore = require("@alicloud/alfa-core");
16
16
  var _xconsoleContext = require("@alicloud/xconsole-context");
17
17
  var _consoleBaseMessenger = require("@alicloud/console-base-messenger");
18
+ var _reactLazyload = require("react-lazyload");
18
19
  var _Loading = _interopRequireDefault(require("./components/Loading"));
19
20
  var _utils = require("./utils");
21
+ var _hooks = require("./hooks");
20
22
  var _counter = require("./utils/counter");
21
23
  var _version = require("./version");
22
- var _reactLazyload = require("react-lazyload");
23
24
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
24
25
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
26
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
26
27
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
27
28
  var eventBus = (0, _alfaCore.createEventBus)();
28
- var resolvePath = function resolvePath() {
29
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
30
- args[_key] = arguments[_key];
31
- }
32
- return "/".concat(args.join('/')).replace(/\/+/g, '/');
33
- };
34
-
35
- /**
36
- * 去掉 location.origin 的路径
37
- */
38
- var peelPath = function peelPath(location) {
39
- return location.pathname + location.search + location.hash;
40
- };
41
- var addBasename = function addBasename(path, basename) {
42
- if (!basename) return path;
43
- return resolvePath(basename, path);
44
- };
45
- var addLeftSlash = function addLeftSlash(path) {
46
- return path.charAt(0) === '/' ? path : "/".concat(path);
47
- };
48
-
49
- /**
50
- * 从 path 移除 basename 部分
51
- * @param path
52
- * @param basename
53
- * @returns string
54
- */
55
- var stripBasename = function stripBasename(path, basename) {
56
- if (!basename) return path;
57
- var _path = resolvePath(path);
58
- var _basename = resolvePath(basename);
59
- if (_path === _basename) return '/';
60
- // escape all possible regex special characters
61
- return _path.replace(new RegExp("^".concat(_basename.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')), 'ig'), '');
62
- };
63
-
64
- /**
65
- * fix Error (we do not know why):
66
- * Failed to read the 'state' property from 'History':
67
- * May not use a History object associated with a Document that is not fully active
68
- * @returns any
69
- */
70
- var getHistoryState = function getHistoryState() {
71
- try {
72
- var _window;
73
- return (_window = window) === null || _window === void 0 ? void 0 : _window.history.state;
74
- } catch (e) {
75
- return null;
76
- }
29
+ var dispatchFramePopstate = function dispatchFramePopstate(App) {
30
+ var _App$context$baseFram, _App$context$baseFram2;
31
+ var popstateEvent = new Event('popstate');
32
+ popstateEvent.state = (0, _utils.getHistoryState)() || {};
33
+ App === null || App === void 0 ? void 0 : (_App$context$baseFram = App.context.baseFrame) === null || _App$context$baseFram === void 0 ? void 0 : (_App$context$baseFram2 = _App$context$baseFram.contentWindow) === null || _App$context$baseFram2 === void 0 ? void 0 : _App$context$baseFram2.dispatchEvent(popstateEvent);
77
34
  };
78
35
 
79
36
  /**
@@ -110,7 +67,6 @@ function createApplication(loader) {
110
67
  syncResourceGroup = props.syncResourceGroup,
111
68
  basename = props.basename,
112
69
  channel = props.channel,
113
- onSyncHistory = props.onSyncHistory,
114
70
  delayPromise = props.delayPromise,
115
71
  preLoader = props.preLoader;
116
72
  var handleExternalLink = customProps.handleExternalLink;
@@ -132,15 +88,21 @@ function createApplication(loader) {
132
88
  _useState6 = (0, _slicedToArray2.default)(_useState5, 2),
133
89
  releaseVersion = _useState6[0],
134
90
  setReleaseVersion = _useState6[1];
91
+ var initOptions = (0, _react.useRef)({
92
+ delayPromise: delayPromise,
93
+ preLoader: preLoader,
94
+ container: container
95
+ });
96
+ var onSyncHistory = (0, _hooks.useCallbackRef)(props.onSyncHistory || function () {});
135
97
  $syncHistory.current = syncHistory;
136
98
  $basename.current = basename;
137
99
 
138
100
  // if (customProps.__innerStamp) console.warn('Please do not use __innerStamp which used in internal.');
139
101
  // 更新标记,保证每次更新都会更新
140
102
  customProps.__innerStamp = (+new Date()).toString(36);
141
- customProps.__historyState = getHistoryState();
103
+ customProps.__historyState = (0, _utils.getHistoryState)();
142
104
  if (customProps.path) {
143
- customProps.path = addLeftSlash(customProps.path);
105
+ customProps.path = (0, _utils.addLeftSlash)(customProps.path);
144
106
  }
145
107
 
146
108
  // 受控模式锁定一些参数
@@ -148,7 +110,7 @@ function createApplication(loader) {
148
110
  // 禁止子应用和 consoleBase 通信
149
111
  customProps.consoleBase = null;
150
112
  // 覆写 path 参数,用于通知子应用更新路由
151
- customProps.path = addLeftSlash(stripBasename(peelPath(window.location), $basename.current));
113
+ customProps.path = (0, _utils.addLeftSlash)((0, _utils.stripBasename)((0, _utils.peelPath)(window.location), $basename.current));
152
114
  // 禁止注入 history
153
115
  customProps.__injectHistory = null;
154
116
  }
@@ -221,7 +183,6 @@ function createApplication(loader) {
221
183
  name: name,
222
184
  version: version,
223
185
  manifest: manifest,
224
- container: container,
225
186
  props: customProps,
226
187
  sandbox: sandbox,
227
188
  logger: customLogger,
@@ -239,18 +200,15 @@ function createApplication(loader) {
239
200
  channel: channel
240
201
  };
241
202
  }, []);
203
+ var getFakeBody = (0, _react.useCallback)(function () {
204
+ return initOptions.current.container || appRef.current || document.body;
205
+ }, []);
242
206
  (0, _react.useEffect)(function () {
243
207
  var isUnmounted = false;
244
208
  var App;
245
209
  var originalPushState;
246
210
  var originalReplaceState;
247
211
  var originalGo;
248
- var dispatchFramePopstate = function dispatchFramePopstate() {
249
- var _App, _App$context$baseFram, _App$context$baseFram2;
250
- var popstateEvent = new Event('popstate');
251
- popstateEvent.state = getHistoryState() || {};
252
- (_App = App) === null || _App === void 0 ? void 0 : (_App$context$baseFram = _App.context.baseFrame) === null || _App$context$baseFram === void 0 ? void 0 : (_App$context$baseFram2 = _App$context$baseFram.contentWindow) === null || _App$context$baseFram2 === void 0 ? void 0 : _App$context$baseFram2.dispatchEvent(popstateEvent);
253
- };
254
212
 
255
213
  /**
256
214
  * 因为要兼容历史逻辑,所以这段逻辑并不会执行
@@ -259,16 +217,16 @@ function createApplication(loader) {
259
217
  */
260
218
  var updateAppHistory = function updateAppHistory() {
261
219
  if (App) {
262
- var nextPath = peelPath(App.context.location);
220
+ var nextPath = (0, _utils.peelPath)(App.context.location);
263
221
 
264
222
  // 路由同步只应该在相同 basename 下生效
265
- if (!peelPath(window.location).startsWith($basename.current || '')) return;
223
+ if (!(0, _utils.peelPath)(window.location).startsWith($basename.current || '')) return;
266
224
 
267
225
  // 如果主子应用路径不同,主动通知子应用 popstate 事件
268
- if (nextPath !== stripBasename(peelPath(window.location), $basename.current)) {
226
+ if (nextPath !== (0, _utils.stripBasename)((0, _utils.peelPath)(window.location), $basename.current)) {
269
227
  if (originalReplaceState) {
270
- originalReplaceState(getHistoryState(), '', stripBasename(peelPath(window.location), $basename.current));
271
- dispatchFramePopstate();
228
+ originalReplaceState((0, _utils.getHistoryState)(), '', (0, _utils.stripBasename)((0, _utils.peelPath)(window.location), $basename.current));
229
+ dispatchFramePopstate(App);
272
230
  }
273
231
  }
274
232
  }
@@ -283,20 +241,20 @@ function createApplication(loader) {
283
241
  while (1) switch (_context.prev = _context.next) {
284
242
  case 0:
285
243
  (0, _counter.countRegister)(memoOptions.name);
286
- fakeBody = memoOptions.container || appRef.current || document.body;
287
- if (!delayPromise) {
244
+ fakeBody = getFakeBody();
245
+ if (!initOptions.current.delayPromise) {
288
246
  _context.next = 5;
289
247
  break;
290
248
  }
291
249
  _context.next = 5;
292
- return delayPromise;
250
+ return initOptions.current.delayPromise;
293
251
  case 5:
294
- if (!preLoader) {
252
+ if (!initOptions.current.preLoader) {
295
253
  _context.next = 11;
296
254
  break;
297
255
  }
298
256
  _context.next = 8;
299
- return preLoader(_objectSpread(_objectSpread({}, memoOptions), {}, {
257
+ return initOptions.current.preLoader(_objectSpread(_objectSpread({}, memoOptions), {}, {
300
258
  container: fakeBody
301
259
  }));
302
260
  case 8:
@@ -352,13 +310,13 @@ function createApplication(loader) {
352
310
  originalReplaceState = frameWindow === null || frameWindow === void 0 ? void 0 : frameWindow.history.replaceState;
353
311
  originalGo = frameWindow === null || frameWindow === void 0 ? void 0 : frameWindow.history.go;
354
312
  // update context history according to path
355
- if (path) originalReplaceState(getHistoryState(), '', path.replace(/\/+/g, '/'));
313
+ if (path) originalReplaceState((0, _utils.getHistoryState)(), '', path.replace(/\/+/g, '/'));
356
314
  frameWindow.history.pushState = function (data, unused, _url) {
357
315
  if ($syncHistory.current) {
358
- var nextPath = addBasename((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
359
- if ("".concat(nextPath) !== peelPath(window.location)) {
316
+ var nextPath = (0, _utils.addBasename)((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
317
+ if ("".concat(nextPath) !== (0, _utils.peelPath)(window.location)) {
360
318
  window.history.pushState(data, unused, nextPath);
361
- onSyncHistory && onSyncHistory('push', nextPath, data);
319
+ onSyncHistory('push', nextPath, data);
362
320
  }
363
321
  originalReplaceState(data, unused, _url);
364
322
  } else {
@@ -366,10 +324,10 @@ function createApplication(loader) {
366
324
  }
367
325
  };
368
326
  frameWindow.history.replaceState = function (data, unused, _url) {
369
- var nextPath = addBasename((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
327
+ var nextPath = (0, _utils.addBasename)((_url === null || _url === void 0 ? void 0 : _url.toString()) || '', $basename.current);
370
328
  if ($syncHistory.current) {
371
329
  window.history.replaceState(data, unused, nextPath);
372
- onSyncHistory && onSyncHistory('replace', nextPath, data);
330
+ onSyncHistory('replace', nextPath, data);
373
331
  }
374
332
  originalReplaceState(data, unused, _url);
375
333
  };
@@ -379,35 +337,16 @@ function createApplication(loader) {
379
337
  window.history.go(n);
380
338
  });
381
339
  }
382
- _context.next = 32;
383
- return app.mount(fakeBody, {
384
- customProps: customProps
385
- });
386
- case 32:
387
- if (!isUnmounted) {
388
- _context.next = 34;
389
- break;
390
- }
391
- return _context.abrupt("return");
392
- case 34:
393
- // 降低优先级
394
- setTimeout(function () {
395
- (0, _reactLazyload.forceCheck)();
396
- }, 0);
397
340
  (logger === null || logger === void 0 ? void 0 : logger.record) && (logger === null || logger === void 0 ? void 0 : logger.record({
398
341
  REQUEST_VERSION: memoOptions.version,
399
342
  RESPONSE_VERSION: realVersion,
400
343
  END_TIME: Date.now()
401
344
  }));
402
345
  (logger === null || logger === void 0 ? void 0 : logger.send) && (logger === null || logger === void 0 ? void 0 : logger.send());
403
- if (frameWindow) {
404
- // 每次挂载后主动触发子应用内的 popstate 事件,借此触发 react-router history 的检查逻辑
405
- dispatchFramePopstate();
406
- }
407
346
 
408
347
  // just run once
409
348
  setAppInstance(app);
410
- case 39:
349
+ case 33:
411
350
  case "end":
412
351
  return _context.stop();
413
352
  }
@@ -432,12 +371,10 @@ function createApplication(loader) {
432
371
  (0, _utils.setNativeProperty)(frameHistory, 'go', originalGo);
433
372
  }
434
373
  }
435
- App.unmount();
436
-
437
374
  // TODO: 在沙箱中嵌套时,unmount 必须销毁沙箱实例,避免在其它微应用中复用该沙箱,导致环境变量污染
438
375
  // if (isOsContext()) App.destroy();
439
376
  };
440
- }, [memoOptions]);
377
+ }, [memoOptions, getFakeBody, onSyncHistory]);
441
378
  (0, _react.useEffect)(function () {
442
379
  var _handleExternalLink = function _handleExternalLink(href) {
443
380
  handleExternalLink === null || handleExternalLink === void 0 ? void 0 : handleExternalLink(href);
@@ -447,6 +384,36 @@ function createApplication(loader) {
447
384
  eventBus.removeListener("".concat((0, _utils.normalizeName)(name), ":external-router"), _handleExternalLink);
448
385
  };
449
386
  }, [handleExternalLink, name]);
387
+ (0, _react.useEffect)(function () {
388
+ var isUnmounted = false;
389
+ // 等待加载完成并更新了视图后再挂载
390
+ if (!appInstance) return;
391
+ appInstance.mount(getFakeBody(), {
392
+ customProps: customProps
393
+ }).then(function () {
394
+ var _appInstance$context$;
395
+ if (isUnmounted) return;
396
+
397
+ // 每次挂载后检查是否还有 lazyload 组件未加载
398
+ setTimeout(function () {
399
+ (0, _reactLazyload.forceCheck)();
400
+ }, 0);
401
+ if ((_appInstance$context$ = appInstance.context.baseFrame) !== null && _appInstance$context$ !== void 0 && _appInstance$context$.contentWindow) {
402
+ // 每次挂载后主动触发子应用内的 popstate 事件,借此触发 react-router history 的检查逻辑
403
+ dispatchFramePopstate(appInstance);
404
+ }
405
+ }).catch(function (e) {
406
+ setError(function () {
407
+ throw e;
408
+ });
409
+ });
410
+
411
+ // 手动销毁
412
+ return function () {
413
+ isUnmounted = true;
414
+ appInstance.unmount();
415
+ };
416
+ }, [appInstance, getFakeBody]);
450
417
  if (appInstance) {
451
418
  appInstance.update(customProps);
452
419
  }
@@ -459,16 +426,18 @@ function createApplication(loader) {
459
426
  // 实际线上版本
460
427
  'data-release-version': releaseVersion
461
428
  };
462
- return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !appInstance ? /*#__PURE__*/_react.default.createElement(_Loading.default, {
463
- loading: loading
464
- }) : null, sandbox && sandbox.disableFakeBody ? /*#__PURE__*/_react.default.createElement(tagName, _objectSpread({
429
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, sandbox !== null && sandbox !== void 0 && sandbox.disableFakeBody ? /*#__PURE__*/_react.default.createElement(tagName, _objectSpread({
465
430
  style: style,
466
431
  className: className,
467
432
  ref: appRef
468
- }, dataAttrs)) : /*#__PURE__*/_react.default.createElement(tagName, _objectSpread({}, dataAttrs), /*#__PURE__*/_react.default.createElement('div', {
433
+ }, dataAttrs), /*#__PURE__*/_react.default.createElement(_Loading.default, {
434
+ loading: !appInstance && loading
435
+ })) : /*#__PURE__*/_react.default.createElement(tagName, _objectSpread({}, dataAttrs), /*#__PURE__*/_react.default.createElement('div', {
469
436
  ref: appRef,
470
437
  style: style,
471
438
  className: className
472
- })));
439
+ }, /*#__PURE__*/_react.default.createElement(_Loading.default, {
440
+ loading: !appInstance && loading
441
+ }))));
473
442
  };
474
443
  }
@@ -3,9 +3,24 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ var _exportNames = {
7
+ useLoaderEvent: true
8
+ };
6
9
  exports.useLoaderEvent = useLoaderEvent;
7
10
  var _react = require("react");
8
11
  var _alfaCore = require("@alicloud/alfa-core");
12
+ var _useCallbackRef = require("./useCallbackRef");
13
+ Object.keys(_useCallbackRef).forEach(function (key) {
14
+ if (key === "default" || key === "__esModule") return;
15
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
16
+ if (key in exports && exports[key] === _useCallbackRef[key]) return;
17
+ Object.defineProperty(exports, key, {
18
+ enumerable: true,
19
+ get: function get() {
20
+ return _useCallbackRef[key];
21
+ }
22
+ });
23
+ });
9
24
  var emitter = (0, _alfaCore.createEventBus)();
10
25
  function useLoaderEvent(eventName, cb) {
11
26
  var fn = (0, _react.useRef)(cb);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useCallbackRef = useCallbackRef;
7
+ var _react = require("react");
8
+ function useCallbackRef(callback) {
9
+ var ref = (0, _react.useRef)(callback);
10
+ (0, _react.useEffect)(function () {
11
+ ref.current = callback;
12
+ }, [callback]);
13
+ return (0, _react.useCallback)(function () {
14
+ return ref.current.apply(ref, arguments);
15
+ }, []);
16
+ }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setNativeProperty = exports.normalizeName = exports.isOsContext = exports.IS_SSR = void 0;
6
+ exports.stripBasename = exports.setNativeProperty = exports.resolvePath = exports.peelPath = exports.normalizeName = exports.isOsContext = exports.getHistoryState = exports.addLeftSlash = exports.addBasename = exports.IS_SSR = void 0;
7
7
  /**
8
8
  * kernel 会为沙箱 context 注入 __IS_CONSOLE_OS_CONTEXT__
9
9
  */
@@ -43,4 +43,60 @@ var setNativeProperty = function setNativeProperty(obj, propertyName, value) {
43
43
  };
44
44
  exports.setNativeProperty = setNativeProperty;
45
45
  var IS_SSR = typeof document === 'undefined';
46
- exports.IS_SSR = IS_SSR;
46
+
47
+ /**
48
+ * 去掉 location.origin 的路径
49
+ */
50
+ exports.IS_SSR = IS_SSR;
51
+ var peelPath = function peelPath(location) {
52
+ return location.pathname + location.search + location.hash;
53
+ };
54
+ exports.peelPath = peelPath;
55
+ var resolvePath = function resolvePath() {
56
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
57
+ args[_key] = arguments[_key];
58
+ }
59
+ return "/".concat(args.join('/')).replace(/\/+/g, '/');
60
+ };
61
+ exports.resolvePath = resolvePath;
62
+ var addBasename = function addBasename(path, basename) {
63
+ if (!basename) return path;
64
+ return resolvePath(basename, path);
65
+ };
66
+ exports.addBasename = addBasename;
67
+ var addLeftSlash = function addLeftSlash(path) {
68
+ return path.charAt(0) === '/' ? path : "/".concat(path);
69
+ };
70
+
71
+ /**
72
+ * 从 path 移除 basename 部分
73
+ * @param path
74
+ * @param basename
75
+ * @returns string
76
+ */
77
+ exports.addLeftSlash = addLeftSlash;
78
+ var stripBasename = function stripBasename(path, basename) {
79
+ if (!basename) return path;
80
+ var _path = resolvePath(path);
81
+ var _basename = resolvePath(basename);
82
+ if (_path === _basename) return '/';
83
+ // escape all possible regex special characters
84
+ return _path.replace(new RegExp("^".concat(_basename.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1')), 'ig'), '');
85
+ };
86
+
87
+ /**
88
+ * fix Error (we do not know why):
89
+ * Failed to read the 'state' property from 'History':
90
+ * May not use a History object associated with a Document that is not fully active
91
+ * @returns any
92
+ */
93
+ exports.stripBasename = stripBasename;
94
+ var getHistoryState = function getHistoryState() {
95
+ try {
96
+ var _window;
97
+ return (_window = window) === null || _window === void 0 ? void 0 : _window.history.state;
98
+ } catch (e) {
99
+ return null;
100
+ }
101
+ };
102
+ exports.getHistoryState = getHistoryState;
package/lib/version.js CHANGED
@@ -4,5 +4,5 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.version = void 0;
7
- var version = '1.7.0-alpha.0';
7
+ var version = '1.7.1-alpha.0';
8
8
  exports.version = version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alicloud/alfa-react",
3
- "version": "1.7.0-alpha.0",
3
+ "version": "1.7.1-alpha.0",
4
4
  "description": "Alfa Framework (React Version)",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -41,7 +41,7 @@
41
41
  "prop-types": "^15.8.1",
42
42
  "react-lazyload": "^3.2.1",
43
43
  "@alicloud/alfa-core": "^1.4.38",
44
- "@alicloud/console-os-loader": "^1.4.44"
44
+ "@alicloud/console-os-loader": "^1.4.45-alpha.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "react": ">=16.0.0",
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { AlfaFactoryOption } from './types';
3
3
  declare function createAlfaWidget<P = any>(option: AlfaFactoryOption): React.FC<any>;
4
+ export declare function createAlfaWidgetSingleton(option: AlfaFactoryOption): React.FC<any>;
4
5
  /**
5
6
  * create memorized app in react function component, just create App after first mounted
6
7
  * @param option
@@ -1,5 +1,5 @@
1
1
  import { BaseLoader } from '@alicloud/alfa-core';
2
- import { AlfaFactoryOption } from './types';
2
+ import type { AlfaFactoryOption } from './types';
3
3
  export interface IApplicationCustomProps {
4
4
  /**
5
5
  * 根结点样式
@@ -1 +1,2 @@
1
1
  export declare function useLoaderEvent<P = any>(eventName: string, cb: (args: P) => void): void;
2
+ export * from './useCallbackRef';
@@ -0,0 +1 @@
1
+ export declare function useCallbackRef<T extends (...args: any[]) => any>(callback: T): (...args: Parameters<T>) => any;
@@ -12,3 +12,24 @@ export declare const isOsContext: () => boolean;
12
12
  */
13
13
  export declare const setNativeProperty: (obj: any, propertyName: string, value: any) => void;
14
14
  export declare const IS_SSR: boolean;
15
+ /**
16
+ * 去掉 location.origin 的路径
17
+ */
18
+ export declare const peelPath: (location: Location) => string;
19
+ export declare const resolvePath: (...args: Array<string | undefined>) => string;
20
+ export declare const addBasename: (path: string, basename?: string) => string;
21
+ export declare const addLeftSlash: (path: string) => string;
22
+ /**
23
+ * 从 path 移除 basename 部分
24
+ * @param path
25
+ * @param basename
26
+ * @returns string
27
+ */
28
+ export declare const stripBasename: (path: string, basename?: string) => string;
29
+ /**
30
+ * fix Error (we do not know why):
31
+ * Failed to read the 'state' property from 'History':
32
+ * May not use a History object associated with a Document that is not fully active
33
+ * @returns any
34
+ */
35
+ export declare const getHistoryState: () => any;
@@ -1 +1 @@
1
- export declare const version = "1.7.0-alpha.0";
1
+ export declare const version = "1.7.1-alpha.0";