Merge pull request #10457 from webpack/feat-support-query-for-asset-modules

feat: support `[query]` for asset modules
This commit is contained in:
Tobias Koppers 2020-08-04 16:00:55 +02:00 committed by GitHub
commit a348f9558d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 103 additions and 17 deletions

View File

@ -9,6 +9,7 @@ const { basename, extname } = require("path");
const util = require("util");
const Chunk = require("./Chunk");
const Module = require("./Module");
const { parseResource } = require("./util/identifier");
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
/** @typedef {import("./Compilation").PathData} PathData */
@ -96,26 +97,17 @@ const replacePathVariables = (path, data, assetInfo) => {
//
// Placeholders
//
// for /some/path/file.js?query:
// for /some/path/file.js?query#fragment:
// [file] - /some/path/file.js
// [query] - ?query
// [fragment] - #fragment
// [base] - file.js
// [path] - /some/path/
// [name] - file
// [ext] - .js
if (data.filename) {
if (typeof data.filename === "string") {
const idx = data.filename.indexOf("?");
let file, query;
if (idx >= 0) {
file = data.filename.substr(0, idx);
query = data.filename.substr(idx);
} else {
file = data.filename;
query = "";
}
const { path: file, query, fragment } = parseResource(data.filename);
const ext = extname(file);
const base = basename(file);
@ -124,6 +116,7 @@ const replacePathVariables = (path, data, assetInfo) => {
replacements.set("file", replacer(file));
replacements.set("query", replacer(query, true));
replacements.set("fragment", replacer(fragment, true));
replacements.set("path", replacer(path, true));
replacements.set("base", replacer(base));
replacements.set("name", replacer(name));

View File

@ -62,7 +62,7 @@ class AssetGenerator extends Generator {
null,
originalSource.source(),
{
filename: module.nameForCondition(),
filename: module.matchResource || module.resource,
module
}
);
@ -131,7 +131,7 @@ class AssetGenerator extends Generator {
} = this.compilation.getAssetPathWithInfo(assetModuleFilename, {
module,
runtime,
filename: module.nameForCondition(),
filename: module.matchResource || module.resource,
chunkGraph,
contentHash
});

View File

@ -34,7 +34,7 @@ class AssetParser extends Parser {
if (typeof this.dataUrlCondition === "function") {
state.module.buildInfo.dataUrl = this.dataUrlCondition(source, {
filename: state.module.nameForCondition(),
filename: state.module.matchResource || state.module.resource,
module: state.module
});
} else if (typeof this.dataUrlCondition === "boolean") {

View File

@ -533,7 +533,7 @@ const applyOutputDefaults = (
}
return "[id].js";
});
D(output, "assetModuleFilename", "[hash][ext]");
D(output, "assetModuleFilename", "[hash][ext][query]");
D(output, "webassemblyModuleFilename", "[hash].module.wasm");
D(output, "publicPath", "");
D(output, "compareBeforeEmit", true);

View File

@ -206,7 +206,7 @@ describe("Defaults", () => {
"usedExports": false,
},
"output": Object {
"assetModuleFilename": "[hash][ext]",
"assetModuleFilename": "[hash][ext][query]",
"chunkCallbackName": "webpackChunkwebpack",
"chunkFilename": "[name].js",
"chunkLoadTimeout": 120000,

View File

@ -0,0 +1,9 @@
import png from "../_images/file.png?foo=bar";
import svg from "../_images/file.svg";
import jpg from "../_images/file.jpg?foo=bar#hash";
it("should output various asset types", () => {
expect(png).toContain("data:image/png;base64,");
expect(svg).toMatch(/^[\da-f]{20}\.svg$/);
expect(jpg).toContain("data:image/jpeg;base64,");
});

View File

@ -0,0 +1,19 @@
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.(png|svg|jpg)$/,
type: "asset",
parser: {
dataUrlCondition: (source, { filename, module }) => {
return filename.includes("?foo=bar");
}
}
}
]
},
experiments: {
asset: true
}
};

View File

@ -0,0 +1,9 @@
import png from "../_images/file.png";
import svg from "../_images/file.svg?foo=bar";
import jpg from "../_images/file.jpg";
it("should output various asset types", () => {
expect(png).toMatch(/^data:image\/png;base64,[0-9a-zA-Z+/]+=*$/);
expect(svg).toMatch(/^data:image\/svg\+xml,/);
expect(jpg).toMatch(/^data:image\/jpeg;base64,[0-9a-zA-Z+/]+=*$/);
});

View File

@ -0,0 +1,33 @@
const svgToMiniDataURI = require("mini-svg-data-uri");
const mimeTypes = require("mime-types");
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.(png|svg|jpg)$/,
type: "asset/inline",
generator: {
dataUrl: (source, { filename, module }) => {
if (filename.endsWith("?foo=bar")) {
if (typeof source !== "string") {
source = source.toString();
}
return svgToMiniDataURI(source);
}
const mimeType = mimeTypes.lookup(module.nameForCondition());
const encodedContent = source.toString("base64");
return `data:${mimeType};base64,${encodedContent}`;
}
}
}
]
},
experiments: {
asset: true
}
};

View File

@ -0,0 +1,9 @@
import png from "../_images/file.png?foo=bar";
import svg from "../_images/file.svg?";
import jpg from "../_images/file.jpg?foo=bar#hash";
it("should output various asset types", () => {
expect(png).toMatch(/^[\da-f]{20}\.png\?foo=bar$/);
expect(svg).toMatch(/^[\da-f]{20}\.svg\?$/);
expect(jpg).toMatch(/^[\da-f]{20}\.jpg\?foo=bar$/);
});

View File

@ -0,0 +1,14 @@
module.exports = {
mode: "development",
module: {
rules: [
{
test: /\.(png|svg|jpg)$/,
type: "asset/resource"
}
]
},
experiments: {
asset: true
}
};