Skip to content

Commit

Permalink
refactor(enhanced): improve EmbedFederationRuntimePlugin structure an…
Browse files Browse the repository at this point in the history
…d logic
  • Loading branch information
ScriptedAlchemy committed Jan 24, 2025
1 parent cd9c448 commit 2a7829a
Showing 1 changed file with 42 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ import type { Compiler, Chunk, Compilation } from 'webpack';
import { getFederationGlobalScope } from './utils';
import ContainerEntryDependency from '../ContainerEntryDependency';
import FederationRuntimeDependency from './FederationRuntimeDependency';
import {
federationStartup,
generateEntryStartup,
generateESMEntryStartup,
} from '../../startup/StartupHelpers';
import { ConcatSource } from 'webpack-sources';

const { RuntimeGlobals } = require(
Expand All @@ -26,6 +21,10 @@ interface EmbedFederationRuntimePluginOptions {
enableForAllChunks?: boolean;
}

/**
* Plugin that handles embedding of Module Federation runtime code into chunks.
* It ensures proper initialization of federated modules and manages runtime requirements.
*/
class EmbedFederationRuntimePlugin {
private readonly options: EmbedFederationRuntimePluginOptions;
private readonly processedChunks = new WeakMap<Chunk, boolean>();
Expand All @@ -37,11 +36,30 @@ class EmbedFederationRuntimePlugin {
};
}

/**
* Determines if runtime embedding should be enabled for a given chunk
*/
private isEnabledForChunk(chunk: Chunk): boolean {
if (this.options.enableForAllChunks) return true;
if (chunk.id === 'build time chunk') return false;
return chunk.hasRuntime();
}

/**
* Checks if a compilation hook has already been tapped by this plugin
*/
private isHookAlreadyTapped(
taps: Array<{ name: string }>,
hookName: string,
): boolean {
return taps.some((tap) => tap.name === hookName);
}

apply(compiler: Compiler): void {
// Check if plugin is already applied
// Prevent double application of plugin
const compilationTaps = compiler.hooks.thisCompilation.taps || [];
if (
compilationTaps.find((tap) => tap.name === 'EmbedFederationRuntimePlugin')
this.isHookAlreadyTapped(compilationTaps, 'EmbedFederationRuntimePlugin')
) {
return;
}
Expand All @@ -54,11 +72,12 @@ class EmbedFederationRuntimePlugin {
compilation,
);

// Check if renderStartup hook is already tapped
// Prevent double tapping of renderStartup hook
const startupTaps = renderStartup.taps || [];
if (
startupTaps.find(
(tap) => tap.name === 'MfStartupChunkDependenciesPlugin',
this.isHookAlreadyTapped(
startupTaps,
'MfStartupChunkDependenciesPlugin',
)
) {
return;
Expand All @@ -67,15 +86,9 @@ class EmbedFederationRuntimePlugin {
renderStartup.tap(
'MfStartupChunkDependenciesPlugin',
(startupSource, lastInlinedModule, renderContext) => {
const { chunk, chunkGraph, runtimeTemplate } = renderContext;

const isEnabledForChunk = (chunk: Chunk) => {
if (this.options.enableForAllChunks) return true;
if (chunk.id === 'build time chunk') return false;
return chunk.hasRuntime();
};
const { chunk, chunkGraph } = renderContext;

if (!isEnabledForChunk(chunk)) {
if (!this.isEnabledForChunk(chunk)) {
return startupSource;
}

Expand All @@ -92,44 +105,24 @@ class EmbedFederationRuntimePlugin {
return startupSource;
}

// Check if we've already processed this chunk
// Skip if chunk was already processed
if (this.processedChunks.get(chunk)) {
return startupSource;
}

const entryModules = Array.from(
chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk),
);

if (chunkGraph.getNumberOfEntryModules(chunk) === 0) {
// Mark chunk as processed
this.processedChunks.set(chunk, true);
return new ConcatSource(
startupSource,
`${RuntimeGlobals.startup}();\n`,
);
}

// Mark chunk as processed
this.processedChunks.set(chunk, true);
const entryGeneration = runtimeTemplate.outputOptions.module
? generateESMEntryStartup
: generateEntryStartup;

return new compiler.webpack.sources.ConcatSource(
entryGeneration(
compilation,
chunkGraph,
runtimeTemplate,
entryModules,
chunk,
false,
),

// Add basic startup call
return new ConcatSource(
startupSource,
`${RuntimeGlobals.startup}();\n`,
);
},
);
},
);

compiler.hooks.thisCompilation.tap(
'EmbedFederationRuntimePlugin',
(compilation: Compilation) => {
Expand All @@ -145,31 +138,21 @@ class EmbedFederationRuntimePlugin {
},
);

const isEnabledForChunk = (chunk: Chunk) => {
if (this.options.enableForAllChunks) return true;
if (chunk.id === 'build time chunk') return false;
return chunk.hasRuntime();
};

const handleRuntimeRequirements = (
chunk: Chunk,
runtimeRequirements: Set<string>,
) => {
console.log(runtimeRequirements);
if (!isEnabledForChunk(chunk)) {
if (!this.isEnabledForChunk(chunk)) {
return;
}
if (runtimeRequirements.has('embeddedFederationRuntime')) return;
if (!runtimeRequirements.has(federationGlobal)) {
return;
}

runtimeRequirements.add(RuntimeGlobals.startupOnlyBefore);
runtimeRequirements.add('embeddedFederationRuntime');
if (runtimeRequirements.has(RuntimeGlobals.startup)) {
// debugger;
} else {
// debugger
}

const runtimeModule = new EmbedFederationRuntimeModule(
containerEntrySet,
);
Expand All @@ -179,17 +162,9 @@ class EmbedFederationRuntimePlugin {
compilation.hooks.runtimeRequirementInTree
.for(federationGlobal)
.tap('EmbedFederationRuntimePlugin', handleRuntimeRequirements);

// compilation.hooks.additionalTreeRuntimeRequirements.tap(
// 'EmbedFederationRuntimePlugin',
// (chunk, runtimeRequirements) => {
// if(!chunk.hasRuntime()) return;
// runtimeRequirements.add(RuntimeGlobals.startupOnlyBefore);
// runtimeRequirements.add(RuntimeGlobals.startup);
// },
// );
},
);
}
}

export default EmbedFederationRuntimePlugin;

0 comments on commit 2a7829a

Please sign in to comment.