@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.
- package/lib/NextFederationPlugin2.js +0 -0
- package/lib/_virtual/UrlNode.js +8 -0
- package/lib/_virtual/_commonjsHelpers.js +26 -0
- package/lib/_virtual/_tslib.js +101 -0
- package/lib/_virtual/helpers.js +7 -0
- package/lib/_virtual/nextPageMapLoader.js +7 -0
- package/lib/client/CombinedPages.d.ts +28 -0
- package/lib/client/CombinedPages.d.ts.map +1 -0
- package/lib/client/CombinedPages.js +60 -0
- package/lib/client/MFClient.d.ts +70 -0
- package/lib/client/MFClient.d.ts.map +1 -0
- package/lib/client/MFClient.js +197 -0
- package/lib/client/RemoteContainer.d.ts +58 -0
- package/lib/client/RemoteContainer.d.ts.map +1 -0
- package/lib/client/RemoteContainer.js +161 -0
- package/lib/client/RemotePages.d.ts +48 -0
- package/lib/client/RemotePages.d.ts.map +1 -0
- package/lib/client/RemotePages.js +168 -0
- package/lib/client/UrlNode.d.ts +18 -0
- package/lib/client/UrlNode.d.ts.map +1 -0
- package/lib/client/UrlNode.js +162 -0
- package/lib/client/helpers.d.ts +17 -0
- package/lib/client/helpers.d.ts.map +1 -0
- package/lib/client/helpers.js +108 -0
- package/lib/client/useMFClient.d.ts +25 -0
- package/lib/client/useMFClient.d.ts.map +1 -0
- package/lib/client/useMFClient.js +79 -0
- package/lib/client/useMFRemote.d.ts +17 -0
- package/lib/client/useMFRemote.d.ts.map +1 -0
- package/lib/client/useMFRemote.js +72 -0
- package/lib/loaders/UrlNode.js +215 -0
- package/lib/loaders/helpers.js +10 -3
- package/lib/loaders/nextPageMapLoader.js +81 -17
- package/lib/loaders/patchNextClientPageLoader.js +53 -0
- package/lib/plugins/DevHmrFixInvalidPongPlugin.js +65 -0
- package/lib/utils.js +7 -3
- package/package.json +21 -4
- package/tsconfig.json +33 -0
|
@@ -1,5 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var nextPageMapLoader$1 = require('../_virtual/nextPageMapLoader.js');
|
|
4
|
+
var require$$0 = require('fast-glob');
|
|
5
|
+
var require$$1 = require('fs');
|
|
6
|
+
var UrlNode$1 = require('../_virtual/UrlNode.js');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
|
|
11
|
+
var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
|
|
12
|
+
|
|
13
|
+
const fg = require$$0__default["default"];
|
|
14
|
+
const fs = require$$1__default["default"];
|
|
15
|
+
|
|
16
|
+
// TODO: import UrlNode from ./client folder when whole project migrates on TypeScript (but right now using JS copy of this class)
|
|
17
|
+
// const UrlNode = require('../client/UrlNode').UrlNode;
|
|
18
|
+
const UrlNode = UrlNode$1.UrlNode;
|
|
3
19
|
|
|
4
20
|
/**
|
|
5
21
|
* Webpack loader which prepares MF map for NextJS pages
|
|
@@ -7,17 +23,22 @@ const fs = require('fs');
|
|
|
7
23
|
* @type {(this: import("webpack").LoaderContext<{}>, content: string) => string>}
|
|
8
24
|
*/
|
|
9
25
|
function nextPageMapLoader() {
|
|
10
|
-
const pages = getNextPages(this.rootContext);
|
|
11
|
-
const pageMap = preparePageMap(pages);
|
|
12
|
-
|
|
13
26
|
// const [pagesRoot] = getNextPagesRoot(this.rootContext);
|
|
14
27
|
// this.addContextDependency(pagesRoot);
|
|
28
|
+
const opts = this.getOptions();
|
|
29
|
+
const pages = getNextPages(this.rootContext);
|
|
15
30
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
31
|
+
let result = '';
|
|
32
|
+
if (Object.hasOwnProperty.call(opts, 'v2')) {
|
|
33
|
+
result = preparePageMapV2(pages);
|
|
34
|
+
} else {
|
|
35
|
+
result = preparePageMap(pages);
|
|
36
|
+
}
|
|
19
37
|
|
|
20
|
-
this.callback(
|
|
38
|
+
this.callback(
|
|
39
|
+
null,
|
|
40
|
+
`module.exports = { default: ${JSON.stringify(result)} };`
|
|
41
|
+
);
|
|
21
42
|
}
|
|
22
43
|
|
|
23
44
|
/**
|
|
@@ -38,6 +59,7 @@ function exposeNextjsPages(cwd) {
|
|
|
38
59
|
|
|
39
60
|
const exposesWithPageMap = {
|
|
40
61
|
'./pages-map': `${__filename}!${__filename}`,
|
|
62
|
+
'./pages-map-v2': `${__filename}?v2!${__filename}`,
|
|
41
63
|
...pageModulesMap,
|
|
42
64
|
};
|
|
43
65
|
|
|
@@ -113,17 +135,59 @@ function sanitizePagePath(item) {
|
|
|
113
135
|
function preparePageMap(pages) {
|
|
114
136
|
const result = {};
|
|
115
137
|
|
|
116
|
-
pages.
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
138
|
+
const clearedPages = pages.map((p) => `/${sanitizePagePath(p)}`);
|
|
139
|
+
|
|
140
|
+
// getSortedRoutes @see https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
|
|
141
|
+
const root = new UrlNode();
|
|
142
|
+
clearedPages.forEach((pagePath) => root.insert(pagePath));
|
|
143
|
+
// Smoosh will then sort those sublevels up to the point where you get the correct route definition priority
|
|
144
|
+
const sortedPages = root.smoosh();
|
|
145
|
+
|
|
146
|
+
sortedPages.forEach((page) => {
|
|
147
|
+
let key = page
|
|
148
|
+
.replace(/\[\.\.\.[^\]]+\]/gi, '*')
|
|
149
|
+
.replace(/\[([^\]]+)\]/gi, ':$1');
|
|
121
150
|
key = key.replace(/^\/pages\//, '/').replace(/\/index$/, '') || '/';
|
|
122
|
-
result[key] =
|
|
151
|
+
result[key] = `.${page}`;
|
|
123
152
|
});
|
|
124
153
|
|
|
125
154
|
return result;
|
|
126
155
|
}
|
|
127
156
|
|
|
128
|
-
|
|
129
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Create MF list of NextJS pages
|
|
159
|
+
*
|
|
160
|
+
* From
|
|
161
|
+
* ['pages/index.tsx', 'pages/storage/[...slug].tsx', 'pages/storage/index.tsx']
|
|
162
|
+
* Getting the following map
|
|
163
|
+
* {
|
|
164
|
+
* '/': './pages/index',
|
|
165
|
+
* '/storage': './pages/storage/index'
|
|
166
|
+
* '/storage/[...slug]': './pages/storage/[...slug]',
|
|
167
|
+
* }
|
|
168
|
+
*
|
|
169
|
+
* @type {(pages: string[]) => {[key: string]: string}}
|
|
170
|
+
*/
|
|
171
|
+
function preparePageMapV2(pages) {
|
|
172
|
+
const result = {};
|
|
173
|
+
|
|
174
|
+
const clearedPages = pages.map((p) => `/${sanitizePagePath(p)}`);
|
|
175
|
+
|
|
176
|
+
// getSortedRoutes @see https://github.com/vercel/next.js/blob/canary/packages/next/shared/lib/router/utils/sorted-routes.ts
|
|
177
|
+
const root = new UrlNode();
|
|
178
|
+
clearedPages.forEach((pagePath) => root.insert(pagePath));
|
|
179
|
+
// Smoosh will then sort those sublevels up to the point where you get the correct route definition priority
|
|
180
|
+
const sortedPages = root.smoosh();
|
|
181
|
+
|
|
182
|
+
sortedPages.forEach((page) => {
|
|
183
|
+
let key = page.replace(/^\/pages\//, '/').replace(/\/index$/, '') || '/';
|
|
184
|
+
result[key] = `.${page}`;
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
nextPageMapLoader$1.nextPageMapLoader.exports = nextPageMapLoader;
|
|
191
|
+
nextPageMapLoader$1.nextPageMapLoader.exports.exposeNextjsPages = exposeNextjsPages;
|
|
192
|
+
|
|
193
|
+
module.exports = nextPageMapLoader$1.nextPageMapLoader.exports;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This webpack loader patches next/dist/client/page-loader.js file.
|
|
5
|
+
* Also it requires `include-defaults.js` with required shared libs
|
|
6
|
+
*
|
|
7
|
+
* @type {(this: import("webpack").LoaderContext<{}>, content: string) => string>}
|
|
8
|
+
*/
|
|
9
|
+
function patchNextClientPageLoader(content) {
|
|
10
|
+
if (content.includes('MFClient')) {
|
|
11
|
+
// If MFClient already applied then skip patch
|
|
12
|
+
return content;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// avoid absolute paths as they break hashing when the root for the project is moved
|
|
16
|
+
// @see https://webpack.js.org/contribute/writing-a-loader/#absolute-paths
|
|
17
|
+
const pathIncludeDefaults = path.relative(
|
|
18
|
+
this.context,
|
|
19
|
+
path.resolve(__dirname, '../include-defaults.js')
|
|
20
|
+
);
|
|
21
|
+
const pathMFClient = path.relative(
|
|
22
|
+
this.context,
|
|
23
|
+
path.resolve(__dirname, '../client/MFClient.js')
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
patchedContent = content.replace(
|
|
27
|
+
'exports.default = PageLoader;',
|
|
28
|
+
`
|
|
29
|
+
require(${JSON.stringify(pathIncludeDefaults)});
|
|
30
|
+
const MFClient = require(${JSON.stringify(pathMFClient)}).MFClient;
|
|
31
|
+
|
|
32
|
+
class PageLoaderExtended extends PageLoader {
|
|
33
|
+
constructor(buildId, assetPrefix) {
|
|
34
|
+
super(buildId, assetPrefix);
|
|
35
|
+
global.mf_client = new MFClient(this);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_getPageListOriginal() {
|
|
39
|
+
return super.getPageList();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getPageList() {
|
|
43
|
+
return global.mf_client.getPageList();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.default = PageLoaderExtended;
|
|
47
|
+
`
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
return patchedContent;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = patchNextClientPageLoader;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* If HMR through websocket received {"invalid":true, "event":"pong"} event
|
|
5
|
+
* then pages reloads. But for federated page this is unwanted behavior.
|
|
6
|
+
*
|
|
7
|
+
* So this plugin in DEV mode disables page.reload() in HMR for federated pages.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
class DevHmrFixInvalidPongPlugin {
|
|
11
|
+
/**
|
|
12
|
+
* Apply the plugin
|
|
13
|
+
* @param {import("webpack").Compiler} compiler the compiler instance
|
|
14
|
+
* @returns {void}
|
|
15
|
+
*/
|
|
16
|
+
apply(compiler) {
|
|
17
|
+
const webpack = compiler.webpack;
|
|
18
|
+
|
|
19
|
+
compiler.hooks.thisCompilation.tap(
|
|
20
|
+
'DevHmrFixInvalidPongPlugin',
|
|
21
|
+
(compilation) => {
|
|
22
|
+
compilation.hooks.processAssets.tap(
|
|
23
|
+
{
|
|
24
|
+
name: 'DevHmrFixInvalidPongPlugin',
|
|
25
|
+
state: compilation.constructor.PROCESS_ASSETS_STAGE_PRE_PROCESS,
|
|
26
|
+
},
|
|
27
|
+
(assets) => {
|
|
28
|
+
Object.keys(assets).forEach((filename) => {
|
|
29
|
+
if (filename.endsWith('/main.js')) {
|
|
30
|
+
const asset = compilation.getAsset(filename);
|
|
31
|
+
const newSource = asset.source.source().replace(
|
|
32
|
+
new RegExp(
|
|
33
|
+
escapeRegExp(
|
|
34
|
+
'if (payload.event === \\"pong\\" && payload.invalid && !self.__NEXT_DATA__.err) {'
|
|
35
|
+
),
|
|
36
|
+
'g'
|
|
37
|
+
),
|
|
38
|
+
`if (payload.event === \\"pong\\" && payload.invalid && !self.__NEXT_DATA__.err) {
|
|
39
|
+
if (window.mf_client && window.mf_client.isFederatedPathname(window.location.pathname)) return;
|
|
40
|
+
`.replaceAll('\n', '\\n')
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const updatedAsset = new webpack.sources.RawSource(newSource);
|
|
44
|
+
|
|
45
|
+
if (asset) {
|
|
46
|
+
compilation.updateAsset(filename, updatedAsset);
|
|
47
|
+
} else {
|
|
48
|
+
compilation.emitAsset(filename, updatedAsset);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function escapeRegExp(string) {
|
|
60
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
var DevHmrFixInvalidPongPlugin_1 = DevHmrFixInvalidPongPlugin;
|
|
64
|
+
|
|
65
|
+
module.exports = DevHmrFixInvalidPongPlugin_1;
|
package/lib/utils.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
1
5
|
const remoteVars = process.env.REMOTES || {};
|
|
2
6
|
|
|
3
7
|
const runtimeRemotes = Object.entries(remoteVars).reduce(function (acc, item) {
|
|
@@ -13,8 +17,6 @@ const runtimeRemotes = Object.entries(remoteVars).reduce(function (acc, item) {
|
|
|
13
17
|
return acc;
|
|
14
18
|
}, {});
|
|
15
19
|
|
|
16
|
-
module.exports.remotes = runtimeRemotes;
|
|
17
|
-
|
|
18
20
|
/**
|
|
19
21
|
* Return initialized remote container by remote's key or its runtime remote item data.
|
|
20
22
|
*
|
|
@@ -94,4 +96,6 @@ function injectScript(keyOrRuntimeRemoteItem) {
|
|
|
94
96
|
});
|
|
95
97
|
}
|
|
96
98
|
|
|
97
|
-
|
|
99
|
+
var injectScript_1 = injectScript;
|
|
100
|
+
|
|
101
|
+
exports.injectScript = injectScript_1;
|
package/package.json
CHANGED
|
@@ -1,33 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"public": true,
|
|
3
3
|
"name": "@module-federation/nextjs-mf",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.3.0",
|
|
5
5
|
"description": "Module Federation helper for NextJS",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"types": "lib/index.d.ts",
|
|
8
8
|
"repository": "https://github.com/module-federation/nextjs-mf",
|
|
9
9
|
"author": "Zack Jackson <zackary.l.jackson@gmail.com>",
|
|
10
|
+
"contributors": [
|
|
11
|
+
"Pavel Chertorogov, nodkz <pavel.chertorogov@gmail.com> (www.ps.kz)"
|
|
12
|
+
],
|
|
10
13
|
"license": "MIT",
|
|
11
14
|
"scripts": {
|
|
12
|
-
"demo": "
|
|
15
|
+
"demo": "sleep 3 && cd demo && yarn install && yarn dev",
|
|
16
|
+
"dev": "rm -rf lib && concurrently \"yarn sync-files --watch\" \"yarn compile --watch\" \"yarn demo\"",
|
|
13
17
|
"prettier": "prettier --write \"**/*.{js,json,md,ts,tsx}\"",
|
|
14
|
-
"
|
|
18
|
+
"sync-files": "cpx \"src/**/*.js\" lib/",
|
|
19
|
+
"compile": "rollup -c",
|
|
20
|
+
"build": "rm -rf lib && yarn sync-files && yarn compile",
|
|
15
21
|
"prepublishOnly": "yarn build"
|
|
16
22
|
},
|
|
17
23
|
"dependencies": {
|
|
18
24
|
"chalk": "^4.0.0",
|
|
25
|
+
"eventemitter3": "^4.0.7",
|
|
19
26
|
"fast-glob": "^3.2.11"
|
|
20
27
|
},
|
|
21
28
|
"devDependencies": {
|
|
22
29
|
"@rollup/plugin-commonjs": "^22.0.2",
|
|
23
30
|
"@rollup/plugin-multi-entry": "^4.1.0",
|
|
24
31
|
"@rollup/plugin-node-resolve": "^13.3.0",
|
|
25
|
-
"
|
|
32
|
+
"@types/react": "^18.0.19",
|
|
33
|
+
"concurrently": "^7.3.0",
|
|
34
|
+
"cpx": "^1.5.0",
|
|
35
|
+
"next": "12.2.2",
|
|
26
36
|
"prettier": "2.3.2",
|
|
37
|
+
"react": "^18.2.0",
|
|
27
38
|
"rollup": "^2.78.1",
|
|
28
39
|
"rollup-obfuscator": "^3.0.1",
|
|
29
40
|
"rollup-plugin-node-builtins": "^2.1.2",
|
|
30
41
|
"rollup-plugin-node-globals": "^1.4.0",
|
|
42
|
+
"rollup-plugin-typescript2": "^0.33.0",
|
|
43
|
+
"tslib": "^2.4.0",
|
|
44
|
+
"typescript": "^4.8.2",
|
|
31
45
|
"webpack": "5.45.1"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"react": "^17.0.0 || ^18.0.0"
|
|
32
49
|
}
|
|
33
50
|
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es5",
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"module": "ES2020",
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"downlevelIteration": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"strict": false,
|
|
13
|
+
"allowJs": true,
|
|
14
|
+
"strictBindCallApply": true,
|
|
15
|
+
"strictNullChecks": true,
|
|
16
|
+
"strictPropertyInitialization": false,
|
|
17
|
+
"suppressImplicitAnyIndexErrors": true,
|
|
18
|
+
"importHelpers": false,
|
|
19
|
+
"noImplicitAny": true,
|
|
20
|
+
"noImplicitReturns": true,
|
|
21
|
+
"noImplicitThis": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUnusedParameters": false,
|
|
24
|
+
"noUnusedLocals": false,
|
|
25
|
+
"noEmitOnError": false,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"skipLibCheck": true,
|
|
28
|
+
"lib": ["dom", "ESNext"],
|
|
29
|
+
"jsx": "react",
|
|
30
|
+
},
|
|
31
|
+
"exclude": ["node_modules"],
|
|
32
|
+
"include": ["src/client/**/*"]
|
|
33
|
+
}
|