@module-federation/nextjs-mf 5.2.2 → 5.3.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.
Files changed (38) hide show
  1. package/lib/NextFederationPlugin2.js +0 -0
  2. package/lib/_virtual/UrlNode.js +8 -0
  3. package/lib/_virtual/_commonjsHelpers.js +26 -0
  4. package/lib/_virtual/_tslib.js +101 -0
  5. package/lib/_virtual/helpers.js +7 -0
  6. package/lib/_virtual/nextPageMapLoader.js +7 -0
  7. package/lib/client/CombinedPages.d.ts +28 -0
  8. package/lib/client/CombinedPages.d.ts.map +1 -0
  9. package/lib/client/CombinedPages.js +60 -0
  10. package/lib/client/MFClient.d.ts +70 -0
  11. package/lib/client/MFClient.d.ts.map +1 -0
  12. package/lib/client/MFClient.js +197 -0
  13. package/lib/client/RemoteContainer.d.ts +58 -0
  14. package/lib/client/RemoteContainer.d.ts.map +1 -0
  15. package/lib/client/RemoteContainer.js +161 -0
  16. package/lib/client/RemotePages.d.ts +48 -0
  17. package/lib/client/RemotePages.d.ts.map +1 -0
  18. package/lib/client/RemotePages.js +168 -0
  19. package/lib/client/UrlNode.d.ts +18 -0
  20. package/lib/client/UrlNode.d.ts.map +1 -0
  21. package/lib/client/UrlNode.js +162 -0
  22. package/lib/client/helpers.d.ts +17 -0
  23. package/lib/client/helpers.d.ts.map +1 -0
  24. package/lib/client/helpers.js +108 -0
  25. package/lib/client/useMFClient.d.ts +25 -0
  26. package/lib/client/useMFClient.d.ts.map +1 -0
  27. package/lib/client/useMFClient.js +79 -0
  28. package/lib/client/useMFRemote.d.ts +17 -0
  29. package/lib/client/useMFRemote.d.ts.map +1 -0
  30. package/lib/client/useMFRemote.js +72 -0
  31. package/lib/loaders/UrlNode.js +215 -0
  32. package/lib/loaders/helpers.js +10 -3
  33. package/lib/loaders/nextPageMapLoader.js +81 -17
  34. package/lib/loaders/patchNextClientPageLoader.js +53 -0
  35. package/lib/plugins/DevHmrFixInvalidPongPlugin.js +65 -0
  36. package/lib/utils.js +7 -3
  37. package/package.json +21 -4
  38. package/tsconfig.json +33 -0
Binary file
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var _commonjsHelpers = require('./_commonjsHelpers.js');
4
+ var UrlNode = require('../loaders/UrlNode.js');
5
+
6
+ var require$$2 = /*@__PURE__*/_commonjsHelpers.getAugmentedNamespace(UrlNode);
7
+
8
+ module.exports = require$$2;
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ function getAugmentedNamespace(n) {
6
+ var f = n.default;
7
+ if (typeof f == "function") {
8
+ var a = function () {
9
+ return f.apply(this, arguments);
10
+ };
11
+ a.prototype = f.prototype;
12
+ } else a = {};
13
+ Object.defineProperty(a, '__esModule', {value: true});
14
+ Object.keys(n).forEach(function (k) {
15
+ var d = Object.getOwnPropertyDescriptor(n, k);
16
+ Object.defineProperty(a, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () {
19
+ return n[k];
20
+ }
21
+ });
22
+ });
23
+ return a;
24
+ }
25
+
26
+ exports.getAugmentedNamespace = getAugmentedNamespace;
@@ -0,0 +1,101 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /******************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+
20
+ function __awaiter(thisArg, _arguments, P, generator) {
21
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
22
+ return new (P || (P = Promise))(function (resolve, reject) {
23
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
24
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
25
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
26
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
27
+ });
28
+ }
29
+
30
+ function __generator(thisArg, body) {
31
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
32
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
33
+ function verb(n) { return function (v) { return step([n, v]); }; }
34
+ function step(op) {
35
+ if (f) throw new TypeError("Generator is already executing.");
36
+ while (_) try {
37
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
38
+ if (y = 0, t) op = [op[0] & 2, t.value];
39
+ switch (op[0]) {
40
+ case 0: case 1: t = op; break;
41
+ case 4: _.label++; return { value: op[1], done: false };
42
+ case 5: _.label++; y = op[1]; op = [0]; continue;
43
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
44
+ default:
45
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
46
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
47
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
48
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
49
+ if (t[2]) _.ops.pop();
50
+ _.trys.pop(); continue;
51
+ }
52
+ op = body.call(thisArg, _);
53
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
54
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
55
+ }
56
+ }
57
+
58
+ function __values(o) {
59
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
60
+ if (m) return m.call(o);
61
+ if (o && typeof o.length === "number") return {
62
+ next: function () {
63
+ if (o && i >= o.length) o = void 0;
64
+ return { value: o && o[i++], done: !o };
65
+ }
66
+ };
67
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
68
+ }
69
+
70
+ function __read(o, n) {
71
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
72
+ if (!m) return o;
73
+ var i = m.call(o), r, ar = [], e;
74
+ try {
75
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
76
+ }
77
+ catch (error) { e = { error: error }; }
78
+ finally {
79
+ try {
80
+ if (r && !r.done && (m = i["return"])) m.call(i);
81
+ }
82
+ finally { if (e) throw e.error; }
83
+ }
84
+ return ar;
85
+ }
86
+
87
+ function __spreadArray(to, from, pack) {
88
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
89
+ if (ar || !(i in from)) {
90
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
91
+ ar[i] = from[i];
92
+ }
93
+ }
94
+ return to.concat(ar || Array.prototype.slice.call(from));
95
+ }
96
+
97
+ exports.__awaiter = __awaiter;
98
+ exports.__generator = __generator;
99
+ exports.__read = __read;
100
+ exports.__spreadArray = __spreadArray;
101
+ exports.__values = __values;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var helpers = {};
6
+
7
+ exports.__exports = helpers;
@@ -0,0 +1,7 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var nextPageMapLoader = {exports: {}};
6
+
7
+ exports.nextPageMapLoader = nextPageMapLoader;
@@ -0,0 +1,28 @@
1
+ import { RemotePages } from './RemotePages';
2
+ /**
3
+ * Class which provides combined sorted list of local and remote routes.
4
+ */
5
+ export declare class CombinedPages {
6
+ /** Computable list of available local & remote pages in proper sorted order. */
7
+ private sortedPageCache;
8
+ /** List of pages that belongs to the current host application */
9
+ private localPagesCache;
10
+ /** List of known remote pages this list might be extent during runtime */
11
+ private remotePagesCache;
12
+ /** Nextjs getter which obtained from patchNextClientPageLoader */
13
+ private localPagesGetter;
14
+ /** Loader of remote pages */
15
+ private remotePages;
16
+ constructor(localPagesGetter: () => Promise<string[]>, remotePages: RemotePages);
17
+ /**
18
+ * Check that provided route belongs to host application
19
+ */
20
+ isLocalRoute(route: string): Promise<boolean>;
21
+ /**
22
+ * Return sorted list of local & remotes routes.
23
+ * This method is used in patchNextClientPageLoader
24
+ * for patching nextjs' getPageList method.
25
+ */
26
+ getPageList(): Promise<string[]>;
27
+ }
28
+ //# sourceMappingURL=CombinedPages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CombinedPages.d.ts","sourceRoot":"","sources":["../../src/client/CombinedPages.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C;;GAEG;AACH,qBAAa,aAAa;IACxB,gFAAgF;IAChF,OAAO,CAAC,eAAe,CAAW;IAElC,iEAAiE;IACjE,OAAO,CAAC,eAAe,CAAW;IAClC,0EAA0E;IAC1E,OAAO,CAAC,gBAAgB,CAAW;IACnC,kEAAkE;IAClE,OAAO,CAAC,gBAAgB,CAA0B;IAClD,8BAA8B;IAC9B,OAAO,CAAC,WAAW,CAAc;gBAG/B,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,EACzC,WAAW,EAAE,WAAW;IAM1B;;OAEG;IACG,YAAY,CAAC,KAAK,EAAE,MAAM;IAKhC;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAavC"}
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+ var helpers = require('./helpers.js');
7
+
8
+ /**
9
+ * Class which provides combined sorted list of local and remote routes.
10
+ */
11
+ var CombinedPages = /** @class */ (function () {
12
+ function CombinedPages(localPagesGetter, remotePages) {
13
+ this.localPagesGetter = localPagesGetter;
14
+ this.remotePages = remotePages;
15
+ }
16
+ /**
17
+ * Check that provided route belongs to host application
18
+ */
19
+ CombinedPages.prototype.isLocalRoute = function (route) {
20
+ return _tslib.__awaiter(this, void 0, void 0, function () {
21
+ var localPages;
22
+ return _tslib.__generator(this, function (_a) {
23
+ switch (_a.label) {
24
+ case 0: return [4 /*yield*/, this.localPagesGetter()];
25
+ case 1:
26
+ localPages = _a.sent();
27
+ return [2 /*return*/, localPages.includes(route)];
28
+ }
29
+ });
30
+ });
31
+ };
32
+ /**
33
+ * Return sorted list of local & remotes routes.
34
+ * This method is used in patchNextClientPageLoader
35
+ * for patching nextjs' getPageList method.
36
+ */
37
+ CombinedPages.prototype.getPageList = function () {
38
+ return _tslib.__awaiter(this, void 0, void 0, function () {
39
+ var localPages, remotePages;
40
+ return _tslib.__generator(this, function (_a) {
41
+ switch (_a.label) {
42
+ case 0: return [4 /*yield*/, this.localPagesGetter()];
43
+ case 1:
44
+ localPages = _a.sent();
45
+ remotePages = this.remotePages.getPageList();
46
+ if (localPages !== this.localPagesCache ||
47
+ remotePages !== this.remotePagesCache) {
48
+ this.localPagesCache = localPages;
49
+ this.remotePagesCache = remotePages;
50
+ this.sortedPageCache = helpers.sortNextPages(_tslib.__spreadArray(_tslib.__spreadArray([], _tslib.__read(localPages), false), _tslib.__read(remotePages), false));
51
+ }
52
+ return [2 /*return*/, this.sortedPageCache];
53
+ }
54
+ });
55
+ });
56
+ };
57
+ return CombinedPages;
58
+ }());
59
+
60
+ exports.CombinedPages = CombinedPages;
@@ -0,0 +1,70 @@
1
+ import type PageLoader from 'next/dist/client/page-loader';
2
+ import EventEmitter from 'eventemitter3';
3
+ import { CombinedPages } from './CombinedPages';
4
+ import { RemotePages } from './RemotePages';
5
+ import { RemoteContainer } from './RemoteContainer';
6
+ declare type EventTypes = 'loadedRemoteRoute' | 'loadedLocalRoute';
7
+ /** Remote Container string eg `home@https://example.com/_next/static/chunks/remoteEntry.js` */
8
+ export declare type RemoteString = string;
9
+ /**
10
+ * The main class for Module Federation on the client side in runtime.
11
+ * Instance of this class is a Singleton and stored in `window.mf_client` variable.
12
+ */
13
+ export declare class MFClient {
14
+ /** List of registered remotes */
15
+ remotes: Record<RemoteString, RemoteContainer>;
16
+ /** Local & Remote pages sorted in correct order */
17
+ combinedPages: CombinedPages;
18
+ /** Remote pages loader */
19
+ remotePages: RemotePages;
20
+ /** EventEmitter which allows to subscribe on different events */
21
+ events: EventEmitter<EventTypes>;
22
+ /** Original nextjs PageLoader which passed by `patchNextClientPageLoader.js` */
23
+ private _nextPageLoader;
24
+ constructor(nextPageLoader: PageLoader);
25
+ /**
26
+ * This method returns sorted list of local and federated pages.
27
+ *
28
+ * `patchNextClientPageLoader` change vanilla PageLoader.getPageList() method:
29
+ * - exposes vanilla implementation as _getPageListOriginal()
30
+ * - and PageLoader.getPageList() starting call this method under the hood
31
+ */
32
+ getPageList(): Promise<string[]>;
33
+ /**
34
+ * Check that current browser pathname is served by federated remotes.
35
+ *
36
+ * Eg. if cleanPathname `/shop/nodkz/product123` and pageListFederated is ['/shop/nodkz/[...mee]']
37
+ * then this method will match federated dynamic route and return true.
38
+ *
39
+ * PS. This method is used by DevHmrFixInvalidPongPlugin (fix HMR page reloads in dev mode)
40
+ */
41
+ isFederatedPathname(cleanPathname: string): boolean;
42
+ /**
43
+ * Add remote entry to remotes registry of MFClient.
44
+ * This RemoteContainer will be used for loading remote pages.
45
+ *
46
+ * @remoteStr string - eg. `home@https://example.com/_next/static/chunks/remoteEntry.js`
47
+ */
48
+ registerRemote(remoteStr: RemoteString): RemoteContainer;
49
+ /**
50
+ * Convert browser pathname to NextJS route.
51
+ *
52
+ * /shop/products/123 -> /shop/products/[...id]
53
+ *
54
+ * For regular pages logic is simple (just match exact name).
55
+ * But for dynamic routes it's quite complicated - page list must be in specific order.
56
+ */
57
+ pathnameToRoute(cleanPathname: string): Promise<string | undefined>;
58
+ /**
59
+ * This method patch routeLoader.loadRoute() in runtime (on bootstrap).
60
+ * During the build it's quite complicated to do.
61
+ */
62
+ private _wrapLoadRoute;
63
+ /**
64
+ * This method patch routeLoader.whenEntrypoint() in runtime (on bootstrap).
65
+ * During the build it's quite complicated to do.
66
+ */
67
+ private _wrapWhenEntrypoint;
68
+ }
69
+ export {};
70
+ //# sourceMappingURL=MFClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MFClient.d.ts","sourceRoot":"","sources":["../../src/client/MFClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,8BAA8B,CAAC;AAC3D,OAAO,YAAY,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,aAAK,UAAU,GAAG,mBAAmB,GAAG,kBAAkB,CAAC;AAE3D,+FAA+F;AAC/F,oBAAY,YAAY,GAAG,MAAM,CAAC;AAElC;;;GAGG;AACH,qBAAa,QAAQ;IACnB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,CAAM;IACpD,mDAAmD;IACnD,aAAa,EAAE,aAAa,CAAC;IAC7B,0BAA0B;IAC1B,WAAW,EAAE,WAAW,CAAC;IACzB,iEAAiE;IACjE,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACjC,gFAAgF;IAChF,OAAO,CAAC,eAAe,CAAa;gBAExB,cAAc,EAAE,UAAU;IAuBtC;;;;;;OAMG;IACG,WAAW;IAIjB;;;;;;;OAOG;IACH,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAInD;;;;;OAKG;IACH,cAAc,CAAC,SAAS,EAAE,YAAY;IAMtC;;;;;;;OAOG;IACG,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKzE;;;OAGG;IACH,OAAO,CAAC,cAAc;IAoCtB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;CAwD5B"}
@@ -0,0 +1,197 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../_virtual/_tslib.js');
6
+ var EventEmitter = require('eventemitter3');
7
+ var helpers = require('./helpers.js');
8
+ var CombinedPages = require('./CombinedPages.js');
9
+ var RemotePages = require('./RemotePages.js');
10
+ var RemoteContainer = require('./RemoteContainer.js');
11
+
12
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
13
+
14
+ var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
15
+
16
+ /**
17
+ * The main class for Module Federation on the client side in runtime.
18
+ * Instance of this class is a Singleton and stored in `window.mf_client` variable.
19
+ */
20
+ var MFClient = /** @class */ (function () {
21
+ function MFClient(nextPageLoader) {
22
+ var _this = this;
23
+ var _a, _b;
24
+ /** List of registered remotes */
25
+ this.remotes = {};
26
+ this._nextPageLoader = nextPageLoader;
27
+ this.events = new EventEmitter__default["default"]();
28
+ var cfg = ((_b = (_a = global === null || global === void 0 ? void 0 : global.__NEXT_DATA__) === null || _a === void 0 ? void 0 : _a.props) === null || _b === void 0 ? void 0 : _b.mfRoutes) || {};
29
+ this.remotePages = new RemotePages.RemotePages();
30
+ Object.keys(cfg).forEach(function (remoteStr) {
31
+ var remote = _this.registerRemote(remoteStr);
32
+ _this.remotePages.addRoutes(cfg[remoteStr], remote);
33
+ });
34
+ this.combinedPages = new CombinedPages.CombinedPages(this._nextPageLoader._getPageListOriginal.bind(this._nextPageLoader), this.remotePages);
35
+ this._wrapLoadRoute(nextPageLoader);
36
+ this._wrapWhenEntrypoint(nextPageLoader);
37
+ }
38
+ /**
39
+ * This method returns sorted list of local and federated pages.
40
+ *
41
+ * `patchNextClientPageLoader` change vanilla PageLoader.getPageList() method:
42
+ * - exposes vanilla implementation as _getPageListOriginal()
43
+ * - and PageLoader.getPageList() starting call this method under the hood
44
+ */
45
+ MFClient.prototype.getPageList = function () {
46
+ return _tslib.__awaiter(this, void 0, void 0, function () {
47
+ return _tslib.__generator(this, function (_a) {
48
+ return [2 /*return*/, this.combinedPages.getPageList()];
49
+ });
50
+ });
51
+ };
52
+ /**
53
+ * Check that current browser pathname is served by federated remotes.
54
+ *
55
+ * Eg. if cleanPathname `/shop/nodkz/product123` and pageListFederated is ['/shop/nodkz/[...mee]']
56
+ * then this method will match federated dynamic route and return true.
57
+ *
58
+ * PS. This method is used by DevHmrFixInvalidPongPlugin (fix HMR page reloads in dev mode)
59
+ */
60
+ MFClient.prototype.isFederatedPathname = function (cleanPathname) {
61
+ return !!this.remotePages.routeToRemote(cleanPathname);
62
+ };
63
+ /**
64
+ * Add remote entry to remotes registry of MFClient.
65
+ * This RemoteContainer will be used for loading remote pages.
66
+ *
67
+ * @remoteStr string - eg. `home@https://example.com/_next/static/chunks/remoteEntry.js`
68
+ */
69
+ MFClient.prototype.registerRemote = function (remoteStr) {
70
+ var remote = RemoteContainer.RemoteContainer.createSingleton(remoteStr);
71
+ this.remotes[remote.global] = remote;
72
+ return remote;
73
+ };
74
+ /**
75
+ * Convert browser pathname to NextJS route.
76
+ *
77
+ * /shop/products/123 -> /shop/products/[...id]
78
+ *
79
+ * For regular pages logic is simple (just match exact name).
80
+ * But for dynamic routes it's quite complicated - page list must be in specific order.
81
+ */
82
+ MFClient.prototype.pathnameToRoute = function (cleanPathname) {
83
+ return _tslib.__awaiter(this, void 0, void 0, function () {
84
+ var routes;
85
+ return _tslib.__generator(this, function (_a) {
86
+ switch (_a.label) {
87
+ case 0: return [4 /*yield*/, this.getPageList()];
88
+ case 1:
89
+ routes = _a.sent();
90
+ return [2 /*return*/, helpers.pathnameToRoute(cleanPathname, routes)];
91
+ }
92
+ });
93
+ });
94
+ };
95
+ /**
96
+ * This method patch routeLoader.loadRoute() in runtime (on bootstrap).
97
+ * During the build it's quite complicated to do.
98
+ */
99
+ MFClient.prototype._wrapLoadRoute = function (nextPageLoader) {
100
+ var _this = this;
101
+ var _a;
102
+ if (!((_a = nextPageLoader === null || nextPageLoader === void 0 ? void 0 : nextPageLoader.routeLoader) === null || _a === void 0 ? void 0 : _a.loadRoute)) {
103
+ throw new Error('[nextjs-mf] Cannot wrap `pageLoader.routeLoader.loadRoute()` with custom logic.');
104
+ }
105
+ var routeLoader = nextPageLoader.routeLoader;
106
+ // if _loadRouteOriginal does not initialized then take original loadRoute method
107
+ if (!routeLoader._loadRouteOriginal) {
108
+ routeLoader._loadRouteOriginal = routeLoader.loadRoute.bind(routeLoader);
109
+ }
110
+ // replace loadRoute logic
111
+ routeLoader.loadRoute = function (route, prefetch) { return _tslib.__awaiter(_this, void 0, void 0, function () {
112
+ var routeInfo;
113
+ return _tslib.__generator(this, function (_a) {
114
+ switch (_a.label) {
115
+ case 0: return [4 /*yield*/, this.combinedPages.isLocalRoute(route)];
116
+ case 1:
117
+ if (!_a.sent()) return [3 /*break*/, 3];
118
+ return [4 /*yield*/, routeLoader._loadRouteOriginal(route)];
119
+ case 2:
120
+ routeInfo = _a.sent();
121
+ this.events.emit('loadedLocalRoute', routeInfo, prefetch);
122
+ return [3 /*break*/, 5];
123
+ case 3: return [4 /*yield*/, this.remotePages.getRouteInfo(route)];
124
+ case 4:
125
+ routeInfo = _a.sent();
126
+ this.events.emit('loadedRemoteRoute', routeInfo, prefetch, this.remotePages.routeToRemote(route));
127
+ _a.label = 5;
128
+ case 5: return [2 /*return*/, routeInfo];
129
+ }
130
+ });
131
+ }); };
132
+ };
133
+ /**
134
+ * This method patch routeLoader.whenEntrypoint() in runtime (on bootstrap).
135
+ * During the build it's quite complicated to do.
136
+ */
137
+ MFClient.prototype._wrapWhenEntrypoint = function (nextPageLoader) {
138
+ var _this = this;
139
+ var _a;
140
+ if (!((_a = nextPageLoader.routeLoader) === null || _a === void 0 ? void 0 : _a.whenEntrypoint)) {
141
+ throw new Error('[nextjs-mf] Cannot wrap `pageLoader.routeLoader.whenEntrypoint()` with custom logic.');
142
+ }
143
+ var routeLoader = nextPageLoader.routeLoader;
144
+ // if _whenEntrypointOriginal does not initialized then take original loadRoute method
145
+ if (!routeLoader._whenEntrypointOriginal) {
146
+ routeLoader._whenEntrypointOriginal =
147
+ routeLoader.whenEntrypoint.bind(routeLoader);
148
+ }
149
+ // replace routeLoader.whenEntrypoint logic
150
+ routeLoader.whenEntrypoint = function (route) { return _tslib.__awaiter(_this, void 0, void 0, function () {
151
+ var route_1, awaitRemotes_1, routeInfo_1, routeInfo;
152
+ var _this = this;
153
+ return _tslib.__generator(this, function (_a) {
154
+ switch (_a.label) {
155
+ case 0:
156
+ if (!(route === '/_error')) return [3 /*break*/, 6];
157
+ return [4 /*yield*/, this.pathnameToRoute(window.location.pathname)];
158
+ case 1:
159
+ route_1 = _a.sent();
160
+ if (!!route_1) return [3 /*break*/, 4];
161
+ awaitRemotes_1 = [];
162
+ Object.values(this.remotes).forEach(function (remote) {
163
+ if (!remote.isLoaded()) {
164
+ awaitRemotes_1.push(remote
165
+ .getContainer()
166
+ .then(function () { return _this.remotePages.loadRemotePageMap(remote); })
167
+ .catch(function () { return null; }));
168
+ }
169
+ });
170
+ return [4 /*yield*/, Promise.all(awaitRemotes_1)];
171
+ case 2:
172
+ _a.sent();
173
+ return [4 /*yield*/, this.pathnameToRoute(window.location.pathname)];
174
+ case 3:
175
+ route_1 = _a.sent();
176
+ _a.label = 4;
177
+ case 4:
178
+ if (!route_1) return [3 /*break*/, 6];
179
+ // TODO: fix router properties for the first page load of federated page http://localhost:3000/shop/products/B
180
+ console.warn('replace entrypoint /_error by', route_1);
181
+ return [4 /*yield*/, this.remotePages.getRouteInfo(route_1)];
182
+ case 5:
183
+ routeInfo_1 = _a.sent();
184
+ this.events.emit('loadedRemoteRoute', routeInfo_1, false, this.remotePages.routeToRemote(route_1));
185
+ return [2 /*return*/, routeInfo_1];
186
+ case 6: return [4 /*yield*/, routeLoader._whenEntrypointOriginal(route)];
187
+ case 7:
188
+ routeInfo = _a.sent();
189
+ return [2 /*return*/, routeInfo];
190
+ }
191
+ });
192
+ }); };
193
+ };
194
+ return MFClient;
195
+ }());
196
+
197
+ exports.MFClient = MFClient;
@@ -0,0 +1,58 @@
1
+ import EventEmitter from 'eventemitter3';
2
+ declare type EventTypes = 'loadStart' | 'loadComplete' | 'loadError';
3
+ export declare type WebpackRemoteContainer = {
4
+ get(modulePath: ModulePath): () => any;
5
+ };
6
+ export declare type NextRoute = string;
7
+ export declare type ModulePath = string;
8
+ export declare type RemoteData = {
9
+ global: string;
10
+ url: string;
11
+ };
12
+ export declare type PageMap = Record<NextRoute, ModulePath>;
13
+ /**
14
+ * This is a Lazy loader of webpack remote container with some NextJS-specific helper methods.
15
+ *
16
+ * It provides the ability to register remote, and load & init it on the first use.
17
+ */
18
+ export declare class RemoteContainer {
19
+ global: string;
20
+ url: string;
21
+ container: WebpackRemoteContainer | undefined;
22
+ pageMap: PageMap | undefined;
23
+ error?: Error;
24
+ events: EventEmitter<EventTypes>;
25
+ static instances: Record<string, RemoteContainer>;
26
+ /**
27
+ * Create or reuse existed remote entry.
28
+ *
29
+ * Be careful, Singleton pattern does not work well in webpack builds,
30
+ * because one module may be copied between different chunks. In such a way
31
+ * you obtain several lists of instances.
32
+ */
33
+ static createSingleton(remote: string | RemoteData): RemoteContainer;
34
+ constructor(opts: RemoteData);
35
+ /**
36
+ * Check is the current remoteEntry.js loaded or not
37
+ */
38
+ isLoaded(): boolean;
39
+ /**
40
+ * Returns initialized webpack RemoteContainer.
41
+ * If its' script does not loaded - then load & init it firstly.
42
+ */
43
+ getContainer(): Promise<WebpackRemoteContainer>;
44
+ /**
45
+ * Return remote module from container.
46
+ * If you provide `exportName` it automatically return exact property value from module.
47
+ *
48
+ * @example
49
+ * remote.getModule('./pages/index', 'default')
50
+ */
51
+ getModule(modulePath: string, exportName?: string): Promise<any>;
52
+ /**
53
+ * Retrieve registered nextjs' routes from remote app
54
+ */
55
+ getPageMap(): Promise<PageMap | undefined>;
56
+ }
57
+ export {};
58
+ //# sourceMappingURL=RemoteContainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoteContainer.d.ts","sourceRoot":"","sources":["../../src/client/RemoteContainer.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAC;AAGzC,aAAK,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,WAAW,CAAC;AAE7D,oBAAY,sBAAsB,GAAG;IACnC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,CAAC;CACxC,CAAC;AACF,oBAAY,SAAS,GAAG,MAAM,CAAC;AAC/B,oBAAY,UAAU,GAAG,MAAM,CAAC;AAChC,oBAAY,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AACF,oBAAY,OAAO,GAAG,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;AAEpD;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IAEjC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAM;IAEvD;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;gBA8BtC,IAAI,EAAE,UAAU;IAM5B;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,sBAAsB,CAAC;IA2BrD;;;;;;OAMG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAYvD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;CAiBjD"}