98 lines
No EOL
4.2 KiB
JavaScript
Executable file
98 lines
No EOL
4.2 KiB
JavaScript
Executable file
import { webpack } from 'next/dist/compiled/webpack/webpack';
|
|
import createDebug from 'next/dist/compiled/debug';
|
|
const debug = createDebug('next:deferred-entries-plugin');
|
|
const PLUGIN_NAME = 'DeferredEntriesPlugin';
|
|
/**
|
|
* A webpack plugin that handles deferred entries by:
|
|
* 1. Accepting deferred entrypoints separately from the main config
|
|
* 2. After non-deferred entries are compiled, calling the onBeforeDeferredEntries callback
|
|
* 3. Then adding and compiling the deferred entries within the same compilation
|
|
*
|
|
* This approach avoids module ID conflicts that would occur with separate compilations.
|
|
*/ export class DeferredEntriesPlugin {
|
|
constructor(options){
|
|
this.callbackCalled = false;
|
|
this.onBeforeDeferredEntries = options.config.experimental.onBeforeDeferredEntries;
|
|
this.deferredEntrypoints = options.deferredEntrypoints;
|
|
}
|
|
apply(compiler) {
|
|
// Skip if no deferred entrypoints to process
|
|
if (!this.deferredEntrypoints || Object.keys(this.deferredEntrypoints).length === 0) {
|
|
return;
|
|
}
|
|
// Use finishMake hook to add deferred entries after all initial entries are processed
|
|
// This is the same pattern used by FlightClientEntryPlugin
|
|
compiler.hooks.finishMake.tapPromise(PLUGIN_NAME, async (compilation)=>{
|
|
// Only process if we haven't called callback yet
|
|
if (this.callbackCalled) {
|
|
return;
|
|
}
|
|
this.callbackCalled = true;
|
|
// Call the onBeforeDeferredEntries callback
|
|
if (this.onBeforeDeferredEntries) {
|
|
debug('calling onBeforeDeferredEntries callback');
|
|
await this.onBeforeDeferredEntries();
|
|
debug('onBeforeDeferredEntries callback completed');
|
|
}
|
|
// Add deferred entries to compilation
|
|
const addEntryPromises = [];
|
|
const bundler = webpack;
|
|
debug('adding deferred entries:', Object.keys(this.deferredEntrypoints));
|
|
for (const [name, entryData] of Object.entries(this.deferredEntrypoints)){
|
|
debug('processing deferred entry:', name, entryData);
|
|
// Normalize entry data structure
|
|
let entry;
|
|
if (typeof entryData === 'string') {
|
|
entry = {
|
|
import: [
|
|
entryData
|
|
]
|
|
};
|
|
} else if (Array.isArray(entryData)) {
|
|
entry = {
|
|
import: entryData
|
|
};
|
|
} else {
|
|
entry = entryData;
|
|
}
|
|
// Get imports array
|
|
const imports = entry.import ? Array.isArray(entry.import) ? entry.import : [
|
|
entry.import
|
|
] : [];
|
|
if (imports.length === 0) {
|
|
continue;
|
|
}
|
|
// Normalize dependOn to always be an array
|
|
const dependOn = entry.dependOn ? Array.isArray(entry.dependOn) ? entry.dependOn : [
|
|
entry.dependOn
|
|
] : undefined;
|
|
// Create dependencies for all imports
|
|
for (const importPath of imports){
|
|
if (typeof importPath !== 'string') {
|
|
continue;
|
|
}
|
|
const dep = bundler.EntryPlugin.createDependency(importPath, {
|
|
name
|
|
});
|
|
addEntryPromises.push(new Promise((resolve, reject)=>{
|
|
compilation.addEntry(compiler.context, dep, {
|
|
name,
|
|
layer: entry.layer,
|
|
runtime: entry.runtime,
|
|
dependOn
|
|
}, (err)=>{
|
|
if (err) {
|
|
reject(err);
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
}));
|
|
}
|
|
}
|
|
await Promise.all(addEntryPromises);
|
|
});
|
|
}
|
|
}
|
|
|
|
//# sourceMappingURL=deferred-entries-plugin.js.map
|