chore: comments

This commit is contained in:
Ryuya 2025-07-27 22:44:29 -07:00
parent c94b2e9a1b
commit a47f4443d1
7 changed files with 35 additions and 40 deletions

View File

@ -155,13 +155,13 @@ URLDependency.Template = class URLDependencyTemplate extends (
runtimeRequirements.add(RuntimeGlobals.require); runtimeRequirements.add(RuntimeGlobals.require);
// Check if we need to add prefetch/preload runtime // Determine if prefetch/preload hints are specified
const needsPrefetch = dep.prefetch !== undefined && dep.prefetch !== false; const needsPrefetch = dep.prefetch !== undefined && dep.prefetch !== false;
const needsPreload = dep.preload !== undefined && dep.preload !== false; const needsPreload = dep.preload !== undefined && dep.preload !== false;
// Skip inline prefetch/preload if handled by startup module // Generate inline prefetch/preload code if not handled by startup module
if ((needsPrefetch || needsPreload) && !dep._startupPrefetch) { if ((needsPrefetch || needsPreload) && !dep._startupPrefetch) {
// Get the module to determine asset type // Resolve module to determine appropriate asset type
const module = moduleGraph.getModule(dep); const module = moduleGraph.getModule(dep);
let asType = ""; let asType = "";
@ -172,7 +172,7 @@ URLDependency.Template = class URLDependencyTemplate extends (
asType = getAssetType(request); asType = getAssetType(request);
} }
// Generate the module expression (just the module id) // Get the module ID for runtime code generation
const moduleExpr = runtimeTemplate.moduleRaw({ const moduleExpr = runtimeTemplate.moduleRaw({
chunkGraph, chunkGraph,
module: moduleGraph.getModule(dep), module: moduleGraph.getModule(dep),
@ -181,9 +181,9 @@ URLDependency.Template = class URLDependencyTemplate extends (
weak: false weak: false
}); });
// Build the prefetch/preload code // Construct prefetch/preload function calls
const hintCode = []; const hintCode = [];
// Only pass valid fetchPriority values // Validate fetchPriority against allowed values
const validFetchPriority = const validFetchPriority =
dep.fetchPriority && ["high", "low", "auto"].includes(dep.fetchPriority) dep.fetchPriority && ["high", "low", "auto"].includes(dep.fetchPriority)
? dep.fetchPriority ? dep.fetchPriority
@ -196,20 +196,20 @@ URLDependency.Template = class URLDependencyTemplate extends (
: "undefined"; : "undefined";
if (needsPrefetch && !needsPreload) { if (needsPrefetch && !needsPreload) {
// Only prefetch // Generate prefetch call
runtimeRequirements.add(RuntimeGlobals.prefetchAsset); runtimeRequirements.add(RuntimeGlobals.prefetchAsset);
hintCode.push( hintCode.push(
`${RuntimeGlobals.prefetchAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});` `${RuntimeGlobals.prefetchAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});`
); );
} else if (needsPreload) { } else if (needsPreload) {
// Preload (takes precedence over prefetch) // Generate preload call (overrides prefetch if both specified)
runtimeRequirements.add(RuntimeGlobals.preloadAsset); runtimeRequirements.add(RuntimeGlobals.preloadAsset);
hintCode.push( hintCode.push(
`${RuntimeGlobals.preloadAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});` `${RuntimeGlobals.preloadAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});`
); );
} }
// Wrap in IIFE to execute hint code and return URL // Create IIFE that generates URL and adds resource hints
if (dep.relative) { if (dep.relative) {
runtimeRequirements.add(RuntimeGlobals.relativeUrl); runtimeRequirements.add(RuntimeGlobals.relativeUrl);
source.replace( source.replace(
@ -234,7 +234,7 @@ URLDependency.Template = class URLDependencyTemplate extends (
); );
} }
} else if ((needsPrefetch || needsPreload) && dep._startupPrefetch) { } else if ((needsPrefetch || needsPreload) && dep._startupPrefetch) {
// Prefetch/preload handled by startup module - generate standard URL // Generate standard URL when prefetch/preload is handled by startup module
if (dep.relative) { if (dep.relative) {
runtimeRequirements.add(RuntimeGlobals.relativeUrl); runtimeRequirements.add(RuntimeGlobals.relativeUrl);
source.replace( source.replace(
@ -264,14 +264,14 @@ URLDependency.Template = class URLDependencyTemplate extends (
})}, ${RuntimeGlobals.baseURI}` })}, ${RuntimeGlobals.baseURI}`
); );
} }
// Still need to add runtime requirements for prefetch/preload // Register runtime requirements for prefetch/preload functions
if (needsPrefetch && !needsPreload) { if (needsPrefetch && !needsPreload) {
runtimeRequirements.add(RuntimeGlobals.prefetchAsset); runtimeRequirements.add(RuntimeGlobals.prefetchAsset);
} else if (needsPreload) { } else if (needsPreload) {
runtimeRequirements.add(RuntimeGlobals.preloadAsset); runtimeRequirements.add(RuntimeGlobals.preloadAsset);
} }
} else if (dep.relative) { } else if (dep.relative) {
// No prefetch/preload - use original code // Standard URL generation without resource hints
runtimeRequirements.add(RuntimeGlobals.relativeUrl); runtimeRequirements.add(RuntimeGlobals.relativeUrl);
source.replace( source.replace(
dep.outerRange[0], dep.outerRange[0],

View File

@ -41,12 +41,12 @@ class AssetPrefetchStartupPlugin {
const assetPrefetchMap = new WeakMap(); const assetPrefetchMap = new WeakMap();
const chunkAssetInfoMap = new WeakMap(); const chunkAssetInfoMap = new WeakMap();
// Hook into finishModules to collect all URLDependencies // Collect URLDependencies with prefetch/preload hints during module finalization
compilation.hooks.finishModules.tap(PLUGIN_NAME, (modules) => { compilation.hooks.finishModules.tap(PLUGIN_NAME, (modules) => {
for (const module of modules) { for (const module of modules) {
if (!module.dependencies) continue; if (!module.dependencies) continue;
// Collect URLDependencies with prefetch/preload // Find all URL dependencies that have prefetch or preload hints
const assetDeps = []; const assetDeps = [];
for (const dep of module.dependencies) { for (const dep of module.dependencies) {
if (dep.constructor.name === "URLDependency") { if (dep.constructor.name === "URLDependency") {
@ -64,7 +64,7 @@ class AssetPrefetchStartupPlugin {
} }
}); });
// Process assets when chunks are being optimized // Aggregate prefetch/preload assets by chunk during optimization
compilation.hooks.optimizeChunks.tap( compilation.hooks.optimizeChunks.tap(
{ name: PLUGIN_NAME, stage: 1 }, { name: PLUGIN_NAME, stage: 1 },
(chunks) => { (chunks) => {
@ -77,13 +77,13 @@ class AssetPrefetchStartupPlugin {
preload: /** @type {AssetInfo[]} */ ([]) preload: /** @type {AssetInfo[]} */ ([])
}; };
// Process all modules in this chunk // Iterate through all modules in the chunk
for (const module of chunkGraph.getChunkModules(chunk)) { for (const module of chunkGraph.getChunkModules(chunk)) {
const urlDeps = assetPrefetchMap.get(module); const urlDeps = assetPrefetchMap.get(module);
if (!urlDeps) continue; if (!urlDeps) continue;
for (const dep of urlDeps) { for (const dep of urlDeps) {
// Mark dependency as handled by startup prefetch // Flag this dependency as handled by startup module to prevent inline generation
dep._startupPrefetch = true; dep._startupPrefetch = true;
const resolvedModule = moduleGraph.getModule(dep); const resolvedModule = moduleGraph.getModule(dep);
@ -94,7 +94,7 @@ class AssetPrefetchStartupPlugin {
).request; ).request;
if (!request) continue; if (!request) continue;
// Get the actual asset filename from module buildInfo // Extract the asset filename from module metadata
let assetUrl; let assetUrl;
if ( if (
resolvedModule.buildInfo && resolvedModule.buildInfo &&
@ -102,7 +102,7 @@ class AssetPrefetchStartupPlugin {
) { ) {
assetUrl = resolvedModule.buildInfo.filename; assetUrl = resolvedModule.buildInfo.filename;
} else { } else {
// Fallback to extracting from request // Fall back to filename from request path
assetUrl = request.split(/[\\/]/).pop() || request; assetUrl = request.split(/[\\/]/).pop() || request;
} }
@ -160,18 +160,15 @@ class AssetPrefetchStartupPlugin {
} }
); );
// Ensure runtime functions are available
compilation.hooks.runtimeRequirementInTree compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.prefetchAsset) .for(RuntimeGlobals.prefetchAsset)
.tap(PLUGIN_NAME, (chunk, set) => { .tap(PLUGIN_NAME, (chunk, set) => {
// AssetPrefetchPreloadRuntimeModule will be added by URLParserPlugin
set.add(RuntimeGlobals.publicPath); set.add(RuntimeGlobals.publicPath);
}); });
compilation.hooks.runtimeRequirementInTree compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.preloadAsset) .for(RuntimeGlobals.preloadAsset)
.tap(PLUGIN_NAME, (chunk, set) => { .tap(PLUGIN_NAME, (chunk, set) => {
// AssetPrefetchPreloadRuntimeModule will be added by URLParserPlugin
set.add(RuntimeGlobals.publicPath); set.add(RuntimeGlobals.publicPath);
}); });
}); });

View File

@ -55,8 +55,8 @@ class AssetPrefetchStartupRuntimeModule extends RuntimeModule {
const lines = []; const lines = [];
/** /**
* @param {AssetInfo} asset The asset information to serialize * @param {AssetInfo} asset asset info object
* @returns {string} Serialized arguments for prefetch/preload function * @returns {string} serialized function arguments
*/ */
const serializeAsset = (asset) => { const serializeAsset = (asset) => {
const args = [ const args = [

View File

@ -19,7 +19,7 @@ class AssetPrefetchPreloadPlugin {
*/ */
apply(compiler) { apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
// Add runtime module for asset prefetch // Register runtime module for asset prefetch
compilation.hooks.runtimeRequirementInTree compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.prefetchAsset) .for(RuntimeGlobals.prefetchAsset)
.tap(PLUGIN_NAME, (chunk, set) => { .tap(PLUGIN_NAME, (chunk, set) => {
@ -29,7 +29,7 @@ class AssetPrefetchPreloadPlugin {
); );
}); });
// Add runtime module for asset preload // Register runtime module for asset preload
compilation.hooks.runtimeRequirementInTree compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.preloadAsset) .for(RuntimeGlobals.preloadAsset)
.tap(PLUGIN_NAME, (chunk, set) => { .tap(PLUGIN_NAME, (chunk, set) => {

View File

@ -47,7 +47,7 @@ class AssetPrefetchPreloadRuntimeModule extends RuntimeModule {
"link.setAttribute('fetchpriority', fetchPriority);" "link.setAttribute('fetchpriority', fetchPriority);"
]), ]),
"}", "}",
// Add nonce if needed // Apply nonce attribute for CSP if configured
compilation.outputOptions.crossOriginLoading compilation.outputOptions.crossOriginLoading
? Template.asString([ ? Template.asString([
`if(${RuntimeGlobals.scriptNonce}) {`, `if(${RuntimeGlobals.scriptNonce}) {`,

View File

@ -185,9 +185,9 @@ class URLParserPlugin {
); );
dep.loc = /** @type {DependencyLocation} */ (expr.loc); dep.loc = /** @type {DependencyLocation} */ (expr.loc);
// Handle prefetch/preload hints // Process magic comments for prefetch/preload hints
if (importOptions) { if (importOptions) {
// Validate webpackPrefetch // webpackPrefetch should be boolean true
if ( if (
importOptions.webpackPrefetch !== undefined && importOptions.webpackPrefetch !== undefined &&
importOptions.webpackPrefetch !== true importOptions.webpackPrefetch !== true
@ -200,7 +200,7 @@ class URLParserPlugin {
); );
} }
// Validate webpackPreload // webpackPreload should be boolean true
if ( if (
importOptions.webpackPreload !== undefined && importOptions.webpackPreload !== undefined &&
importOptions.webpackPreload !== true importOptions.webpackPreload !== true
@ -213,7 +213,7 @@ class URLParserPlugin {
); );
} }
// Validate webpackFetchPriority // webpackFetchPriority should be one of: high, low, auto
if ( if (
importOptions.webpackFetchPriority !== undefined && importOptions.webpackFetchPriority !== undefined &&
(typeof importOptions.webpackFetchPriority !== "string" || (typeof importOptions.webpackFetchPriority !== "string" ||
@ -229,7 +229,7 @@ class URLParserPlugin {
); );
} }
// Validate webpackPreloadAs // webpackPreloadAs should be a string
if ( if (
importOptions.webpackPreloadAs !== undefined && importOptions.webpackPreloadAs !== undefined &&
typeof importOptions.webpackPreloadAs !== "string" typeof importOptions.webpackPreloadAs !== "string"
@ -242,7 +242,7 @@ class URLParserPlugin {
); );
} }
// Validate webpackPreloadType // webpackPreloadType should be a string
if ( if (
importOptions.webpackPreloadType !== undefined && importOptions.webpackPreloadType !== undefined &&
typeof importOptions.webpackPreloadType !== "string" typeof importOptions.webpackPreloadType !== "string"
@ -255,7 +255,7 @@ class URLParserPlugin {
); );
} }
// Store hints on the dependency for later use // Store magic comment values on dependency
dep.prefetch = importOptions.webpackPrefetch; dep.prefetch = importOptions.webpackPrefetch;
dep.preload = importOptions.webpackPreload; dep.preload = importOptions.webpackPreload;
dep.fetchPriority = importOptions.webpackFetchPriority; dep.fetchPriority = importOptions.webpackFetchPriority;
@ -263,7 +263,7 @@ class URLParserPlugin {
dep.preloadType = importOptions.webpackPreloadType; dep.preloadType = importOptions.webpackPreloadType;
} }
// Add dependency directly // Register the dependency
parser.state.current.addDependency(dep); parser.state.current.addDependency(dep);
InnerGraph.onUsage(parser.state, (e) => (dep.usedByExports = e)); InnerGraph.onUsage(parser.state, (e) => (dep.usedByExports = e));
return true; return true;

View File

@ -7,10 +7,9 @@
/** /**
* Determines the 'as' attribute value for prefetch/preload based on file extension * Determines the 'as' attribute value for prefetch/preload based on file extension
* Reference: MDN rel=preload documentation
* https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/preload#what_types_of_content_can_be_preloaded * https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/preload#what_types_of_content_can_be_preloaded
* @param {string} request The module request string or filename * @param {string} request module request string or filename
* @returns {string} The 'as' attribute value for link element * @returns {string} asset type for link element 'as' attribute
*/ */
const getAssetType = (request) => { const getAssetType = (request) => {
if (/\.(png|jpe?g|gif|svg|webp|avif|bmp|ico|tiff?)$/i.test(request)) { if (/\.(png|jpe?g|gif|svg|webp|avif|bmp|ico|tiff?)$/i.test(request)) {
@ -26,8 +25,7 @@ const getAssetType = (request) => {
} else if ( } else if (
/\.(mp4|webm|ogg|mp3|wav|flac|aac|m4a|avi|mov|wmv|mkv)$/i.test(request) /\.(mp4|webm|ogg|mp3|wav|flac|aac|m4a|avi|mov|wmv|mkv)$/i.test(request)
) { ) {
// Audio/video files: use 'fetch' as fallback since as='audio'/'video' not supported // Audio/video files use 'fetch' as browser support varies
// Reference: https://github.com/mdn/browser-compat-data/issues/9577
return "fetch"; return "fetch";
} }
return "fetch"; return "fetch";