mirror of https://github.com/webpack/webpack.git
feat: add webpackPreloadType support for new URL() syntax
This commit is contained in:
parent
fb8bd910f0
commit
9532eea79c
|
@ -40,9 +40,8 @@ const getIgnoredRawDataUrlModule = memoize(
|
|||
* @returns {string} The 'as' attribute value
|
||||
*/
|
||||
const getAssetType = (request) => {
|
||||
// Reference: MDN rel=preload documentation (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel/preload)
|
||||
// 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)
|
||||
// Valid 'as' values: fetch, font, image, script, style, track
|
||||
// Note: audio/video are in spec but not supported by major browsers as of 2025
|
||||
if (/\.(png|jpe?g|gif|svg|webp|avif|bmp|ico|tiff?)$/i.test(request)) {
|
||||
return "image";
|
||||
} else if (/\.(woff2?|ttf|otf|eot)$/i.test(request)) {
|
||||
|
@ -59,8 +58,6 @@ const getAssetType = (request) => {
|
|||
// Audio/video files: use 'fetch' as fallback since as='audio'/'video' not supported
|
||||
// Reference: https://github.com/mdn/browser-compat-data/issues/9577
|
||||
return "fetch";
|
||||
} else if (/\.(json|xml|txt|csv|pdf|doc|docx|wasm)$/i.test(request)) {
|
||||
return "fetch"; // Data files, documents, WebAssembly
|
||||
}
|
||||
return "fetch"; // Generic fetch for unknown types
|
||||
};
|
||||
|
@ -121,6 +118,7 @@ class URLDependency extends ModuleDependency {
|
|||
write(this.preload);
|
||||
write(this.fetchPriority);
|
||||
write(this.preloadAs);
|
||||
write(this.preloadType);
|
||||
super.serialize(context);
|
||||
}
|
||||
|
||||
|
@ -136,6 +134,7 @@ class URLDependency extends ModuleDependency {
|
|||
this.preload = read();
|
||||
this.fetchPriority = read();
|
||||
this.preloadAs = read();
|
||||
this.preloadType = read();
|
||||
super.deserialize(context);
|
||||
}
|
||||
}
|
||||
|
@ -206,18 +205,21 @@ URLDependency.Template = class URLDependencyTemplate extends (
|
|||
const fetchPriority = validFetchPriority
|
||||
? `"${validFetchPriority}"`
|
||||
: "undefined";
|
||||
const preloadType = dep.preloadType
|
||||
? `"${dep.preloadType}"`
|
||||
: "undefined";
|
||||
|
||||
if (needsPrefetch && !needsPreload) {
|
||||
// Only prefetch
|
||||
runtimeRequirements.add(RuntimeGlobals.prefetchAsset);
|
||||
hintCode.push(
|
||||
`${RuntimeGlobals.prefetchAsset}(url, "${asType}", ${fetchPriority});`
|
||||
`${RuntimeGlobals.prefetchAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});`
|
||||
);
|
||||
} else if (needsPreload) {
|
||||
// Preload (takes precedence over prefetch)
|
||||
runtimeRequirements.add(RuntimeGlobals.preloadAsset);
|
||||
hintCode.push(
|
||||
`${RuntimeGlobals.preloadAsset}(url, "${asType}", ${fetchPriority});`
|
||||
`${RuntimeGlobals.preloadAsset}(url, "${asType}", ${fetchPriority}, ${preloadType});`
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,12 +33,13 @@ class AssetPrefetchPreloadRuntimeModule extends RuntimeModule {
|
|||
: RuntimeGlobals.preloadAsset;
|
||||
|
||||
return Template.asString([
|
||||
`${fn} = ${runtimeTemplate.basicFunction("url, as, fetchPriority", [
|
||||
`${fn} = ${runtimeTemplate.basicFunction("url, as, fetchPriority, type", [
|
||||
"var link = document.createElement('link');",
|
||||
this._type === "prefetch"
|
||||
? "link.rel = 'prefetch';"
|
||||
: "link.rel = 'preload';",
|
||||
"if(as) link.as = as;",
|
||||
"if(type) link.type = type;",
|
||||
"link.href = url;",
|
||||
"if(fetchPriority) {",
|
||||
Template.indent([
|
||||
|
|
|
@ -242,11 +242,25 @@ class URLParserPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
// Validate webpackPreloadType
|
||||
if (
|
||||
importOptions.webpackPreloadType !== undefined &&
|
||||
typeof importOptions.webpackPreloadType !== "string"
|
||||
) {
|
||||
parser.state.module.addWarning(
|
||||
new UnsupportedFeatureWarning(
|
||||
`\`webpackPreloadType\` expected a string, but received: ${importOptions.webpackPreloadType}.`,
|
||||
/** @type {DependencyLocation} */ (expr.loc)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Store hints on the dependency for later use
|
||||
dep.prefetch = importOptions.webpackPrefetch;
|
||||
dep.preload = importOptions.webpackPreload;
|
||||
dep.fetchPriority = importOptions.webpackFetchPriority;
|
||||
dep.preloadAs = importOptions.webpackPreloadAs;
|
||||
dep.preloadType = importOptions.webpackPreloadType;
|
||||
}
|
||||
|
||||
// Add dependency directly
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background-color: #f0f0f0;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
.typed-element {
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
// Invalid fetchPriority value - should generate warning
|
||||
const invalidPriorityUrl = new URL(/* webpackPrefetch: true */ /* webpackFetchPriority: "invalid" */ "./assets/images/priority-invalid.png", import.meta.url);
|
||||
|
||||
// Both prefetch and preload specified - no warning anymore (preload takes precedence)
|
||||
const bothHintsUrl = new URL(/* webpackPrefetch: true */ /* webpackPreload: true */ /* webpackFetchPriority: "high" */ "./assets/images/both-hints.png", import.meta.url);
|
||||
// Invalid webpackPreloadType value - should generate warning
|
||||
const invalidTypeUrl = new URL(/* webpackPreload: true */ /* webpackPreloadType: 123 */ "./assets/styles/invalid-type.css", import.meta.url);
|
||||
|
||||
export default {};
|
||||
|
|
|
@ -86,9 +86,8 @@ it("should handle multiple URLs with different priorities", () => {
|
|||
});
|
||||
|
||||
it("should prefer preload over prefetch when both are specified", () => {
|
||||
// Note: The warning for both hints is tested in generate-warnings.js
|
||||
// Here we just verify that preload takes precedence
|
||||
const bothUrl = new URL(/* webpackPreload: true */ /* webpackFetchPriority: "high" */ "./assets/images/test.png", import.meta.url);
|
||||
// When both prefetch and preload are specified, preload takes precedence
|
||||
const bothUrl = new URL(/* webpackPrefetch: true */ /* webpackPreload: true */ /* webpackFetchPriority: "high" */ "./assets/images/both-hints.png", import.meta.url);
|
||||
|
||||
expect(document.head._children).toHaveLength(1);
|
||||
const link1 = document.head._children[0];
|
||||
|
@ -97,6 +96,19 @@ it("should prefer preload over prefetch when both are specified", () => {
|
|||
expect(link1._attributes.fetchpriority).toBe("high");
|
||||
});
|
||||
|
||||
it("should handle webpackPreloadType for CSS files", () => {
|
||||
// Test preload with custom type
|
||||
const cssUrl = new URL(/* webpackPreload: true */ /* webpackPreloadType: "text/css" */ "./assets/styles/typed.css", import.meta.url);
|
||||
|
||||
expect(document.head._children).toHaveLength(1);
|
||||
const link1 = document.head._children[0];
|
||||
expect(link1._type).toBe("link");
|
||||
expect(link1.rel).toBe("preload");
|
||||
expect(link1.as).toBe("style");
|
||||
expect(link1.type).toBe("text/css");
|
||||
expect(link1.href.toString()).toMatch(/typed\.css$/);
|
||||
});
|
||||
|
||||
it("should handle different asset types correctly", () => {
|
||||
// Image
|
||||
const imageUrl = new URL(/* webpackPrefetch: true */ /* webpackFetchPriority: "high" */ "./assets/images/test.png", import.meta.url);
|
||||
|
|
|
@ -60,10 +60,11 @@ module.exports = {
|
|||
moduleScope(scope) {
|
||||
// Inject runtime globals that would normally be provided by webpack
|
||||
scope.__webpack_require__ = {
|
||||
PA(url, as, fetchPriority) {
|
||||
PA(url, as, fetchPriority, type) {
|
||||
const link = global.document.createElement("link");
|
||||
link.rel = "prefetch";
|
||||
if (as) link.as = as;
|
||||
if (type) link.type = type;
|
||||
link.href = url;
|
||||
if (fetchPriority) {
|
||||
link.fetchPriority = fetchPriority;
|
||||
|
@ -71,10 +72,11 @@ module.exports = {
|
|||
}
|
||||
global.document.head.appendChild(link);
|
||||
},
|
||||
LA(url, as, fetchPriority) {
|
||||
LA(url, as, fetchPriority, type) {
|
||||
const link = global.document.createElement("link");
|
||||
link.rel = "preload";
|
||||
if (as) link.as = as;
|
||||
if (type) link.type = type;
|
||||
link.href = url;
|
||||
if (fetchPriority) {
|
||||
link.fetchPriority = fetchPriority;
|
||||
|
|
|
@ -4,5 +4,7 @@ module.exports = [
|
|||
// Invalid fetchPriority value warning
|
||||
[
|
||||
/`webpackFetchPriority` expected "low", "high" or "auto", but received: invalid\./
|
||||
]
|
||||
],
|
||||
// Invalid webpackPreloadType value warning
|
||||
[/`webpackPreloadType` expected a string, but received: 123\./]
|
||||
];
|
||||
|
|
Loading…
Reference in New Issue