mirror of https://github.com/webpack/webpack.git
feat: add preload options for enhanced asset loading
- Introduced `preloadAs`, `preloadType`, and `preloadMedia` properties to `URLDependency` for better control over asset preloading.
This commit is contained in:
parent
37632364c5
commit
3c30c24d8f
|
@ -231,6 +231,7 @@
|
|||
"serializables",
|
||||
"serializer",
|
||||
"serializers",
|
||||
"serviceworker",
|
||||
"shama",
|
||||
"skypack",
|
||||
"snapshotting",
|
||||
|
|
|
@ -52,6 +52,12 @@ class URLDependency extends ModuleDependency {
|
|||
this.prefetch = undefined;
|
||||
this.preload = undefined;
|
||||
this.fetchPriority = undefined;
|
||||
/** @type {string|undefined} */
|
||||
this.preloadAs = undefined;
|
||||
/** @type {string|undefined} */
|
||||
this.preloadType = undefined;
|
||||
/** @type {string|undefined} */
|
||||
this.preloadMedia = undefined;
|
||||
}
|
||||
|
||||
get type() {
|
||||
|
@ -93,6 +99,9 @@ class URLDependency extends ModuleDependency {
|
|||
write(this.prefetch);
|
||||
write(this.preload);
|
||||
write(this.fetchPriority);
|
||||
write(this.preloadAs);
|
||||
write(this.preloadType);
|
||||
write(this.preloadMedia);
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
|
@ -107,6 +116,9 @@ class URLDependency extends ModuleDependency {
|
|||
this.prefetch = read();
|
||||
this.preload = read();
|
||||
this.fetchPriority = read();
|
||||
this.preloadAs = read();
|
||||
this.preloadType = read();
|
||||
this.preloadMedia = read();
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +215,7 @@ URLDependency.Template = class URLDependencyTemplate extends (
|
|||
// Prefetch/Preload via InitFragment
|
||||
if ((dep.prefetch || dep.preload) && module) {
|
||||
const request = dep.request;
|
||||
const assetType = URLDependencyTemplate._getAssetType(request);
|
||||
const detectedAssetType = URLDependencyTemplate._getAssetType(request);
|
||||
const id = chunkGraph.getModuleId(module);
|
||||
if (id !== null) {
|
||||
const moduleId = runtimeTemplate.moduleId({
|
||||
|
@ -215,13 +227,19 @@ URLDependency.Template = class URLDependencyTemplate extends (
|
|||
|
||||
if (dep.preload) {
|
||||
runtimeRequirements.add(RuntimeGlobals.preloadAsset);
|
||||
const asArg = JSON.stringify(dep.preloadAs || detectedAssetType);
|
||||
const fetchPriorityArg = dep.fetchPriority
|
||||
? JSON.stringify(dep.fetchPriority)
|
||||
: "undefined";
|
||||
const typeArg = dep.preloadType
|
||||
? JSON.stringify(dep.preloadType)
|
||||
: "undefined";
|
||||
const mediaArg = dep.preloadMedia
|
||||
? JSON.stringify(dep.preloadMedia)
|
||||
: "undefined";
|
||||
initFragments.push(
|
||||
new InitFragment(
|
||||
`${RuntimeGlobals.preloadAsset}(${moduleId}, ${JSON.stringify(
|
||||
assetType
|
||||
)}${dep.fetchPriority ? `, ${JSON.stringify(dep.fetchPriority)}` : ""}, ${
|
||||
dep.relative
|
||||
});\n`,
|
||||
`${RuntimeGlobals.preloadAsset}(${moduleId}, ${asArg}, ${fetchPriorityArg}, ${typeArg}, ${mediaArg}, ${dep.relative});\n`,
|
||||
InitFragment.STAGE_CONSTANTS,
|
||||
-10,
|
||||
`asset_preload_${moduleId}`
|
||||
|
@ -229,13 +247,13 @@ URLDependency.Template = class URLDependencyTemplate extends (
|
|||
);
|
||||
} else if (dep.prefetch) {
|
||||
runtimeRequirements.add(RuntimeGlobals.prefetchAsset);
|
||||
const asArg = JSON.stringify(detectedAssetType);
|
||||
const fetchPriorityArg = dep.fetchPriority
|
||||
? JSON.stringify(dep.fetchPriority)
|
||||
: "undefined";
|
||||
initFragments.push(
|
||||
new InitFragment(
|
||||
`${RuntimeGlobals.prefetchAsset}(${moduleId}, ${JSON.stringify(
|
||||
assetType
|
||||
)}${dep.fetchPriority ? `, ${JSON.stringify(dep.fetchPriority)}` : ""}, ${
|
||||
dep.relative
|
||||
});\n`,
|
||||
`${RuntimeGlobals.prefetchAsset}(${moduleId}, ${asArg}, ${fetchPriorityArg}, undefined, undefined, ${dep.relative});\n`,
|
||||
InitFragment.STAGE_CONSTANTS,
|
||||
-5,
|
||||
`asset_prefetch_${moduleId}`
|
||||
|
|
|
@ -61,6 +61,9 @@ class ResourcePrefetchRuntimeModule extends RuntimeModule {
|
|||
]),
|
||||
"}",
|
||||
"",
|
||||
"if (type) link.type = type;",
|
||||
"if (media) link.media = media;",
|
||||
"",
|
||||
crossOriginLoading
|
||||
? Template.asString([
|
||||
"if (link.href.indexOf(window.location.origin + '/') !== 0) {",
|
||||
|
@ -78,7 +81,7 @@ class ResourcePrefetchRuntimeModule extends RuntimeModule {
|
|||
if (isNeutralPlatform) {
|
||||
return Template.asString([
|
||||
`${fnName} = ${runtimeTemplate.basicFunction(
|
||||
"moduleId, as, fetchPriority, relative",
|
||||
"moduleId, as, fetchPriority, type, media, relative",
|
||||
[
|
||||
"// Only execute in browser environment",
|
||||
"if (typeof document !== 'undefined') {",
|
||||
|
@ -92,7 +95,7 @@ class ResourcePrefetchRuntimeModule extends RuntimeModule {
|
|||
// For browser-only targets, generate code without the check
|
||||
return Template.asString([
|
||||
`${fnName} = ${runtimeTemplate.basicFunction(
|
||||
"moduleId, as, fetchPriority, relative",
|
||||
"moduleId, as, fetchPriority, type, media, relative",
|
||||
code
|
||||
)};`
|
||||
]);
|
||||
|
|
|
@ -224,6 +224,75 @@ class URLParserPlugin {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
// webpackPreloadAs: allow override of the "as" attribute for preload
|
||||
// Fetch Standard: Request destinations (enumerates destinations used by `as`) https://fetch.spec.whatwg.org/#concept-request-destination
|
||||
if (importOptions.webpackPreloadAs !== undefined) {
|
||||
const allowedAs = [
|
||||
// Per HTML LS "match-preload-type" + Fetch Standard request destinations
|
||||
// See references above
|
||||
"audio",
|
||||
"audioworklet",
|
||||
"document",
|
||||
"embed",
|
||||
"fetch",
|
||||
"font",
|
||||
"image",
|
||||
"manifest",
|
||||
"object",
|
||||
"paintworklet",
|
||||
"report",
|
||||
"script",
|
||||
"sharedworker",
|
||||
"serviceworker",
|
||||
"style",
|
||||
"track",
|
||||
"video",
|
||||
"worker",
|
||||
"xslt"
|
||||
];
|
||||
if (
|
||||
typeof importOptions.webpackPreloadAs === "string" &&
|
||||
allowedAs.includes(importOptions.webpackPreloadAs)
|
||||
) {
|
||||
dep.preloadAs = importOptions.webpackPreloadAs;
|
||||
} else {
|
||||
parser.state.module.addWarning(
|
||||
new UnsupportedFeatureWarning(
|
||||
`\`webpackPreloadAs\` expected one of ${JSON.stringify(allowedAs)}, but received: ${importOptions.webpackPreloadAs}.`,
|
||||
/** @type {DependencyLocation} */ (expr.loc)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// webpackPreloadType: set link.type when provided
|
||||
if (importOptions.webpackPreloadType !== undefined) {
|
||||
if (typeof importOptions.webpackPreloadType === "string") {
|
||||
dep.preloadType = importOptions.webpackPreloadType;
|
||||
} else {
|
||||
parser.state.module.addWarning(
|
||||
new UnsupportedFeatureWarning(
|
||||
`\`webpackPreloadType\` expected a string, but received: ${importOptions.webpackPreloadType}.`,
|
||||
/** @type {DependencyLocation} */ (expr.loc)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// webpackPreloadMedia: set link.media when provided
|
||||
if (importOptions.webpackPreloadMedia !== undefined) {
|
||||
if (typeof importOptions.webpackPreloadMedia === "string") {
|
||||
dep.preloadMedia = importOptions.webpackPreloadMedia;
|
||||
} else {
|
||||
parser.state.module.addWarning(
|
||||
new UnsupportedFeatureWarning(
|
||||
`\`webpackPreloadMedia\` expected a string, but received: ${importOptions.webpackPreloadMedia}.`,
|
||||
/** @type {DependencyLocation} */ (expr.loc)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Register the dependency
|
||||
|
|
Loading…
Reference in New Issue