fix: no extra runtime for external asset modules in CSS

This commit is contained in:
Alexander Akait 2024-10-23 22:03:15 +03:00 committed by GitHub
commit abe931a19b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 156 additions and 14 deletions

View File

@ -55,8 +55,9 @@ const { register } = require("./util/serialization");
/** @typedef {{ attributes?: ImportAttributes, externalType: "import" | "module" | undefined }} ImportDependencyMeta */ /** @typedef {{ attributes?: ImportAttributes, externalType: "import" | "module" | undefined }} ImportDependencyMeta */
/** @typedef {{ layer?: string, supports?: string, media?: string }} CssImportDependencyMeta */ /** @typedef {{ layer?: string, supports?: string, media?: string }} CssImportDependencyMeta */
/** @typedef {{ sourceType: "css-url" }} AssetDependencyMeta */
/** @typedef {ImportDependencyMeta | CssImportDependencyMeta} DependencyMeta */ /** @typedef {ImportDependencyMeta | CssImportDependencyMeta | AssetDependencyMeta} DependencyMeta */
/** /**
* @typedef {object} SourceData * @typedef {object} SourceData
@ -69,6 +70,7 @@ const { register } = require("./util/serialization");
const TYPES = new Set(["javascript"]); const TYPES = new Set(["javascript"]);
const CSS_TYPES = new Set(["css-import"]); const CSS_TYPES = new Set(["css-import"]);
const CSS_URL_TYPES = new Set(["css-url"]);
const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]); const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]); const RUNTIME_REQUIREMENTS_FOR_SCRIPT = new Set([RuntimeGlobals.loadScript]);
const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([ const RUNTIME_REQUIREMENTS_FOR_MODULE = new Set([
@ -500,7 +502,18 @@ class ExternalModule extends Module {
* @returns {SourceTypes} types available (do not mutate) * @returns {SourceTypes} types available (do not mutate)
*/ */
getSourceTypes() { getSourceTypes() {
return this.externalType === "css-import" ? CSS_TYPES : TYPES; if (
this.externalType === "asset" &&
this.dependencyMeta &&
/** @type {AssetDependencyMeta} */
(this.dependencyMeta).sourceType === "css-url"
) {
return CSS_URL_TYPES;
} else if (this.externalType === "css-import") {
return CSS_TYPES;
}
return TYPES;
} }
/** /**
@ -674,12 +687,24 @@ class ExternalModule extends Module {
if (externalType === "module-import") { if (externalType === "module-import") {
if ( if (
this.dependencyMeta && this.dependencyMeta &&
/** @type {ImportDependencyMeta} */ (this.dependencyMeta).externalType /** @type {ImportDependencyMeta} */
(this.dependencyMeta).externalType
) { ) {
return /** @type {ImportDependencyMeta} */ (this.dependencyMeta) return /** @type {ImportDependencyMeta} */ (this.dependencyMeta)
.externalType; .externalType;
} }
return "module"; return "module";
} else if (externalType === "asset") {
if (
this.dependencyMeta &&
/** @type {AssetDependencyMeta} */
(this.dependencyMeta).sourceType
) {
return /** @type {AssetDependencyMeta} */ (this.dependencyMeta)
.sourceType;
}
return "asset";
} }
return externalType; return externalType;
@ -816,10 +841,13 @@ class ExternalModule extends Module {
new RawSource(`module.exports = ${JSON.stringify(request)};`) new RawSource(`module.exports = ${JSON.stringify(request)};`)
); );
const data = new Map(); const data = new Map();
data.set("url", { data.set("url", { javascript: request });
javascript: request, return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
"css-url": request }
}); case "css-url": {
const sources = new Map();
const data = new Map();
data.set("url", { "css-url": request });
return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data }; return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS, data };
} }
case "css-import": { case "css-import": {

View File

@ -9,6 +9,7 @@ const util = require("util");
const ExternalModule = require("./ExternalModule"); const ExternalModule = require("./ExternalModule");
const ContextElementDependency = require("./dependencies/ContextElementDependency"); const ContextElementDependency = require("./dependencies/ContextElementDependency");
const CssImportDependency = require("./dependencies/CssImportDependency"); const CssImportDependency = require("./dependencies/CssImportDependency");
const CssUrlDependency = require("./dependencies/CssUrlDependency");
const HarmonyImportDependency = require("./dependencies/HarmonyImportDependency"); const HarmonyImportDependency = require("./dependencies/HarmonyImportDependency");
const ImportDependency = require("./dependencies/ImportDependency"); const ImportDependency = require("./dependencies/ImportDependency");
const { resolveByProperty, cachedSetProperty } = require("./util/cleverMerge"); const { resolveByProperty, cachedSetProperty } = require("./util/cleverMerge");
@ -117,6 +118,8 @@ class ExternalModuleFactoryPlugin {
} }
} }
const resolvedType = /** @type {string} */ (type || globalType);
// TODO make it pluggable/add hooks to `ExternalModule` to allow output modules own externals? // TODO make it pluggable/add hooks to `ExternalModule` to allow output modules own externals?
/** @type {DependencyMeta | undefined} */ /** @type {DependencyMeta | undefined} */
let dependencyMeta; let dependencyMeta;
@ -145,12 +148,18 @@ class ExternalModuleFactoryPlugin {
}; };
} }
if (
resolvedType === "asset" &&
dependency instanceof CssUrlDependency
) {
dependencyMeta = { sourceType: "css-url" };
}
callback( callback(
null, null,
new ExternalModule( new ExternalModule(
externalConfig, externalConfig,
/** @type {string} */ resolvedType,
(type || globalType),
dependency.request, dependency.request,
dependencyMeta dependencyMeta
) )

View File

@ -4921,7 +4921,7 @@ Array [
background: background:
url(img.png), url(img.png),
url(img.png), url(img.png),
url(data:image/png;base64,AAA); url(d4da020aedcd249a7a41.png);
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=),
url(resource.png), url(resource.png),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=),
@ -4929,6 +4929,22 @@ Array [
url(https://example.com/img.png); url(https://example.com/img.png);
} }
.class-2 {
background: url(shared.png);
}
.class-3 {
background: url(shared-external.png);
}
.class-4 {
background: url(cde81354a9a8ce8d5f51.gif);
}
.class-5 {
background: url(5649e83cc54c4b57bc28.png);
}
head{--webpack-main:&\\\\.\\\\/style\\\\.css;}", head{--webpack-main:&\\\\.\\\\/style\\\\.css;}",
] ]
`; `;

View File

@ -4921,7 +4921,7 @@ Array [
background: background:
url(img.png), url(img.png),
url(img.png), url(img.png),
url(data:image/png;base64,AAA); url(d4da020aedcd249a7a41.png);
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=),
url(resource.png), url(resource.png),
url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=), url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=),
@ -4929,6 +4929,22 @@ Array [
url(https://example.com/img.png); url(https://example.com/img.png);
} }
.class-2 {
background: url(shared.png);
}
.class-3 {
background: url(shared-external.png);
}
.class-4 {
background: url(cde81354a9a8ce8d5f51.gif);
}
.class-5 {
background: url(5649e83cc54c4b57bc28.png);
}
head{--webpack-main:&\\\\.\\\\/style\\\\.css;}", head{--webpack-main:&\\\\.\\\\/style\\\\.css;}",
] ]
`; `;

View File

@ -10,5 +10,38 @@ it("should compile", () => {
} }
expect(css).toMatchSnapshot(); expect(css).toMatchSnapshot();
expect(Object.keys(__webpack_modules__).length).toBe(3) expect(Object.keys(__webpack_modules__).length).toBe(7);
expect(__webpack_modules__['./index.js']).toBeDefined();
expect(__webpack_modules__['./shared-external.png']).toBeDefined();
expect(__webpack_modules__['./shared.png']).toBeDefined();
expect(__webpack_modules__['data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAABNJREFUCB1jZGBg+A/EDEwgAgQADigBA//q6GsAAAAASUVORK5CYII%3D']).toBeDefined();
expect(__webpack_modules__['data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwIj48dGl0bGU+aWNvbi1zcXVhcmUtc21hbGw8L3RpdGxlPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik0zMDAgLjFMNTY1IDE1MHYyOTkuOUwzMDAgNTk5LjggMzUgNDQ5LjlWMTUweiIvPjxwYXRoIGZpbGw9IiM4RUQ2RkIiIGQ9Ik01MTcuNyA0MzkuNUwzMDguOCA1NTcuOHYtOTJMNDM5IDM5NC4xbDc4LjcgNDUuNHptMTQuMy0xMi45VjE3OS40bC03Ni40IDQ0LjF2MTU5bDc2LjQgNDQuMXpNODEuNSA0MzkuNWwyMDguOSAxMTguMnYtOTJsLTEzMC4yLTcxLjYtNzguNyA0NS40em0tMTQuMy0xMi45VjE3OS40bDc2LjQgNDQuMXYxNTlsLTc2LjQgNDQuMXptOC45LTI2My4yTDI5MC40IDQyLjJ2ODlsLTEzNy4zIDc1LjUtMS4xLjYtNzUuOS00My45em00NDYuOSAwTDMwOC44IDQyLjJ2ODlMNDQ2IDIwNi44bDEuMS42IDc1LjktNDR6Ii8+PHBhdGggZmlsbD0iIzFDNzhDMCIgZD0iTTI5MC40IDQ0NC44TDE2MiAzNzQuMVYyMzQuMmwxMjguNCA3NC4xdjEzNi41em0xOC40IDBsMTI4LjQtNzAuNnYtMTQwbC0xMjguNCA3NC4xdjEzNi41ek0yOTkuNiAzMDN6bS0xMjktODVsMTI5LTcwLjlMNDI4LjUgMjE4bC0xMjguOSA3NC40LTEyOS03NC40eiIvPjwvc3ZnPgo=']).toBeDefined();
expect(__webpack_modules__['https://example.com/only-external.png']).toBeDefined();
expect(__webpack_modules__['./style.css']).toBeDefined();
});
it("should work with shared asset module", () => {
const img = new URL("./shared.png", import.meta.url);
expect(img.href.endsWith("shared.png")).toBe(true);
});
it("should work with shared external asset module", () => {
const img = new URL("./shared-external.png", import.meta.url);
expect(img.href.endsWith("shared-external.png")).toBe(true);
});
it("should work with external asset module", () => {
const img = new URL("https://example.com/only-external.png", import.meta.url);
expect(img.href.endsWith("only-external.png")).toBe(true);
});
it("should work and extract DataURI", () => {
const img = new URL("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MDAgNjAwIj48dGl0bGU+aWNvbi1zcXVhcmUtc21hbGw8L3RpdGxlPjxwYXRoIGZpbGw9IiNGRkYiIGQ9Ik0zMDAgLjFMNTY1IDE1MHYyOTkuOUwzMDAgNTk5LjggMzUgNDQ5LjlWMTUweiIvPjxwYXRoIGZpbGw9IiM4RUQ2RkIiIGQ9Ik01MTcuNyA0MzkuNUwzMDguOCA1NTcuOHYtOTJMNDM5IDM5NC4xbDc4LjcgNDUuNHptMTQuMy0xMi45VjE3OS40bC03Ni40IDQ0LjF2MTU5bDc2LjQgNDQuMXpNODEuNSA0MzkuNWwyMDguOSAxMTguMnYtOTJsLTEzMC4yLTcxLjYtNzguNyA0NS40em0tMTQuMy0xMi45VjE3OS40bDc2LjQgNDQuMXYxNTlsLTc2LjQgNDQuMXptOC45LTI2My4yTDI5MC40IDQyLjJ2ODlsLTEzNy4zIDc1LjUtMS4xLjYtNzUuOS00My45em00NDYuOSAwTDMwOC44IDQyLjJ2ODlMNDQ2IDIwNi44bDEuMS42IDc1LjktNDR6Ii8+PHBhdGggZmlsbD0iIzFDNzhDMCIgZD0iTTI5MC40IDQ0NC44TDE2MiAzNzQuMVYyMzQuMmwxMjguNCA3NC4xdjEzNi41em0xOC40IDBsMTI4LjQtNzAuNnYtMTQwbC0xMjguNCA3NC4xdjEzNi41ek0yOTkuNiAzMDN6bS0xMjktODVsMTI5LTcwLjlMNDI4LjUgMjE4bC0xMjguOSA3NC40LTEyOS03NC40eiIvPjwvc3ZnPgo=", import.meta.url);
expect(img.href.endsWith(".svg")).toBe(true);
});
it("should work and extract shared DataURI", () => {
const img = new URL("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAABNJREFUCB1jZGBg+A/EDEwgAgQADigBA//q6GsAAAAASUVORK5CYII%3D", import.meta.url);
expect(img.href.endsWith(".png")).toBe(true);
}); });

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -10,3 +10,19 @@
url('data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'), url('data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'),
url('https://example.com/img.png'); url('https://example.com/img.png');
} }
.class-2 {
background: url("./shared.png");
}
.class-3 {
background: url("./shared-external.png");
}
.class-4 {
background: url("data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=");
}
.class-5 {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAABNJREFUCB1jZGBg+A/EDEwgAgQADigBA//q6GsAAAAASUVORK5CYII%3D");
}

View File

@ -23,10 +23,25 @@ module.exports = {
{ {
mimetype: "text/html", mimetype: "text/html",
type: "asset/resource" type: "asset/resource"
},
{
mimetype: "image/svg",
type: "asset/resource"
},
{
mimetype: "image/gif",
type: "asset/resource"
},
{
mimetype: "image/png",
type: "asset/resource"
} }
] ]
}, },
output: { output: {
assetModuleFilename: "[name][ext]" assetModuleFilename: "[name][ext]"
},
externals: {
"shared-external.png": "asset shared-external.png"
} }
}; };

13
types.d.ts vendored
View File

@ -275,6 +275,9 @@ declare interface Asset {
*/ */
info: AssetInfo; info: AssetInfo;
} }
declare interface AssetDependencyMeta {
sourceType: "css-url";
}
declare interface AssetEmittedInfo { declare interface AssetEmittedInfo {
content: Buffer; content: Buffer;
source: Source; source: Source;
@ -4588,12 +4591,18 @@ declare class ExternalModule extends Module {
request: string | string[] | RequestRecord, request: string | string[] | RequestRecord,
type: string, type: string,
userRequest: string, userRequest: string,
dependencyMeta?: ImportDependencyMeta | CssImportDependencyMeta dependencyMeta?:
| ImportDependencyMeta
| CssImportDependencyMeta
| AssetDependencyMeta
); );
request: string | string[] | Record<string, string | string[]>; request: string | string[] | Record<string, string | string[]>;
externalType: string; externalType: string;
userRequest: string; userRequest: string;
dependencyMeta?: ImportDependencyMeta | CssImportDependencyMeta; dependencyMeta?:
| ImportDependencyMeta
| CssImportDependencyMeta
| AssetDependencyMeta;
/** /**
* restore unsafe cache data * restore unsafe cache data