feat: support assetModulePublicPath

This commit is contained in:
xiaoxiaojx 2021-03-16 02:03:19 +08:00
parent 1def19ea8a
commit 55fd79ee6a
15 changed files with 208 additions and 7 deletions

View File

@ -417,6 +417,15 @@ export type AssetModuleFilename =
pathData: import("../lib/Compilation").PathData,
assetInfo?: import("../lib/Compilation").AssetInfo
) => string);
/**
* The publicPath of asset modules.
*/
export type AssetModulePublicPath =
| string
| ((
pathData: import("../lib/Compilation").PathData,
assetInfo?: import("../lib/Compilation").AssetInfo
) => string);
/**
* Add charset attribute for script tag.
*/
@ -1874,6 +1883,10 @@ export interface Output {
* The filename of asset modules as relative path inside the 'output.path' directory.
*/
assetModuleFilename?: AssetModuleFilename;
/**
* The publicPath of asset modules.
*/
assetModulePublicPath?: AssetModulePublicPath;
/**
* Add a comment in the UMD wrapper.
*/
@ -2592,6 +2605,10 @@ export interface AssetResourceGeneratorOptions {
* Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
filename?: FilenameTemplate;
/**
* The publicPath of asset modules.
*/
publicPath?: AssetModulePublicPath;
}
/**
* No generator options are supported for this module type.
@ -2827,6 +2844,10 @@ export interface OutputNormalized {
* The filename of asset modules as relative path inside the 'output.path' directory.
*/
assetModuleFilename?: AssetModuleFilename;
/**
* The publicPath of asset modules.
*/
assetModulePublicPath?: AssetModulePublicPath;
/**
* Add charset attribute for script tag.
*/

View File

@ -15,6 +15,7 @@ const { makePathsRelative } = require("../util/identifier");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
/** @typedef {import("../../declarations/WebpackOptions").AssetModulePublicPath} AssetModulePublicPath */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
@ -31,12 +32,14 @@ class AssetGenerator extends Generator {
/**
* @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
* @param {string=} filename override for output.assetModuleFilename
* @param {AssetModulePublicPath=} publicPath override for output.assetModulePublicPath
* @param {boolean=} emit generate output asset
*/
constructor(dataUrlOptions, filename, emit) {
constructor(dataUrlOptions, filename, publicPath, emit) {
super();
this.dataUrlOptions = dataUrlOptions;
this.filename = filename;
this.publicPath = publicPath;
this.emit = emit;
}
@ -113,6 +116,10 @@ class AssetGenerator extends Generator {
} else {
const assetModuleFilename =
this.filename || runtimeTemplate.outputOptions.assetModuleFilename;
let assetModulePublicPath =
this.publicPath ||
runtimeTemplate.outputOptions.assetModulePublicPath;
let publicPath;
const hash = createHash(runtimeTemplate.outputOptions.hashFunction);
if (runtimeTemplate.outputOptions.hashSalt) {
hash.update(runtimeTemplate.outputOptions.hashSalt);
@ -144,6 +151,23 @@ class AssetGenerator extends Generator {
contentHash
}
);
if (assetModulePublicPath) {
publicPath = JSON.stringify(
runtimeTemplate.compilation.getAssetPathWithInfo(
assetModulePublicPath,
{
module,
runtime,
filename: sourceFilename,
chunkGraph,
contentHash
}
).path
);
} else {
publicPath = RuntimeGlobals.publicPath;
runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
}
module.buildInfo.filename = filename;
module.buildInfo.assetInfo = {
sourceFilename,
@ -159,12 +183,10 @@ class AssetGenerator extends Generator {
data.set("assetInfo", info);
}
runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
return new RawSource(
`${RuntimeGlobals.module}.exports = ${
RuntimeGlobals.publicPath
} + ${JSON.stringify(filename)};`
`${
RuntimeGlobals.module
}.exports = ${publicPath} + ${JSON.stringify(filename)};`
);
}
}

View File

@ -118,8 +118,10 @@ class AssetModulesPlugin {
}
let filename = undefined;
let publicPath = undefined;
if (type !== "asset/inline") {
filename = generatorOptions.filename;
publicPath = generatorOptions.publicPath;
}
const AssetGenerator = getAssetGenerator();
@ -127,6 +129,7 @@ class AssetModulesPlugin {
return new AssetGenerator(
dataUrl,
filename,
publicPath,
generatorOptions.emit !== false
);
});

View File

@ -271,6 +271,7 @@ const getNormalizedWebpackOptions = config => {
/** @type {OutputNormalized} */
const result = {
assetModuleFilename: output.assetModuleFilename,
assetModulePublicPath: output.assetModulePublicPath,
charset: output.charset,
chunkFilename: output.chunkFilename,
chunkFormat: output.chunkFormat,

View File

@ -107,6 +107,9 @@
},
"filename": {
"$ref": "#/definitions/FilenameTemplate"
},
"publicPath": {
"$ref": "#/definitions/AssetModulePublicPath"
}
}
},
@ -133,6 +136,18 @@
}
]
},
"AssetModulePublicPath": {
"description": "The publicPath of asset modules.",
"anyOf": [
{
"type": "string"
},
{
"instanceof": "Function",
"tsType": "((pathData: import(\"../lib/Compilation\").PathData, assetInfo?: import(\"../lib/Compilation\").AssetInfo) => string)"
}
]
},
"AssetParserDataUrlFunction": {
"description": "Function that executes for module and should return whenever asset should be inlined as DataUrl.",
"instanceof": "Function",
@ -178,6 +193,9 @@
},
"filename": {
"$ref": "#/definitions/FilenameTemplate"
},
"publicPath": {
"$ref": "#/definitions/AssetModulePublicPath"
}
}
},
@ -2487,6 +2505,9 @@
"assetModuleFilename": {
"$ref": "#/definitions/AssetModuleFilename"
},
"assetModulePublicPath": {
"$ref": "#/definitions/AssetModulePublicPath"
},
"auxiliaryComment": {
"cli": {
"exclude": true
@ -2670,6 +2691,9 @@
"assetModuleFilename": {
"$ref": "#/definitions/AssetModuleFilename"
},
"assetModulePublicPath": {
"$ref": "#/definitions/AssetModulePublicPath"
},
"charset": {
"$ref": "#/definitions/Charset"
},

View File

@ -282,6 +282,7 @@ describe("Defaults", () => {
},
"output": Object {
"assetModuleFilename": "[hash][ext][query]",
"assetModulePublicPath": undefined,
"charset": true,
"chunkFilename": "[name].js",
"chunkFormat": "array-push",

View File

@ -496,7 +496,7 @@ describe("Validation", () => {
expect(msg).toMatchInlineSnapshot(`
"Invalid configuration object. Webpack has been initialized using a configuration object that does not match the API schema.
- configuration.output has an unknown property 'ecmaVersion'. These properties are valid:
object { assetModuleFilename?, auxiliaryComment?, charset?, chunkFilename?, chunkFormat?, chunkLoadTimeout?, chunkLoading?, chunkLoadingGlobal?, clean?, compareBeforeEmit?, crossOriginLoading?, devtoolFallbackModuleFilenameTemplate?, devtoolModuleFilenameTemplate?, devtoolNamespace?, enabledChunkLoadingTypes?, enabledLibraryTypes?, enabledWasmLoadingTypes?, environment?, filename?, globalObject?, hashDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateGlobal?, hotUpdateMainFilename?, iife?, importFunctionName?, importMetaName?, library?, libraryExport?, libraryTarget?, module?, path?, pathinfo?, publicPath?, scriptType?, sourceMapFilename?, sourcePrefix?, strictModuleErrorHandling?, strictModuleExceptionHandling?, umdNamedDefine?, uniqueName?, wasmLoading?, webassemblyModuleFilename?, workerChunkLoading?, workerWasmLoading? }
object { assetModuleFilename?, assetModulePublicPath?, auxiliaryComment?, charset?, chunkFilename?, chunkFormat?, chunkLoadTimeout?, chunkLoading?, chunkLoadingGlobal?, clean?, compareBeforeEmit?, crossOriginLoading?, devtoolFallbackModuleFilenameTemplate?, devtoolModuleFilenameTemplate?, devtoolNamespace?, enabledChunkLoadingTypes?, enabledLibraryTypes?, enabledWasmLoadingTypes?, environment?, filename?, globalObject?, hashDigest?, hashDigestLength?, hashFunction?, hashSalt?, hotUpdateChunkFilename?, hotUpdateGlobal?, hotUpdateMainFilename?, iife?, importFunctionName?, importMetaName?, library?, libraryExport?, libraryTarget?, module?, path?, pathinfo?, publicPath?, scriptType?, sourceMapFilename?, sourcePrefix?, strictModuleErrorHandling?, strictModuleExceptionHandling?, umdNamedDefine?, uniqueName?, wasmLoading?, webassemblyModuleFilename?, workerChunkLoading?, workerWasmLoading? }
-> Options affecting the output of the compilation. \`output\` options tell webpack how to write the compiled files to disk.
Did you mean output.environment (output.ecmaVersion was a temporary configuration option during webpack 5 beta)?"
`)

View File

@ -933,6 +933,19 @@ Object {
"multiple": false,
"simpleType": "string",
},
"module-generator-asset-public-path": Object {
"configs": Array [
Object {
"description": "The publicPath of asset modules.",
"multiple": false,
"path": "module.generator.asset.publicPath",
"type": "string",
},
],
"description": "The publicPath of asset modules.",
"multiple": false,
"simpleType": "string",
},
"module-generator-asset-resource-emit": Object {
"configs": Array [
Object {
@ -959,6 +972,19 @@ Object {
"multiple": false,
"simpleType": "string",
},
"module-generator-asset-resource-public-path": Object {
"configs": Array [
Object {
"description": "The publicPath of asset modules.",
"multiple": false,
"path": "module.generator.asset/resource.publicPath",
"type": "string",
},
],
"description": "The publicPath of asset modules.",
"multiple": false,
"simpleType": "string",
},
"module-no-parse": Object {
"configs": Array [
Object {
@ -4039,6 +4065,19 @@ Object {
"multiple": false,
"simpleType": "string",
},
"output-asset-module-public-path": Object {
"configs": Array [
Object {
"description": "The publicPath of asset modules.",
"multiple": false,
"path": "output.assetModulePublicPath",
"type": "string",
},
],
"description": "The publicPath of asset modules.",
"multiple": false,
"simpleType": "string",
},
"output-charset": Object {
"configs": Array [
Object {

View File

@ -0,0 +1,5 @@
import url from "../_images/file.png";
it("should import asset with output.assetModulePublicPath", () => {
expect(url).toEqual("/assets/file.png");
});

View File

@ -0,0 +1,16 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
output: {
assetModulePublicPath: "/assets/",
assetModuleFilename: "file[ext]"
},
module: {
rules: [
{
test: /\.png$/,
type: "asset"
}
]
}
};

View File

@ -0,0 +1,5 @@
import url from "../_images/file.png";
it("should import asset with module.generator.asset.publicPath", () => {
expect(url).toEqual("assets/file.png");
});

View File

@ -0,0 +1,20 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
output: {
assetModuleFilename: "file[ext]"
},
module: {
rules: [
{
test: /\.png$/,
type: "asset"
}
],
generator: {
asset: {
publicPath: "assets/"
}
}
}
};

View File

@ -0,0 +1,5 @@
import url from "../_images/file.png";
it("should import asset with rule.generator.publicPath", () => {
expect(url).toEqual("assets/file.png");
});

View File

@ -0,0 +1,20 @@
/** @type {import("../../../../").Configuration} */
module.exports = {
mode: "development",
output: {
assetModuleFilename: "file[ext]"
},
module: {
rules: [
{
test: /\.png$/,
type: "asset",
generator: {
publicPath: () => {
return "assets/";
}
}
}
]
}
};

19
types.d.ts vendored
View File

@ -308,6 +308,11 @@ declare interface AssetResourceGeneratorOptions {
* Specifies the filename template of output files on disk. You must **not** specify an absolute path here, but the path may contain folders separated by '/'! The specified path is joined with the value of the 'output.path' option to determine the location on disk.
*/
filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* The publicPath of asset modules.
*/
publicPath?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
}
declare abstract class AsyncDependenciesBlock extends DependenciesBlock {
groupOptions: RawChunkGroupOptions & { name?: string } & {
@ -7205,6 +7210,13 @@ declare interface Output {
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* The publicPath of asset modules.
*/
assetModulePublicPath?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* Add a comment in the UMD wrapper.
*/
@ -7482,6 +7494,13 @@ declare interface OutputNormalized {
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* The publicPath of asset modules.
*/
assetModulePublicPath?:
| string
| ((pathData: PathData, assetInfo?: AssetInfo) => string);
/**
* Add charset attribute for script tag.
*/