@module-federation/node 0.0.0-chore-bump-node-22-20260710161714
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/LICENSE +21 -0
- package/README.md +235 -0
- package/dist/_virtual/_rolldown/runtime.js +31 -0
- package/dist/_virtual/_rolldown/runtime.mjs +8 -0
- package/dist/plugins/ChunkCorrelationPlugin.js +308 -0
- package/dist/plugins/ChunkCorrelationPlugin.js.map +1 -0
- package/dist/plugins/ChunkCorrelationPlugin.mjs +305 -0
- package/dist/plugins/ChunkCorrelationPlugin.mjs.map +1 -0
- package/dist/src/filesystem/stratagies.d.mts +21 -0
- package/dist/src/filesystem/stratagies.d.ts +21 -0
- package/dist/src/filesystem/stratagies.js +105 -0
- package/dist/src/filesystem/stratagies.js.map +1 -0
- package/dist/src/filesystem/stratagies.mjs +103 -0
- package/dist/src/filesystem/stratagies.mjs.map +1 -0
- package/dist/src/index.d.mts +8 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +16 -0
- package/dist/src/index.mjs +9 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.d.mts +12 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.d.ts +11 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.js +29 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.js.map +1 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.mjs +28 -0
- package/dist/src/plugins/AutomaticPublicPathPlugin.mjs.map +1 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.d.mts +5 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.d.ts +4 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.js +9 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.js.map +1 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.mjs +8 -0
- package/dist/src/plugins/ChunkCorrelationPlugin.mjs.map +1 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.d.mts +21 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.d.ts +20 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.js +71 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.js.map +1 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.mjs +70 -0
- package/dist/src/plugins/CommonJsChunkLoadingPlugin.mjs.map +1 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.d.mts +46 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.d.ts +45 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.js +112 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.js.map +1 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.mjs +111 -0
- package/dist/src/plugins/DynamicFilesystemChunkLoadingRuntimeModule.mjs.map +1 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.d.mts +17 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.d.ts +17 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.js +39 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.js.map +1 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.mjs +38 -0
- package/dist/src/plugins/EntryChunkTrackerPlugin.mjs.map +1 -0
- package/dist/src/plugins/NodeFederationPlugin.d.mts +54 -0
- package/dist/src/plugins/NodeFederationPlugin.d.ts +53 -0
- package/dist/src/plugins/NodeFederationPlugin.js +76 -0
- package/dist/src/plugins/NodeFederationPlugin.js.map +1 -0
- package/dist/src/plugins/NodeFederationPlugin.mjs +73 -0
- package/dist/src/plugins/NodeFederationPlugin.mjs.map +1 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.d.mts +15 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.d.ts +14 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.js +133 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.js.map +1 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.mjs +132 -0
- package/dist/src/plugins/RemotePublicPathRuntimeModule.mjs.map +1 -0
- package/dist/src/plugins/StreamingTargetPlugin.d.mts +32 -0
- package/dist/src/plugins/StreamingTargetPlugin.d.ts +31 -0
- package/dist/src/plugins/StreamingTargetPlugin.js +46 -0
- package/dist/src/plugins/StreamingTargetPlugin.js.map +1 -0
- package/dist/src/plugins/StreamingTargetPlugin.mjs +46 -0
- package/dist/src/plugins/StreamingTargetPlugin.mjs.map +1 -0
- package/dist/src/plugins/UniversalFederationPlugin.d.mts +49 -0
- package/dist/src/plugins/UniversalFederationPlugin.d.ts +48 -0
- package/dist/src/plugins/UniversalFederationPlugin.js +66 -0
- package/dist/src/plugins/UniversalFederationPlugin.js.map +1 -0
- package/dist/src/plugins/UniversalFederationPlugin.mjs +65 -0
- package/dist/src/plugins/UniversalFederationPlugin.mjs.map +1 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.d.mts +9 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.d.ts +8 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.js +25 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.js.map +1 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.mjs +23 -0
- package/dist/src/plugins/UniverseEntryChunkTrackerPlugin.mjs.map +1 -0
- package/dist/src/plugins/webpackChunkUtilities.d.mts +55 -0
- package/dist/src/plugins/webpackChunkUtilities.d.ts +55 -0
- package/dist/src/plugins/webpackChunkUtilities.js +242 -0
- package/dist/src/plugins/webpackChunkUtilities.js.map +1 -0
- package/dist/src/plugins/webpackChunkUtilities.mjs +234 -0
- package/dist/src/plugins/webpackChunkUtilities.mjs.map +1 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.d.mts +7 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.d.ts +6 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.js +28 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.js.map +1 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.mjs +26 -0
- package/dist/src/recordDynamicRemoteEntryHashPlugin.mjs.map +1 -0
- package/dist/src/runtimePlugin.d.mts +27 -0
- package/dist/src/runtimePlugin.d.ts +27 -0
- package/dist/src/runtimePlugin.js +242 -0
- package/dist/src/runtimePlugin.js.map +1 -0
- package/dist/src/runtimePlugin.mjs +226 -0
- package/dist/src/runtimePlugin.mjs.map +1 -0
- package/dist/src/types/index.d.mts +8 -0
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.js +1 -0
- package/dist/src/types/index.mjs +1 -0
- package/dist/src/utils/flush-chunks.d.mts +15 -0
- package/dist/src/utils/flush-chunks.d.ts +15 -0
- package/dist/src/utils/flush-chunks.js +106 -0
- package/dist/src/utils/flush-chunks.js.map +1 -0
- package/dist/src/utils/flush-chunks.mjs +102 -0
- package/dist/src/utils/flush-chunks.mjs.map +1 -0
- package/dist/src/utils/hot-reload.d.mts +16 -0
- package/dist/src/utils/hot-reload.d.ts +16 -0
- package/dist/src/utils/hot-reload.js +206 -0
- package/dist/src/utils/hot-reload.js.map +1 -0
- package/dist/src/utils/hot-reload.mjs +195 -0
- package/dist/src/utils/hot-reload.mjs.map +1 -0
- package/dist/src/utils/index.d.mts +3 -0
- package/dist/src/utils/index.d.ts +3 -0
- package/dist/src/utils/index.js +15 -0
- package/dist/src/utils/index.mjs +4 -0
- package/package.json +135 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 ScriptedAlchemy LLC (Zack Jackson) Zhou Shaw (zhouxiao)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://github.com/module-federation/nextjs-mf/blob/main/packages/node/assets/banner.png" width="800"/>
|
|
3
|
+
</p>
|
|
4
|
+
<div align="center">
|
|
5
|
+
<!-- for version -->
|
|
6
|
+
<img src="https://img.shields.io/npm/v/@module-federation/node" alt="version" >
|
|
7
|
+
<img src="https://img.shields.io/npm/l/@module-federation/node.svg?" alt="license" >
|
|
8
|
+
<!-- for downloads -->
|
|
9
|
+
<img src="https://img.shields.io/npm/dt/@module-federation/node" alt="downloads">
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<p align="center">
|
|
13
|
+
<strong>A package to bring the concept and power of module federation to NodeJS.</strong>
|
|
14
|
+
</p>
|
|
15
|
+
|
|
16
|
+
## ⚡ Features
|
|
17
|
+
|
|
18
|
+
- Exposes two Webpack Plugins to enable Module Federation.
|
|
19
|
+
- Can exported as UniversalFederationPlugin or NodeFederationPlugin with StreamingTargetPlugin
|
|
20
|
+
- Allows server to fetch chunks across the network.
|
|
21
|
+
- Allow distributed deployments of federated applications.
|
|
22
|
+
|
|
23
|
+
## 📦 Installation
|
|
24
|
+
|
|
25
|
+
To install the plugin run one of the following commands in your terminal for your application.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# npm
|
|
29
|
+
npm install @module-federation/node
|
|
30
|
+
|
|
31
|
+
# yarn
|
|
32
|
+
yarn add @module-federation/node
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 🚀 Usage
|
|
36
|
+
|
|
37
|
+
There are two approaches to using the plugins exported from this package, dependent on your use case.
|
|
38
|
+
|
|
39
|
+
### Use as Runtime Plugin
|
|
40
|
+
|
|
41
|
+
`module-federation/enhanced` supports runtime plugins.
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
const { ModuleFederationPlugin } = require('@module-federation/enhanced');
|
|
45
|
+
|
|
46
|
+
const options = {
|
|
47
|
+
target: 'async-node',
|
|
48
|
+
output: {
|
|
49
|
+
chunkFilename: '[id]-[contenthash].js', // important to hash chunks
|
|
50
|
+
},
|
|
51
|
+
plugins: [
|
|
52
|
+
new ModuleFederationPlugin({
|
|
53
|
+
name: 'app1',
|
|
54
|
+
exposes: {},
|
|
55
|
+
remotes: {
|
|
56
|
+
app2: 'app2@http://',
|
|
57
|
+
},
|
|
58
|
+
runtimePlugins: [require.resolve('@module-federation/node/runtimePlugin')],
|
|
59
|
+
remoteType: 'script',
|
|
60
|
+
library: { type: 'commonjs-module', name: 'app1' },
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
or you can enable it with some presets via UniversalFederation
|
|
67
|
+
|
|
68
|
+
```js
|
|
69
|
+
new UniversalFederationPlugin({
|
|
70
|
+
name: 'website2',
|
|
71
|
+
library: { type: 'commonjs-module' },
|
|
72
|
+
isServer: true, // or false
|
|
73
|
+
remotes: {},
|
|
74
|
+
filename: 'remoteEntry.js',
|
|
75
|
+
useRuntimePlugin: true, // uses the module-federation/enhanced runtime plugin api
|
|
76
|
+
exposes: {
|
|
77
|
+
'./SharedComponent': './remoteServer/SharedComponent',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### UniversalFederationPlugin
|
|
83
|
+
|
|
84
|
+
This plugin is an abstraction over both `NodeFederationPlugin` and `ModuleFederationPlugin`. It will alternate between which it uses based on where the build is intended to be used.
|
|
85
|
+
|
|
86
|
+
If the build is intended to be used on the `browser`, it will use the standard `ModuleFederationPlugin` and bundle your code accordingly, however, if it is intended for `server` usage, it will use `NodeFederationPlugin` to create the bundle.
|
|
87
|
+
|
|
88
|
+
This simplifies the code required in your `webpack.config.js` to enable SSR Module Federation. It determines which platform it needs to build for based on two things:
|
|
89
|
+
|
|
90
|
+
1. If the options passed to the plugin has specified `isServer: true`
|
|
91
|
+
2. If the name assigned to the config being used is `server`
|
|
92
|
+
|
|
93
|
+
It accepts the other standard options from `ModuleFederationPlugin` as well. You can see an example usage below:
|
|
94
|
+
|
|
95
|
+
```js
|
|
96
|
+
const { UniversalFederationPlugin } = require('@module-federation/node');
|
|
97
|
+
|
|
98
|
+
const config = {
|
|
99
|
+
target: isServer ? false : 'web',
|
|
100
|
+
plugins: [
|
|
101
|
+
new UniversalFederationPlugin({
|
|
102
|
+
name: 'website2',
|
|
103
|
+
library: { type: 'commonjs-module' },
|
|
104
|
+
isServer: true, // or false
|
|
105
|
+
remotes: {},
|
|
106
|
+
filename: 'remoteEntry.js',
|
|
107
|
+
useRuntimePlugin: true, // uses the module-federation/enhanced runtime plugins
|
|
108
|
+
exposes: {
|
|
109
|
+
'./SharedComponent': './remoteServer/SharedComponent',
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### NodeFederationPlugin and StreamingTargetPlugin
|
|
117
|
+
|
|
118
|
+
You can also use each of the underlying plugins individually if you need more control over when they are used.
|
|
119
|
+
|
|
120
|
+
At build time, you need to be aware if you're building for the `server` or for the `browser`.
|
|
121
|
+
If it's building for server, we need to set `target: false` to allow the plugins to function correctly.
|
|
122
|
+
|
|
123
|
+
The `NodeFederationPlugin` follows the same API as the [Module Federation Plugin](https://webpack.js.org/plugins/module-federation-plugin) and therefore should be a drop-in replacement if you already have it set up in your `webpack.config.js`.
|
|
124
|
+
|
|
125
|
+
### 🔧 Config Example
|
|
126
|
+
|
|
127
|
+
An example configuration is presented below:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
const { NodeFederationPlugin, StreamingTargetPlugin } = require('@module-federation/node');
|
|
131
|
+
|
|
132
|
+
const config = {
|
|
133
|
+
target: isServer ? false : 'web',
|
|
134
|
+
plugins: [
|
|
135
|
+
new NodeFederationPlugin({
|
|
136
|
+
name: 'website2',
|
|
137
|
+
library: { type: 'commonjs-module' },
|
|
138
|
+
remotes: {},
|
|
139
|
+
filename: 'remoteEntry.js',
|
|
140
|
+
exposes: {
|
|
141
|
+
'./SharedComponent': './remoteServer/SharedComponent',
|
|
142
|
+
},
|
|
143
|
+
}),
|
|
144
|
+
new StreamingTargetPlugin({
|
|
145
|
+
name: 'website2',
|
|
146
|
+
library: { type: 'commonjs-module' },
|
|
147
|
+
remotes: {},
|
|
148
|
+
}),
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Utilities
|
|
154
|
+
|
|
155
|
+
This package also exposes a few utilities to help with the setup of your federated application.
|
|
156
|
+
|
|
157
|
+
### revalidate
|
|
158
|
+
|
|
159
|
+
Used to "hot reload" the federated application.
|
|
160
|
+
|
|
161
|
+
- This is useful when you're developing your federated application and want to see changes without having to restart the server.
|
|
162
|
+
- Also useful for production environments where you want to be able to update the federated application without having to restart the server.
|
|
163
|
+
|
|
164
|
+
```js
|
|
165
|
+
import { revalidate } from '@module-federation/node/utils';
|
|
166
|
+
|
|
167
|
+
// we automatically reset require cache, so the reload callback is only if you need to do something else
|
|
168
|
+
revalidate().then((shouldReload) => {
|
|
169
|
+
// do something extra after revalidation
|
|
170
|
+
if (shouldReload) {
|
|
171
|
+
// reload the server
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
_Note_: To ensure that changes made to files in remotes are picked up `revalidate`, you can set the remotes webpack [output.filename](https://webpack.js.org/configuration/output/#outputfilename) to `[name]-[contenthash].js` (or similar). This will cause the remoteEntry.js file to be regenerated with a unique hash every time a new build occurs. The revalidate method intelligently detects changes by comparing the hashes of the remoteEntry.js files. By incorporating [contenthash] into the remote's webpack configuration, you enable the shell to seamlessly incorporate the updated files from the remotes.
|
|
177
|
+
|
|
178
|
+
**Hot reloading Express.js**
|
|
179
|
+
|
|
180
|
+
Express has its own route stack, so reloading require cache will not be enough to reload the routes inside express.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
//express.js
|
|
184
|
+
const app = express();
|
|
185
|
+
|
|
186
|
+
global.clearRoutes = () => {
|
|
187
|
+
app._router.stack = app._router.stack.filter((k) => !(k && k.route && k.route.path));
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// in some other file (within the scope of webpack build)
|
|
191
|
+
// wherever you have your revalidation logic
|
|
192
|
+
revalidate().then((shouldReload) => {
|
|
193
|
+
if (shouldReload) {
|
|
194
|
+
global.clearRoutes();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Overriding default http chunk fetch
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
const chunkFetcher = globalThis.webpackChunkLoad || globalThis.fetch || fetchPolyfill;
|
|
203
|
+
// then it will pass one argument to the function, the url to fetch
|
|
204
|
+
|
|
205
|
+
chunkFetcher(url)
|
|
206
|
+
.then((res) => res.text())
|
|
207
|
+
.then((text) => {
|
|
208
|
+
// do something with the text
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
If you want to use your own custom fetch, or add fetch headers, either in the entrypoint of webpack or outside of webpack scope, like in express server you can override the default chunk fetcher by setting the `globalThis.webpackChunkLoad` variable.
|
|
213
|
+
|
|
214
|
+
```js
|
|
215
|
+
globalThis.webpackChunkLoad = async (url) => {
|
|
216
|
+
const res = await fetch(url, {
|
|
217
|
+
headers: {
|
|
218
|
+
'x-custom-header': 'custom-header-value',
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
return res.text();
|
|
222
|
+
};
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## 🔑 License
|
|
226
|
+
|
|
227
|
+
- MIT @[ScriptedAlchemy](https://github.com/ScriptedAlchemy)
|
|
228
|
+
|
|
229
|
+
## 👨💻 Contributors
|
|
230
|
+
|
|
231
|
+
List of our amazing contributors 💥
|
|
232
|
+
|
|
233
|
+
<a href="https://github.com/module-federation/nextjs-mf/graphs/contributors">
|
|
234
|
+
<img src="https://contrib.rocks/image?repo=module-federation/node" />
|
|
235
|
+
</a>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
14
|
+
__defProp(to, key, {
|
|
15
|
+
get: ((k) => from[k]).bind(null, key),
|
|
16
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
24
|
+
value: mod,
|
|
25
|
+
enumerable: true
|
|
26
|
+
}) : target, mod));
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
|
|
30
|
+
exports.__commonJSMin = __commonJSMin;
|
|
31
|
+
exports.__toESM = __toESM;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
|
|
3
|
+
//#region \0rolldown/runtime.js
|
|
4
|
+
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
5
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
export { __commonJSMin, __require };
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.js');
|
|
2
|
+
|
|
3
|
+
//#region src/plugins/ChunkCorrelationPlugin.js
|
|
4
|
+
var require_ChunkCorrelationPlugin = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
|
|
5
|
+
const PLUGIN_NAME = "FederationStatsPlugin";
|
|
6
|
+
/** @typedef {import("./webpack-stats-types").WebpackStats} WebpackStats */
|
|
7
|
+
/** @typedef {import( "./webpack-stats-types").WebpackStatsChunk} WebpackStatsChunk */
|
|
8
|
+
/** @typedef {import("./webpack-stats-types").WebpackStatsModule} WebpackStatsModule */
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {object} SharedDependency
|
|
11
|
+
* @property {string} shareScope
|
|
12
|
+
* @property {string} shareKey
|
|
13
|
+
* @property {string} requiredVersion
|
|
14
|
+
* @property {boolean} strictVersion
|
|
15
|
+
* @property {boolean} singleton
|
|
16
|
+
* @property {boolean} eager
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {object} SharedModule
|
|
20
|
+
* @property {string[]} chunks
|
|
21
|
+
* @property {SharedDependency[]} provides
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {object} Exposed
|
|
25
|
+
* @property {string[]} chunks
|
|
26
|
+
* @property {SharedModule[]} sharedModules
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* @typedef {object} FederatedContainer
|
|
30
|
+
* @property {string} remote
|
|
31
|
+
* @property {string} entry
|
|
32
|
+
* @property {SharedModule[]} sharedModules
|
|
33
|
+
* @property {{ [key: string]: Exposed }} exposes
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {object} FederatedStats
|
|
37
|
+
* @property {SharedModule[]} sharedModules
|
|
38
|
+
* @property {FederatedContainer[]} federatedModules
|
|
39
|
+
*/
|
|
40
|
+
const concat = (x, y) => x.concat(y);
|
|
41
|
+
const flatMap = (xs, f) => xs.map(f).reduce(concat, []);
|
|
42
|
+
/**
|
|
43
|
+
*
|
|
44
|
+
* @param {WebpackStats} stats
|
|
45
|
+
* @returns {}
|
|
46
|
+
*/
|
|
47
|
+
function getRemoteModules(stats) {
|
|
48
|
+
return stats.modules.filter((mod) => mod.moduleType === "remote-module").reduce((acc, remoteModule) => {
|
|
49
|
+
acc[remoteModule.nameForCondition] = remoteModule.id;
|
|
50
|
+
return acc;
|
|
51
|
+
}, {});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
*
|
|
55
|
+
* @param {WebpackStats} stats
|
|
56
|
+
* @param {string} exposedFile
|
|
57
|
+
* @returns {WebpackStatsModule[]}
|
|
58
|
+
*/
|
|
59
|
+
function getExposedModules(stats, exposedFile) {
|
|
60
|
+
return stats.modules.filter((mod) => mod.name?.startsWith(exposedFile));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @param {WebpackStats} stats
|
|
65
|
+
* @param {WebpackStatsModule} mod
|
|
66
|
+
* @returns {Exposed}
|
|
67
|
+
*/
|
|
68
|
+
function getExposed(stats, mod) {
|
|
69
|
+
const chunks = stats.chunks.filter((chunk) => {
|
|
70
|
+
return chunk.modules.find((modsInChunk) => {
|
|
71
|
+
return modsInChunk.id === mod.id && !modsInChunk.dependent;
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
const dependencies = stats.modules.filter((sharedModule) => {
|
|
75
|
+
if (sharedModule.moduleType !== "consume-shared-module") return false;
|
|
76
|
+
return sharedModule.issuerId === mod.id;
|
|
77
|
+
}).map((sharedModule) => {
|
|
78
|
+
return sharedModule.identifier.split("|")[2];
|
|
79
|
+
});
|
|
80
|
+
return flatMap(chunks, (chunk) => ({ [chunk.id]: {
|
|
81
|
+
files: chunk.files.map((f) => `${stats.publicPath === "auto" ? "" : stats.publicPath || ""}${f}`),
|
|
82
|
+
requiredModules: dependencies
|
|
83
|
+
} })).reduce((acc, chunk) => {
|
|
84
|
+
Object.assign(acc, chunk);
|
|
85
|
+
return acc;
|
|
86
|
+
}, {});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
*
|
|
90
|
+
* @param {import("webpack").Module} mod
|
|
91
|
+
* @param {(issuer: string) => boolean} check
|
|
92
|
+
* @returns {boolean}
|
|
93
|
+
*/
|
|
94
|
+
function searchIssuer(mod, check) {
|
|
95
|
+
if (mod.issuer && check(mod.issuer)) return true;
|
|
96
|
+
return !!mod.modules && mod.modules.some((m) => searchIssuer(m, check));
|
|
97
|
+
}
|
|
98
|
+
function searchReason(mod, check) {
|
|
99
|
+
if (mod.reasons && check(mod.reasons)) return true;
|
|
100
|
+
return !!mod.reasons && mod.reasons.some((m) => searchReason(m, check));
|
|
101
|
+
}
|
|
102
|
+
function searchIssuerAndReason(mod, check) {
|
|
103
|
+
const foundIssuer = searchIssuer(mod, (issuer) => check(issuer));
|
|
104
|
+
if (foundIssuer) return foundIssuer;
|
|
105
|
+
return searchReason(mod, (reason) => reason.some((r) => check(r?.moduleIdentifier)));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* @param {import("webpack").Module} mod
|
|
109
|
+
* @param {(issuer: string) => boolean} check
|
|
110
|
+
* @returns {string[]}
|
|
111
|
+
*/
|
|
112
|
+
function getIssuers(mod, check) {
|
|
113
|
+
if (mod.issuer && check(mod.issuer)) return [mod.issuer];
|
|
114
|
+
return mod.modules && mod.modules.filter((m) => searchIssuer(m, check)).map((m) => m.issuer) || [];
|
|
115
|
+
}
|
|
116
|
+
function getIssuersAndReasons(mod, check) {
|
|
117
|
+
if (mod.issuer && check(mod.issuer)) return [mod.issuer];
|
|
118
|
+
if (mod.reasons && searchReason(mod, (reason) => reason.some((r) => check(r?.moduleIdentifier)))) return mod.reasons.filter((r) => {
|
|
119
|
+
return r.moduleIdentifier && check(r.moduleIdentifier);
|
|
120
|
+
}).map((r) => r.moduleIdentifier);
|
|
121
|
+
return mod.modules && mod.modules.filter((m) => searchIssuerAndReason(m, check)).map((m) => {
|
|
122
|
+
return m.issuer || m.reasons.find((r) => check(r?.moduleIdentifier)).moduleIdentifier;
|
|
123
|
+
}) || [];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* @param {string} issuer
|
|
127
|
+
* @returns {SharedDependency}
|
|
128
|
+
*/
|
|
129
|
+
function parseFederatedIssuer(issuer) {
|
|
130
|
+
const split = issuer?.split("|") || [];
|
|
131
|
+
if (split.length !== 8 || split[0] !== "consume-shared-module") return null;
|
|
132
|
+
const [, shareScope, shareKey, requiredVersion, strictVersion, , singleton, eager] = split;
|
|
133
|
+
return {
|
|
134
|
+
shareScope,
|
|
135
|
+
shareKey,
|
|
136
|
+
requiredVersion,
|
|
137
|
+
strictVersion: JSON.parse(strictVersion),
|
|
138
|
+
singleton: JSON.parse(singleton),
|
|
139
|
+
eager: JSON.parse(eager)
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
*
|
|
144
|
+
* @param {WebpackStats} stats
|
|
145
|
+
* @param {import("webpack").container.ModuleFederationPlugin} federationPlugin
|
|
146
|
+
* @returns {SharedModule[]}
|
|
147
|
+
*/
|
|
148
|
+
function getSharedModules(stats, federationPlugin) {
|
|
149
|
+
return flatMap(stats.chunks.filter((chunk) => {
|
|
150
|
+
if (!stats.entrypoints[federationPlugin.name]) return false;
|
|
151
|
+
return stats.entrypoints[federationPlugin.name].chunks.some((id) => chunk.id === id);
|
|
152
|
+
}), (chunk) => flatMap(chunk.children, (id) => stats.chunks.filter((c) => c.id === id && c.files.length > 0 && c.parents.some((p) => stats.entrypoints[federationPlugin.name].chunks.some((c) => c === p)) && c.modules.some((m) => searchIssuer(m, (issuer) => issuer?.startsWith("consume-shared-module")))))).map((chunk) => ({
|
|
153
|
+
chunks: chunk.files.map((f) => `${stats.publicPath === "auto" ? "" : stats.publicPath || ""}${f}`),
|
|
154
|
+
provides: flatMap(chunk.modules.filter((m) => searchIssuer(m, (issuer) => issuer?.startsWith("consume-shared-module"))), (m) => getIssuers(m, (issuer) => issuer?.startsWith("consume-shared-module"))).map(parseFederatedIssuer).filter((f) => !!f)
|
|
155
|
+
})).filter((c) => c.provides.length > 0);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* @param {WebpackStats} stats
|
|
159
|
+
* @returns {SharedModule[]}
|
|
160
|
+
*/
|
|
161
|
+
function getMainSharedModules(stats) {
|
|
162
|
+
return flatMap(stats.namedChunkGroups["main"] ? flatMap(stats.namedChunkGroups["main"].chunks, (c) => stats.chunks.filter((chunk) => chunk.id === c)) : [], (chunk) => flatMap(chunk.children, (id) => stats.chunks.filter((c) => {
|
|
163
|
+
return c.id === id && c.files.length > 0 && c.modules.some((m) => {
|
|
164
|
+
return searchIssuerAndReason(m, (check) => check?.startsWith("consume-shared-module"));
|
|
165
|
+
});
|
|
166
|
+
}))).map((chunk) => {
|
|
167
|
+
return {
|
|
168
|
+
chunks: chunk.files.map((f) => `${stats.publicPath === "auto" ? "" : stats.publicPath || ""}${f}`),
|
|
169
|
+
provides: flatMap(chunk.modules.filter((m) => searchIssuerAndReason(m, (check) => check?.startsWith("consume-shared-module"))), (m) => getIssuersAndReasons(m, (issuer) => issuer?.startsWith("consume-shared-module"))).map(parseFederatedIssuer).filter((f) => !!f)
|
|
170
|
+
};
|
|
171
|
+
}).filter((c) => c.provides.length > 0);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
*
|
|
175
|
+
* @param {WebpackStats} stats
|
|
176
|
+
* @param {import("webpack").container.ModuleFederationPlugin} federationPlugin
|
|
177
|
+
* @returns {FederatedStats}
|
|
178
|
+
*/
|
|
179
|
+
function getFederationStats(stats, federationPluginOptions) {
|
|
180
|
+
const exposedModules = Object.entries(federationPluginOptions.exposes).reduce((exposedModules, [exposedAs, exposedFile]) => Object.assign(exposedModules, { [exposedAs]: getExposedModules(stats, exposedFile) }), {});
|
|
181
|
+
/** @type {{ [key: string]: Exposed }} */
|
|
182
|
+
const exposes = Object.entries(exposedModules).reduce((exposedChunks, [exposedAs, exposedModules]) => Object.assign(exposedChunks, { [exposedAs]: flatMap(exposedModules, (mod) => getExposed(stats, mod)) }), {});
|
|
183
|
+
/** @type {string} */
|
|
184
|
+
const remote = federationPluginOptions.library?.name || federationPluginOptions.name;
|
|
185
|
+
const sharedModules = getSharedModules(stats, federationPluginOptions);
|
|
186
|
+
const remoteModules = getRemoteModules(stats);
|
|
187
|
+
return {
|
|
188
|
+
remote,
|
|
189
|
+
entry: `${stats.publicPath === "auto" ? "" : stats.publicPath || ""}${stats.assetsByChunkName[remote] && stats.assetsByChunkName[remote].length === 1 ? stats.assetsByChunkName[remote][0] : federationPluginOptions.filename}`,
|
|
190
|
+
sharedModules,
|
|
191
|
+
exposes,
|
|
192
|
+
remoteModules
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* @typedef {object} FederationStatsPluginOptions
|
|
197
|
+
* @property {string | string[]} filename The filename or an array of filenames in the `output.path` directory to write stats to.
|
|
198
|
+
*/
|
|
199
|
+
/**
|
|
200
|
+
* Writes relevant federation stats to a file for further consumption.
|
|
201
|
+
*/
|
|
202
|
+
var FederationStatsPlugin = class {
|
|
203
|
+
/**
|
|
204
|
+
*
|
|
205
|
+
* @param {FederationStatsPluginOptions} options
|
|
206
|
+
*/
|
|
207
|
+
constructor(options) {
|
|
208
|
+
if (!options || !options.filename) throw new Error("filename option is required.");
|
|
209
|
+
this._options = options;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
*
|
|
213
|
+
* @param {import("webpack").Compiler} compiler
|
|
214
|
+
*/
|
|
215
|
+
apply(compiler) {
|
|
216
|
+
const federationPlugins = compiler.options.plugins?.filter((plugin) => [
|
|
217
|
+
"NextFederationPlugin",
|
|
218
|
+
"UniversalFederationPlugin",
|
|
219
|
+
"NodeFederationPlugin",
|
|
220
|
+
"ModuleFederationPlugin"
|
|
221
|
+
].includes(plugin.constructor.name) && plugin?._options?.exposes);
|
|
222
|
+
if (!federationPlugins || federationPlugins.length === 0) return;
|
|
223
|
+
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {
|
|
224
|
+
compilation.hooks.processAssets.tap({
|
|
225
|
+
name: PLUGIN_NAME,
|
|
226
|
+
stage: compilation.constructor.PROCESS_ASSETS_STAGE_REPORT
|
|
227
|
+
}, () => {
|
|
228
|
+
const [federationOpts] = federationPlugins.map((federationPlugin) => federationPlugin?._options);
|
|
229
|
+
let container;
|
|
230
|
+
for (const [name, entry] of compilation.entrypoints) {
|
|
231
|
+
if (container) break;
|
|
232
|
+
federationOpts.name.includes(name) && (container = entry);
|
|
233
|
+
}
|
|
234
|
+
if (!container) return;
|
|
235
|
+
container = container?.getEntrypointChunk();
|
|
236
|
+
const [containerEntryModule] = Array.from(compilation.chunkGraph.getChunkEntryModulesIterable(container));
|
|
237
|
+
const { blocks } = containerEntryModule;
|
|
238
|
+
const exposedResolved = {};
|
|
239
|
+
const builtExposes = {};
|
|
240
|
+
for (let block of blocks) {
|
|
241
|
+
const blockmodule = block;
|
|
242
|
+
for (const dep of blockmodule.dependencies) {
|
|
243
|
+
const connection = compilation.moduleGraph.getConnection(dep);
|
|
244
|
+
if (!connection) continue;
|
|
245
|
+
const { module: module$1 } = connection;
|
|
246
|
+
const moduleChunks = compilation.chunkGraph.getModuleChunksIterable(module$1);
|
|
247
|
+
for (let exposedChunk of moduleChunks) {
|
|
248
|
+
const isForThisRuntime = (typeof exposedChunk.runtime === "string" ? new Set([exposedChunk.runtime]) : exposedChunk.runtime).has(containerEntryModule._name);
|
|
249
|
+
const moduleActuallyNeedsChunk = compilation.chunkGraph.getChunkRootModules(exposedChunk).includes(module$1);
|
|
250
|
+
if (!isForThisRuntime || !moduleActuallyNeedsChunk) continue;
|
|
251
|
+
builtExposes[dep.exposedName] = [...builtExposes[dep.exposedName] || [], ...exposedChunk.files || []];
|
|
252
|
+
}
|
|
253
|
+
exposedResolved[dep.exposedName] = module$1;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const stats = compilation.getStats().toJson({
|
|
257
|
+
all: false,
|
|
258
|
+
assets: true,
|
|
259
|
+
reasons: true,
|
|
260
|
+
modules: true,
|
|
261
|
+
children: true,
|
|
262
|
+
chunkGroups: true,
|
|
263
|
+
chunkModules: true,
|
|
264
|
+
chunkOrigins: false,
|
|
265
|
+
entrypoints: true,
|
|
266
|
+
namedChunkGroups: false,
|
|
267
|
+
chunkRelations: true,
|
|
268
|
+
chunks: true,
|
|
269
|
+
ids: true,
|
|
270
|
+
nestedModules: false,
|
|
271
|
+
outputPath: true,
|
|
272
|
+
publicPath: true
|
|
273
|
+
});
|
|
274
|
+
const federatedModules = getFederationStats(stats, federationOpts);
|
|
275
|
+
federatedModules.exposes = builtExposes;
|
|
276
|
+
const sharedModules = getMainSharedModules(stats);
|
|
277
|
+
const vendorChunks = /* @__PURE__ */ new Set();
|
|
278
|
+
for (const share of sharedModules) if (share?.chunks) for (const file of share.chunks) vendorChunks.add(file);
|
|
279
|
+
const statsResult = {
|
|
280
|
+
sharedModules,
|
|
281
|
+
federatedModules: [federatedModules]
|
|
282
|
+
};
|
|
283
|
+
const statsJson = JSON.stringify(statsResult);
|
|
284
|
+
const statsBuffer = Buffer.from(statsJson, "utf-8");
|
|
285
|
+
const statsSource = {
|
|
286
|
+
source: () => statsBuffer,
|
|
287
|
+
size: () => statsBuffer.length
|
|
288
|
+
};
|
|
289
|
+
const { filename } = this._options;
|
|
290
|
+
if (Array.isArray(filename)) for (const file of filename) if (compilation.getAsset(file)) compilation.updateAsset(file, statsSource);
|
|
291
|
+
else compilation.emitAsset(file, statsSource);
|
|
292
|
+
else if (compilation.getAsset(filename)) compilation.updateAsset(filename, statsSource);
|
|
293
|
+
else compilation.emitAsset(filename, statsSource);
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
module.exports = FederationStatsPlugin;
|
|
299
|
+
}));
|
|
300
|
+
|
|
301
|
+
//#endregion
|
|
302
|
+
Object.defineProperty(exports, 'default', {
|
|
303
|
+
enumerable: true,
|
|
304
|
+
get: function () {
|
|
305
|
+
return require_ChunkCorrelationPlugin();
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=ChunkCorrelationPlugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChunkCorrelationPlugin.js","names":["module"],"sources":["../../src/plugins/ChunkCorrelationPlugin.js"],"sourcesContent":["const PLUGIN_NAME = 'FederationStatsPlugin';\n\n/** @typedef {import(\"./webpack-stats-types\").WebpackStats} WebpackStats */\n/** @typedef {import( \"./webpack-stats-types\").WebpackStatsChunk} WebpackStatsChunk */\n/** @typedef {import(\"./webpack-stats-types\").WebpackStatsModule} WebpackStatsModule */\n\n/**\n * @typedef {object} SharedDependency\n * @property {string} shareScope\n * @property {string} shareKey\n * @property {string} requiredVersion\n * @property {boolean} strictVersion\n * @property {boolean} singleton\n * @property {boolean} eager\n */\n\n/**\n * @typedef {object} SharedModule\n * @property {string[]} chunks\n * @property {SharedDependency[]} provides\n */\n\n/**\n * @typedef {object} Exposed\n * @property {string[]} chunks\n * @property {SharedModule[]} sharedModules\n */\n\n/**\n * @typedef {object} FederatedContainer\n * @property {string} remote\n * @property {string} entry\n * @property {SharedModule[]} sharedModules\n * @property {{ [key: string]: Exposed }} exposes\n */\n\n/**\n * @typedef {object} FederatedStats\n * @property {SharedModule[]} sharedModules\n * @property {FederatedContainer[]} federatedModules\n */\n\nconst concat = (x, y) => x.concat(y);\n\nconst flatMap = (xs, f) => xs.map(f).reduce(concat, []);\n\n/**\n *\n * @param {WebpackStats} stats\n * @returns {}\n */\nfunction getRemoteModules(stats) {\n return stats.modules\n .filter((mod) => mod.moduleType === 'remote-module')\n .reduce((acc, remoteModule) => {\n acc[remoteModule.nameForCondition] = remoteModule.id;\n return acc;\n }, {});\n}\n\n/**\n *\n * @param {WebpackStats} stats\n * @param {string} exposedFile\n * @returns {WebpackStatsModule[]}\n */\nfunction getExposedModules(stats, exposedFile) {\n return stats.modules.filter((mod) => mod.name?.startsWith(exposedFile));\n}\n//eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction getDependenciesOfChunk(stats, chunk) {\n return stats.chunks\n .filter((c) => c.children.includes(chunk.id))\n .reduce((acc, c) => {\n return acc.concat(c.modules);\n }, []);\n}\n\n/**\n *\n * @param {WebpackStats} stats\n * @param {WebpackStatsModule} mod\n * @returns {Exposed}\n */\nfunction getExposed(stats, mod) {\n const chunks = stats.chunks.filter((chunk) => {\n return chunk.modules.find((modsInChunk) => {\n return modsInChunk.id === mod.id && !modsInChunk.dependent;\n });\n });\n const dependencies = stats.modules\n .filter((sharedModule) => {\n if (sharedModule.moduleType !== 'consume-shared-module') {\n return false;\n }\n return sharedModule.issuerId === mod.id;\n })\n .map((sharedModule) => {\n return sharedModule.identifier.split('|')[2];\n });\n\n const flatChunks = flatMap(chunks, (chunk) => ({\n [chunk.id]: {\n files: chunk.files.map(\n (f) =>\n `${stats.publicPath === 'auto' ? '' : stats.publicPath || ''}${f}`,\n ),\n requiredModules: dependencies,\n },\n }));\n\n return flatChunks.reduce((acc, chunk) => {\n Object.assign(acc, chunk);\n return acc;\n }, {});\n}\n\n/**\n *\n * @param {import(\"webpack\").Module} mod\n * @param {(issuer: string) => boolean} check\n * @returns {boolean}\n */\nfunction searchIssuer(mod, check) {\n if (mod.issuer && check(mod.issuer)) {\n return true;\n }\n\n return !!mod.modules && mod.modules.some((m) => searchIssuer(m, check));\n}\n\nfunction searchReason(mod, check) {\n if (mod.reasons && check(mod.reasons)) {\n return true;\n }\n\n return !!mod.reasons && mod.reasons.some((m) => searchReason(m, check));\n}\n\nfunction searchIssuerAndReason(mod, check) {\n const foundIssuer = searchIssuer(mod, (issuer) => check(issuer));\n if (foundIssuer) {\n return foundIssuer;\n }\n return searchReason(mod, (reason) =>\n reason.some((r) => check(r?.moduleIdentifier)),\n );\n}\n\n/**\n * @param {import(\"webpack\").Module} mod\n * @param {(issuer: string) => boolean} check\n * @returns {string[]}\n */\nfunction getIssuers(mod, check) {\n if (mod.issuer && check(mod.issuer)) {\n return [mod.issuer];\n }\n\n return (\n (mod.modules &&\n mod.modules.filter((m) => searchIssuer(m, check)).map((m) => m.issuer)) ||\n []\n );\n}\n\nfunction getIssuersAndReasons(mod, check) {\n if (mod.issuer && check(mod.issuer)) {\n return [mod.issuer];\n }\n if (\n mod.reasons &&\n searchReason(mod, (reason) =>\n reason.some((r) => check(r?.moduleIdentifier)),\n )\n ) {\n return mod.reasons\n .filter((r) => {\n return r.moduleIdentifier && check(r.moduleIdentifier);\n })\n .map((r) => r.moduleIdentifier);\n }\n\n return (\n (mod.modules &&\n mod.modules\n .filter((m) => searchIssuerAndReason(m, check))\n .map((m) => {\n return (\n m.issuer ||\n m.reasons.find((r) => check(r?.moduleIdentifier)).moduleIdentifier\n );\n })) ||\n []\n );\n}\n\n/**\n * @param {string} issuer\n * @returns {SharedDependency}\n */\nfunction parseFederatedIssuer(issuer) {\n const split = issuer?.split('|') || [];\n if (split.length !== 8 || split[0] !== 'consume-shared-module') {\n return null;\n }\n const [\n ,\n shareScope,\n shareKey,\n requiredVersion,\n strictVersion,\n ,\n singleton,\n eager,\n ] = split;\n\n return {\n shareScope,\n shareKey,\n requiredVersion,\n strictVersion: JSON.parse(strictVersion),\n singleton: JSON.parse(singleton),\n eager: JSON.parse(eager),\n };\n}\n\n/**\n *\n * @param {WebpackStats} stats\n * @param {import(\"webpack\").container.ModuleFederationPlugin} federationPlugin\n * @returns {SharedModule[]}\n */\nfunction getSharedModules(stats, federationPlugin) {\n return flatMap(\n stats.chunks.filter((chunk) => {\n if (!stats.entrypoints[federationPlugin.name]) {\n return false;\n }\n return stats.entrypoints[federationPlugin.name].chunks.some(\n (id) => chunk.id === id,\n );\n }),\n (chunk) =>\n flatMap(chunk.children, (id) =>\n stats.chunks.filter(\n (c) =>\n c.id === id &&\n c.files.length > 0 &&\n c.parents.some((p) =>\n stats.entrypoints[federationPlugin.name].chunks.some(\n (c) => c === p,\n ),\n ) &&\n c.modules.some((m) =>\n searchIssuer(m, (issuer) =>\n issuer?.startsWith('consume-shared-module'),\n ),\n ),\n ),\n ),\n )\n .map((chunk) => ({\n chunks: chunk.files.map(\n (f) =>\n `${stats.publicPath === 'auto' ? '' : stats.publicPath || ''}${f}`,\n ),\n provides: flatMap(\n chunk.modules.filter((m) =>\n searchIssuer(m, (issuer) =>\n issuer?.startsWith('consume-shared-module'),\n ),\n ),\n (m) =>\n getIssuers(m, (issuer) =>\n issuer?.startsWith('consume-shared-module'),\n ),\n )\n .map(parseFederatedIssuer)\n .filter((f) => !!f),\n }))\n .filter((c) => c.provides.length > 0);\n}\n\n/**\n * @param {WebpackStats} stats\n * @returns {SharedModule[]}\n */\nfunction getMainSharedModules(stats) {\n const chunks = stats.namedChunkGroups['main']\n ? flatMap(stats.namedChunkGroups['main'].chunks, (c) =>\n stats.chunks.filter((chunk) => chunk.id === c),\n )\n : [];\n\n return flatMap(chunks, (chunk) =>\n flatMap(chunk.children, (id) =>\n stats.chunks.filter((c) => {\n return (\n c.id === id &&\n c.files.length > 0 &&\n c.modules.some((m) => {\n return searchIssuerAndReason(m, (check) =>\n check?.startsWith('consume-shared-module'),\n );\n })\n );\n }),\n ),\n )\n .map((chunk) => {\n return {\n chunks: chunk.files.map(\n (f) =>\n `${stats.publicPath === 'auto' ? '' : stats.publicPath || ''}${f}`,\n ),\n provides: flatMap(\n chunk.modules.filter((m) =>\n searchIssuerAndReason(m, (check) =>\n check?.startsWith('consume-shared-module'),\n ),\n ),\n (m) =>\n getIssuersAndReasons(m, (issuer) =>\n issuer?.startsWith('consume-shared-module'),\n ),\n )\n .map(parseFederatedIssuer)\n .filter((f) => !!f),\n };\n })\n .filter((c) => c.provides.length > 0);\n}\n\n/**\n *\n * @param {WebpackStats} stats\n * @param {import(\"webpack\").container.ModuleFederationPlugin} federationPlugin\n * @returns {FederatedStats}\n */\nfunction getFederationStats(stats, federationPluginOptions) {\n const exposedModules = Object.entries(federationPluginOptions.exposes).reduce(\n (exposedModules, [exposedAs, exposedFile]) =>\n Object.assign(exposedModules, {\n [exposedAs]: getExposedModules(stats, exposedFile),\n }),\n {},\n );\n\n /** @type {{ [key: string]: Exposed }} */\n const exposes = Object.entries(exposedModules).reduce(\n (exposedChunks, [exposedAs, exposedModules]) =>\n Object.assign(exposedChunks, {\n [exposedAs]: flatMap(exposedModules, (mod) => getExposed(stats, mod)),\n }),\n {},\n );\n\n /** @type {string} */\n const remote =\n federationPluginOptions.library?.name || federationPluginOptions.name;\n\n const sharedModules = getSharedModules(stats, federationPluginOptions);\n const remoteModules = getRemoteModules(stats);\n return {\n remote,\n entry: `${stats.publicPath === 'auto' ? '' : stats.publicPath || ''}${\n stats.assetsByChunkName[remote] &&\n stats.assetsByChunkName[remote].length === 1\n ? stats.assetsByChunkName[remote][0]\n : federationPluginOptions.filename\n }`,\n sharedModules,\n exposes,\n remoteModules,\n };\n}\n\n/**\n * @typedef {object} FederationStatsPluginOptions\n * @property {string | string[]} filename The filename or an array of filenames in the `output.path` directory to write stats to.\n */\n\n/**\n * Writes relevant federation stats to a file for further consumption.\n */\nclass FederationStatsPlugin {\n /**\n *\n * @param {FederationStatsPluginOptions} options\n */\n constructor(options) {\n if (!options || !options.filename) {\n throw new Error('filename option is required.');\n }\n\n this._options = options;\n }\n\n /**\n *\n * @param {import(\"webpack\").Compiler} compiler\n */\n apply(compiler) {\n const federationPlugins = compiler.options.plugins?.filter(\n (plugin) =>\n [\n 'NextFederationPlugin',\n 'UniversalFederationPlugin',\n 'NodeFederationPlugin',\n 'ModuleFederationPlugin',\n ].includes(plugin.constructor.name) && plugin?._options?.exposes,\n );\n\n if (!federationPlugins || federationPlugins.length === 0) {\n return;\n }\n\n // This is where the plugin is tapping into the Webpack compilation lifecycle.\n // It's listening to the 'thisCompilation' event, which is triggered once for each new compilation.\n compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => {\n // 'processAssets' is a hook that gets triggered when Webpack has finished the compilation\n // and is about to generate the final assets. It allows plugins to do additional processing on the assets.\n compilation.hooks.processAssets.tap(\n {\n name: PLUGIN_NAME,\n stage: compilation.constructor.PROCESS_ASSETS_STAGE_REPORT,\n },\n () => {\n // Extract the options from the federation plugins.\n const [federationOpts] = federationPlugins.map(\n (federationPlugin) => federationPlugin?._options,\n );\n\n let container;\n // Loop through all entry points and if one matches the name of a federation plugin,\n // store the entry point in the 'container' variable.\n for (const [name, entry] of compilation.entrypoints) {\n if (container) {\n break;\n }\n federationOpts.name.includes(name) && (container = entry);\n }\n\n // If no matching entry point was found, exit the function early.\n if (!container) {\n return;\n }\n\n // Get the chunk associated with the entry point.\n container = container?.getEntrypointChunk();\n\n // Get the module associated with the chunk.\n const [containerEntryModule] = Array.from(\n compilation.chunkGraph.getChunkEntryModulesIterable(container),\n );\n\n const { blocks } = containerEntryModule;\n\n const exposedResolved = {};\n const builtExposes = {};\n\n // Iterate over each dependency block associated with the entry module.\n for (let block of blocks) {\n const blockmodule = block;\n\n // Iterate over each dependency within the block.\n for (const dep of blockmodule.dependencies) {\n // Get the module that corresponds to the dependency.\n const connection = compilation.moduleGraph.getConnection(dep);\n if (!connection) {\n continue;\n }\n const { module } = connection;\n\n const moduleChunks =\n compilation.chunkGraph.getModuleChunksIterable(module);\n // Iterate over each chunk associated with the module.\n for (let exposedChunk of moduleChunks) {\n // Determine the runtime for the chunk.\n const runtime =\n typeof exposedChunk.runtime === 'string'\n ? new Set([exposedChunk.runtime])\n : exposedChunk.runtime;\n\n // Check if the chunk is meant for the same runtime as the entry module.\n const isForThisRuntime = runtime.has(\n containerEntryModule._name,\n );\n\n // Get the root modules for the chunk.\n const rootModules =\n compilation.chunkGraph.getChunkRootModules(exposedChunk);\n\n // Check if the module associated with the dependency is one of the root modules for the chunk.\n const moduleActuallyNeedsChunk = rootModules.includes(module);\n\n // If the chunk is not meant for this runtime or the module doesn't need the chunk, skip the rest of this iteration.\n if (!isForThisRuntime || !moduleActuallyNeedsChunk) {\n continue;\n }\n\n // Add the files associated with the chunk to the 'builtExposes' object under the name of the exposed module.\n builtExposes[dep.exposedName] = [\n ...(builtExposes[dep.exposedName] || []),\n ...(exposedChunk.files || []),\n ];\n }\n\n // Add the module to the 'exposedResolved' object under the name of the exposed module.\n exposedResolved[dep.exposedName] = module;\n }\n }\n\n // Generate a JSON object that contains detailed information about the compilation.\n const stats = compilation.getStats().toJson({\n all: false,\n assets: true,\n reasons: true,\n modules: true,\n children: true,\n chunkGroups: true,\n chunkModules: true,\n chunkOrigins: false,\n entrypoints: true,\n namedChunkGroups: false,\n chunkRelations: true,\n chunks: true,\n ids: true,\n nestedModules: false,\n outputPath: true,\n publicPath: true,\n });\n\n // Apply a function 'getFederationStats' on the stats with the federation plugin options as the second argument.\n const federatedModules = getFederationStats(stats, federationOpts);\n\n // Assign the 'builtExposes' object to the 'exposes' property of the 'federatedModules' object.\n federatedModules.exposes = builtExposes;\n\n // Apply a function 'getMainSharedModules' on the stats.\n const sharedModules = getMainSharedModules(stats);\n\n // Create a Set to hold the vendor chunks.\n const vendorChunks = new Set();\n\n // Iterate over the shared modules.\n for (const share of sharedModules) {\n if (share?.chunks) {\n // If a shared module has chunks, add them to the 'vendorChunks' Set.\n for (const file of share.chunks) {\n vendorChunks.add(file);\n }\n }\n }\n\n // Construct an object that contains the shared and federated modules.\n const statsResult = {\n sharedModules,\n federatedModules: [federatedModules],\n };\n\n // Convert the 'statsResult' object to a JSON string.\n const statsJson = JSON.stringify(statsResult);\n\n // Convert the JSON string to a buffer.\n const statsBuffer = Buffer.from(statsJson, 'utf-8');\n\n // Construct an object that represents the source of the final asset.\n const statsSource = {\n source: () => statsBuffer,\n size: () => statsBuffer.length,\n };\n\n // Get the filename of the final asset from the plugin options.\n const { filename } = this._options;\n\n // If filename is an array, loop over it to emit or update assets.\n if (Array.isArray(filename)) {\n for (const file of filename) {\n // Check if an asset with the same filename already exists.\n const asset = compilation.getAsset(file);\n\n // If an asset with the same filename already exists, update it. Otherwise, create a new asset.\n if (asset) {\n compilation.updateAsset(file, statsSource);\n } else {\n compilation.emitAsset(file, statsSource);\n }\n }\n } else {\n // Check if an asset with the same filename already exists.\n const asset = compilation.getAsset(filename);\n\n // If an asset with the same filename already exists, update it. Otherwise, create a new asset.\n if (asset) {\n compilation.updateAsset(filename, statsSource);\n } else {\n compilation.emitAsset(filename, statsSource);\n }\n }\n },\n );\n });\n }\n}\n\nmodule.exports = FederationStatsPlugin;\n"],"mappings":"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"}
|