Skip to content

Commit 2abc0db

Browse files
feat: Medusa delegate modules (#447)
* feat: medusa delegate module * feat: medusa delegate module
1 parent eab6bb4 commit 2abc0db

File tree

3 files changed

+158
-159
lines changed

3 files changed

+158
-159
lines changed

dashboard-plugin/FederationDashboardPlugin.js

Lines changed: 51 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class AddRuntimeRequiremetToPromiseExternal {
5050
compiler.hooks.compilation.tap(
5151
"AddRuntimeRequiremetToPromiseExternal",
5252
(compilation) => {
53-
const RuntimeGlobals = compiler.webpack.RuntimeGlobals;
53+
const { RuntimeGlobals } = compiler.webpack;
5454
if (compilation.outputOptions.trustedTypes) {
5555
compilation.hooks.additionalModuleRuntimeRequirements.tap(
5656
"AddRuntimeRequiremetToPromiseExternal",
@@ -81,7 +81,7 @@ class FederationDashboardPlugin {
8181
*/
8282
constructor(options) {
8383
this._options = Object.assign(
84-
{ debug: false, filename: "dashboard.json", useAST: false },
84+
{ debug: false, filename: "dashboard.json", useAST: false, fetchClient: false },
8585
options
8686
);
8787
this._dashData = null;
@@ -92,11 +92,9 @@ class FederationDashboardPlugin {
9292
* @param {Compiler} compiler
9393
*/
9494
apply(compiler) {
95-
compiler.options.output.uniqueName = "v" + Date.now();
95+
compiler.options.output.uniqueName = `v${Date.now()}`;
9696
new AddRuntimeRequiremetToPromiseExternal().apply(compiler);
97-
const FederationPlugin = compiler.options.plugins.find((plugin) => {
98-
return plugin.constructor.name === "ModuleFederationPlugin";
99-
});
97+
const FederationPlugin = compiler.options.plugins.find((plugin) => plugin.constructor.name === "ModuleFederationPlugin");
10098
if (FederationPlugin) {
10199
this.FederationPluginOptions = Object.assign(
102100
{},
@@ -125,6 +123,7 @@ class FederationDashboardPlugin {
125123

126124
if (this.FederationPluginOptions.name) {
127125
new DefinePlugin({
126+
'process.dashboardURL': JSON.stringify(this._options.dashboardURL),
128127
"process.CURRENT_HOST": JSON.stringify(
129128
this.FederationPluginOptions.name
130129
),
@@ -140,23 +139,13 @@ class FederationDashboardPlugin {
140139
// Explore each module within the chunk (built inputs):
141140
chunk.getModules().forEach((module) => {
142141
// Loop through all the dependencies that has the named export that we are looking for
143-
const matchedNamedExports = module.dependencies.filter((dep) => {
144-
return dep.name === "federateComponent";
145-
});
142+
const matchedNamedExports = module.dependencies.filter((dep) => dep.name === "federateComponent");
146143

147-
if (matchedNamedExports.length > 0) {
148-
// we know that this module exported the function we care about
149-
// now we need to know how many times this function is invoked in the source code
150-
// along with all the arguments of it
151-
152-
// these modules could be a combination of multiple source files, so we need to traverse
153-
// through its fileDependencies
154-
if (module.resource) {
155-
filePaths.push({
156-
resource: module.resource,
157-
file: module.resourceResolveData.relativePath,
158-
});
159-
}
144+
if (matchedNamedExports.length > 0 && module.resource) {
145+
filePaths.push({
146+
resource: module.resource,
147+
file: module.resourceResolveData.relativePath,
148+
});
160149
}
161150
});
162151

@@ -174,20 +163,18 @@ class FederationDashboardPlugin {
174163
* More node types are documented here: https://babeljs.io/docs/en/babel-types#api
175164
*/
176165
CallExpression: (path) => {
177-
const node = path.node;
166+
const { node } = path;
178167
const { callee, arguments: args } = node;
179168

180169
if (callee.loc.identifierName === "federateComponent") {
181-
const argsAreStrings = args.every((arg) => {
182-
return arg.type === "StringLiteral";
183-
});
170+
const argsAreStrings = args.every((arg) => arg.type === "StringLiteral");
184171
if (!argsAreStrings) {
185172
return;
186173
}
187174
const argsValue = [file];
188175

189176
// we collect the JS representation of each argument used in this function call
190-
for (let i = 0; i < args.length; i += 1) {
177+
for (let i = 0; i < args.length; i++) {
191178
const a = args[i];
192179
let { code } = generate(a);
193180

@@ -201,12 +188,12 @@ class FederationDashboardPlugin {
201188
// If the value is a Node, that means it was a variable name
202189
// There is no easy way to resolve the variable real value, so we just skip any function calls
203190
// that has variable as its args
204-
if (!isNode(value)) {
205-
argsValue.push(value);
206-
} else {
191+
if (isNode(value)) {
207192
// by breaking out of the loop here,
208193
// we also prevent this args to be pushed to `allArgumentsUsed`
209194
break;
195+
} else {
196+
argsValue.push(value);
210197
}
211198

212199
if (i === args.length - 1) {
@@ -277,7 +264,7 @@ class FederationDashboardPlugin {
277264

278265
if (graphData) {
279266
const dashData = (this._dashData = JSON.stringify(graphData));
280-
// this.writeStatsFiles(stats, dashData);
267+
this.writeStatsFiles(stats, dashData);
281268
if (this._options.dashboardURL && !this._options.nextjs) {
282269
this.postDashboardData(dashData).catch((err) => {
283270
if (err) {
@@ -316,11 +303,8 @@ class FederationDashboardPlugin {
316303
const remoteEntry = curCompiler.getAsset(
317304
this.FederationPluginOptions.filename
318305
);
319-
let cleanVersion = "_" + rawData.version.toString();
306+
const cleanVersion = typeof rawData.version === "string" ? `_${rawData.version.split(".").join("_")}` : `_${rawData.version.toString()}`;
320307

321-
if (typeof rawData.version === "string") {
322-
cleanVersion = "_" + rawData.version.split(".").join("_");
323-
}
324308
let codeSource;
325309
if (!remoteEntry.source._value && remoteEntry.source.source) {
326310
codeSource = remoteEntry.source.source();
@@ -374,18 +358,13 @@ class FederationDashboardPlugin {
374358
}
375359

376360
getRemoteEntryChunk(stats, FederationPluginOptions) {
377-
const remoteEntryChunk = stats.chunks.find((chunk) => {
378-
const specificChunk = chunk.names.find((name) => {
379-
return name === FederationPluginOptions.name;
380-
});
381-
return specificChunk;
382-
});
383-
384-
return remoteEntryChunk;
361+
362+
return stats.chunks.find((chunk) => chunk.names.find((name) => name === FederationPluginOptions.name));
385363
}
386364

387365
getChunkDependencies(validChunkArray) {
388-
const chunkDependencies = validChunkArray.reduce((acc, chunk) => {
366+
367+
return validChunkArray.reduce((acc, chunk) => {
389368
const subset = chunk.getAllReferencedChunks();
390369
const stringifiableChunk = Array.from(subset).map((sub) => {
391370
const cleanSet = Object.getOwnPropertyNames(sub).reduce((acc, key) => {
@@ -400,8 +379,6 @@ class FederationDashboardPlugin {
400379
[chunk.id]: stringifiableChunk,
401380
});
402381
}, {});
403-
404-
return chunkDependencies;
405382
}
406383

407384
buildVendorFederationMap(liveStats) {
@@ -445,7 +422,7 @@ class FederationDashboardPlugin {
445422
}
446423

447424
mapToObjectRec(m) {
448-
let lo = {};
425+
const lo = {};
449426
for (let [key, value] of Object.entries(m)) {
450427
if (value instanceof Map && value.size > 0) {
451428
lo[key] = this.mapToObjectRec(value);
@@ -567,12 +544,12 @@ class FederationDashboardPlugin {
567544
}
568545

569546
async postDashboardData(dashData) {
570-
console.log(this._options.dashboardURL);
571547
if (!this._options.dashboardURL) {
572548
return Promise.resolve();
573549
}
550+
const client = this._options.fetchClient ? this._options.fetchClient : fetch;
574551
try {
575-
const res = await fetch(this._options.dashboardURL, {
552+
const res = await client(this._options.dashboardURL, {
576553
method: "POST",
577554
body: dashData,
578555
headers: {
@@ -601,7 +578,7 @@ class NextMedusaPlugin {
601578
? path.join(compiler.options.output.path, this._options.filename)
602579
: path.join(
603580
compiler.options.output.path,
604-
"sidecar-" + this._options.filename
581+
`sidecar-${this._options.filename}`
605582
);
606583
const hostData = path.join(
607584
compiler.options.output.path,
@@ -617,7 +594,7 @@ class NextMedusaPlugin {
617594
compiler.hooks.afterEmit.tap(PLUGIN_NAME, () => {
618595
const sidecarData = path.join(
619596
compiler.options.output.path,
620-
"sidecar-" + this._options.filename
597+
`sidecar-${this._options.filename}`
621598
);
622599
const hostData = path.join(
623600
compiler.options.output.path,
@@ -644,35 +621,33 @@ class NextMedusaPlugin {
644621

645622
const withMedusa =
646623
({ name, ...medusaConfig }) =>
647-
(nextConfig = {}) => {
648-
return Object.assign({}, nextConfig, {
649-
webpack(config, options) {
650-
if (
651-
options.nextRuntime !== "edge" &&
652-
!options.isServer &&
653-
process.env.NODE_ENV === "production"
654-
) {
655-
if (!name) {
656-
throw new Error(
657-
"Medusa needs a name for the app, please ensure plugin options has {name: <appname>}"
658-
);
659-
}
660-
config.plugins.push(
661-
new NextMedusaPlugin({
662-
standalone: { name },
663-
...medusaConfig,
664-
})
624+
(nextConfig = {}) => Object.assign({}, nextConfig, {
625+
webpack(config, options) {
626+
if (
627+
options.nextRuntime !== "edge" &&
628+
!options.isServer &&
629+
process.env.NODE_ENV === "production"
630+
) {
631+
if (!name) {
632+
throw new Error(
633+
"Medusa needs a name for the app, please ensure plugin options has {name: <appname>}"
665634
);
666635
}
636+
config.plugins.push(
637+
new NextMedusaPlugin({
638+
standalone: { name },
639+
...medusaConfig,
640+
})
641+
);
642+
}
667643

668-
if (typeof nextConfig.webpack === "function") {
669-
return nextConfig.webpack(config, options);
670-
}
644+
if (typeof nextConfig.webpack === "function") {
645+
return nextConfig.webpack(config, options);
646+
}
671647

672-
return config;
673-
},
674-
});
675-
};
648+
return config;
649+
},
650+
});
676651

677652
module.exports = FederationDashboardPlugin;
678653
module.exports.clientVersion = require("./client-version");

0 commit comments

Comments
 (0)