Add 'outputPath' configuration option for resource asset modules
This commit is contained in:
parent
10b38b3726
commit
2fc4c8da1b
|
@ -692,6 +692,15 @@ export type AssetGeneratorDataUrlFunction = (
|
|||
*/
|
||||
export type AssetGeneratorOptions = AssetInlineGeneratorOptions &
|
||||
AssetResourceGeneratorOptions;
|
||||
/**
|
||||
* Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.
|
||||
*/
|
||||
export type AssetModuleOutputPath =
|
||||
| string
|
||||
| ((
|
||||
pathData: import("../lib/Compilation").PathData,
|
||||
assetInfo?: import("../lib/Compilation").AssetInfo
|
||||
) => string);
|
||||
/**
|
||||
* Function that executes for module and should return whenever asset should be inlined as DataUrl.
|
||||
*/
|
||||
|
@ -2705,6 +2714,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;
|
||||
/**
|
||||
* Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.
|
||||
*/
|
||||
outputPath?: AssetModuleOutputPath;
|
||||
/**
|
||||
* The 'publicPath' specifies the public URL address of the output files when referenced in a browser.
|
||||
*/
|
||||
|
|
|
@ -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").AssetModuleOutputPath} AssetModuleOutputPath */
|
||||
/** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
@ -117,13 +118,15 @@ class AssetGenerator extends Generator {
|
|||
* @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
|
||||
* @param {string=} filename override for output.assetModuleFilename
|
||||
* @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
|
||||
* @param {AssetModuleOutputPath=} outputPath the output path for the emitted file which is not included in the runtime import
|
||||
* @param {boolean=} emit generate output asset
|
||||
*/
|
||||
constructor(dataUrlOptions, filename, publicPath, emit) {
|
||||
constructor(dataUrlOptions, filename, publicPath, outputPath, emit) {
|
||||
super();
|
||||
this.dataUrlOptions = dataUrlOptions;
|
||||
this.filename = filename;
|
||||
this.publicPath = publicPath;
|
||||
this.outputPath = outputPath;
|
||||
this.emit = emit;
|
||||
}
|
||||
|
||||
|
@ -276,7 +279,23 @@ class AssetGenerator extends Generator {
|
|||
sourceFilename,
|
||||
...assetInfo
|
||||
};
|
||||
module.buildInfo.filename = filename;
|
||||
let outputFilename = filename;
|
||||
if (this.outputPath) {
|
||||
const { path: outputPath, info } =
|
||||
runtimeTemplate.compilation.getAssetPathWithInfo(
|
||||
this.outputPath,
|
||||
{
|
||||
module,
|
||||
runtime,
|
||||
filename: sourceFilename,
|
||||
chunkGraph,
|
||||
contentHash
|
||||
}
|
||||
);
|
||||
assetInfo = mergeAssetInfo(assetInfo, info);
|
||||
outputFilename = path.posix.join(outputPath, filename);
|
||||
}
|
||||
module.buildInfo.filename = outputFilename;
|
||||
module.buildInfo.assetInfo = assetInfo;
|
||||
if (getData) {
|
||||
// Due to code generation caching module.buildInfo.XXX can't used to store such information
|
||||
|
@ -284,7 +303,7 @@ class AssetGenerator extends Generator {
|
|||
// TODO webpack 6 For back-compat reasons we also store in on module.buildInfo
|
||||
const data = getData();
|
||||
data.set("fullContentHash", fullHash);
|
||||
data.set("filename", filename);
|
||||
data.set("filename", outputFilename);
|
||||
data.set("assetInfo", assetInfo);
|
||||
}
|
||||
|
||||
|
|
|
@ -137,9 +137,11 @@ class AssetModulesPlugin {
|
|||
|
||||
let filename = undefined;
|
||||
let publicPath = undefined;
|
||||
let outputPath = undefined;
|
||||
if (type !== "asset/inline") {
|
||||
filename = generatorOptions.filename;
|
||||
publicPath = generatorOptions.publicPath;
|
||||
outputPath = generatorOptions.outputPath;
|
||||
}
|
||||
|
||||
const AssetGenerator = getAssetGenerator();
|
||||
|
@ -148,6 +150,7 @@ class AssetModulesPlugin {
|
|||
dataUrl,
|
||||
filename,
|
||||
publicPath,
|
||||
outputPath,
|
||||
generatorOptions.emit !== false
|
||||
);
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -108,6 +108,9 @@
|
|||
"filename": {
|
||||
"$ref": "#/definitions/FilenameTemplate"
|
||||
},
|
||||
"outputPath": {
|
||||
"$ref": "#/definitions/AssetModuleOutputPath"
|
||||
},
|
||||
"publicPath": {
|
||||
"$ref": "#/definitions/RawPublicPath"
|
||||
}
|
||||
|
@ -136,6 +139,19 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"AssetModuleOutputPath": {
|
||||
"description": "Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"absolutePath": false
|
||||
},
|
||||
{
|
||||
"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",
|
||||
|
@ -182,6 +198,9 @@
|
|||
"filename": {
|
||||
"$ref": "#/definitions/FilenameTemplate"
|
||||
},
|
||||
"outputPath": {
|
||||
"$ref": "#/definitions/AssetModuleOutputPath"
|
||||
},
|
||||
"publicPath": {
|
||||
"$ref": "#/definitions/RawPublicPath"
|
||||
}
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
* DO NOT MODIFY BY HAND.
|
||||
* Run `yarn special-lint-fix` to update
|
||||
*/
|
||||
const t=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function n(t,{instancePath:r="",parentData:e,parentDataProperty:a,rootData:s=t}={}){let o=null,l=0;const i=l;let p=!1;const c=l;if(l==l)if(t&&"object"==typeof t&&!Array.isArray(t)){const n=l;for(const n in t)if("encoding"!==n&&"mimetype"!==n){const t={params:{additionalProperty:n}};null===o?o=[t]:o.push(t),l++;break}if(n===l){if(void 0!==t.encoding){let n=t.encoding;const r=l;if(!1!==n&&"base64"!==n){const t={params:{}};null===o?o=[t]:o.push(t),l++}var u=r===l}else u=!0;if(u)if(void 0!==t.mimetype){const n=l;if("string"!=typeof t.mimetype){const t={params:{type:"string"}};null===o?o=[t]:o.push(t),l++}u=n===l}else u=!0}}else{const t={params:{type:"object"}};null===o?o=[t]:o.push(t),l++}var f=c===l;if(p=p||f,!p){const n=l;if(!(t instanceof Function)){const t={params:{}};null===o?o=[t]:o.push(t),l++}f=n===l,p=p||f}if(!p){const t={params:{}};return null===o?o=[t]:o.push(t),l++,n.errors=o,!1}return l=i,null!==o&&(i?o.length=i:o=null),n.errors=o,0===l}function r(e,{instancePath:a="",parentData:s,parentDataProperty:o,rootData:l=e}={}){let i=null,p=0;if(0===p){if(!e||"object"!=typeof e||Array.isArray(e))return r.errors=[{params:{type:"object"}}],!1;{const s=p;for(const t in e)if("dataUrl"!==t&&"emit"!==t&&"filename"!==t&&"publicPath"!==t)return r.errors=[{params:{additionalProperty:t}}],!1;if(s===p){if(void 0!==e.dataUrl){const t=p;n(e.dataUrl,{instancePath:a+"/dataUrl",parentData:e,parentDataProperty:"dataUrl",rootData:l})||(i=null===i?n.errors:i.concat(n.errors),p=i.length);var c=t===p}else c=!0;if(c){if(void 0!==e.emit){const t=p;if("boolean"!=typeof e.emit)return r.errors=[{params:{type:"boolean"}}],!1;c=t===p}else c=!0;if(c){if(void 0!==e.filename){let n=e.filename;const a=p,s=p;let o=!1;const l=p;if(p===l)if("string"==typeof n){if(n.includes("!")||!1!==t.test(n)){const t={params:{}};null===i?i=[t]:i.push(t),p++}else if(n.length<1){const t={params:{}};null===i?i=[t]:i.push(t),p++}}else{const t={params:{type:"string"}};null===i?i=[t]:i.push(t),p++}var u=l===p;if(o=o||u,!o){const t=p;if(!(n instanceof Function)){const t={params:{}};null===i?i=[t]:i.push(t),p++}u=t===p,o=o||u}if(!o){const t={params:{}};return null===i?i=[t]:i.push(t),p++,r.errors=i,!1}p=s,null!==i&&(s?i.length=s:i=null),c=a===p}else c=!0;if(c)if(void 0!==e.publicPath){let t=e.publicPath;const n=p,a=p;let s=!1;const o=p;if("string"!=typeof t){const t={params:{type:"string"}};null===i?i=[t]:i.push(t),p++}var f=o===p;if(s=s||f,!s){const n=p;if(!(t instanceof Function)){const t={params:{}};null===i?i=[t]:i.push(t),p++}f=n===p,s=s||f}if(!s){const t={params:{}};return null===i?i=[t]:i.push(t),p++,r.errors=i,!1}p=a,null!==i&&(a?i.length=a:i=null),c=n===p}else c=!0}}}}}return r.errors=i,0===p}function e(t,{instancePath:n="",parentData:a,parentDataProperty:s,rootData:o=t}={}){let l=null,i=0;return r(t,{instancePath:n,parentData:a,parentDataProperty:s,rootData:o})||(l=null===l?r.errors:l.concat(r.errors),i=l.length),e.errors=l,0===i}module.exports=e,module.exports.default=e;
|
||||
const t=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function n(t,{instancePath:r="",parentData:e,parentDataProperty:a,rootData:s=t}={}){let o=null,l=0;const i=l;let p=!1;const u=l;if(l==l)if(t&&"object"==typeof t&&!Array.isArray(t)){const n=l;for(const n in t)if("encoding"!==n&&"mimetype"!==n){const t={params:{additionalProperty:n}};null===o?o=[t]:o.push(t),l++;break}if(n===l){if(void 0!==t.encoding){let n=t.encoding;const r=l;if(!1!==n&&"base64"!==n){const t={params:{}};null===o?o=[t]:o.push(t),l++}var c=r===l}else c=!0;if(c)if(void 0!==t.mimetype){const n=l;if("string"!=typeof t.mimetype){const t={params:{type:"string"}};null===o?o=[t]:o.push(t),l++}c=n===l}else c=!0}}else{const t={params:{type:"object"}};null===o?o=[t]:o.push(t),l++}var f=u===l;if(p=p||f,!p){const n=l;if(!(t instanceof Function)){const t={params:{}};null===o?o=[t]:o.push(t),l++}f=n===l,p=p||f}if(!p){const t={params:{}};return null===o?o=[t]:o.push(t),l++,n.errors=o,!1}return l=i,null!==o&&(i?o.length=i:o=null),n.errors=o,0===l}function r(e,{instancePath:a="",parentData:s,parentDataProperty:o,rootData:l=e}={}){let i=null,p=0;if(0===p){if(!e||"object"!=typeof e||Array.isArray(e))return r.errors=[{params:{type:"object"}}],!1;{const s=p;for(const t in e)if("dataUrl"!==t&&"emit"!==t&&"filename"!==t&&"outputPath"!==t&&"publicPath"!==t)return r.errors=[{params:{additionalProperty:t}}],!1;if(s===p){if(void 0!==e.dataUrl){const t=p;n(e.dataUrl,{instancePath:a+"/dataUrl",parentData:e,parentDataProperty:"dataUrl",rootData:l})||(i=null===i?n.errors:i.concat(n.errors),p=i.length);var u=t===p}else u=!0;if(u){if(void 0!==e.emit){const t=p;if("boolean"!=typeof e.emit)return r.errors=[{params:{type:"boolean"}}],!1;u=t===p}else u=!0;if(u){if(void 0!==e.filename){let n=e.filename;const a=p,s=p;let o=!1;const l=p;if(p===l)if("string"==typeof n){if(n.includes("!")||!1!==t.test(n)){const t={params:{}};null===i?i=[t]:i.push(t),p++}else if(n.length<1){const t={params:{}};null===i?i=[t]:i.push(t),p++}}else{const t={params:{type:"string"}};null===i?i=[t]:i.push(t),p++}var c=l===p;if(o=o||c,!o){const t=p;if(!(n instanceof Function)){const t={params:{}};null===i?i=[t]:i.push(t),p++}c=t===p,o=o||c}if(!o){const t={params:{}};return null===i?i=[t]:i.push(t),p++,r.errors=i,!1}p=s,null!==i&&(s?i.length=s:i=null),u=a===p}else u=!0;if(u){if(void 0!==e.outputPath){let n=e.outputPath;const a=p,s=p;let o=!1;const l=p;if(p===l)if("string"==typeof n){if(n.includes("!")||!1!==t.test(n)){const t={params:{}};null===i?i=[t]:i.push(t),p++}}else{const t={params:{type:"string"}};null===i?i=[t]:i.push(t),p++}var f=l===p;if(o=o||f,!o){const t=p;if(!(n instanceof Function)){const t={params:{}};null===i?i=[t]:i.push(t),p++}f=t===p,o=o||f}if(!o){const t={params:{}};return null===i?i=[t]:i.push(t),p++,r.errors=i,!1}p=s,null!==i&&(s?i.length=s:i=null),u=a===p}else u=!0;if(u)if(void 0!==e.publicPath){let t=e.publicPath;const n=p,a=p;let s=!1;const o=p;if("string"!=typeof t){const t={params:{type:"string"}};null===i?i=[t]:i.push(t),p++}var h=o===p;if(s=s||h,!s){const n=p;if(!(t instanceof Function)){const t={params:{}};null===i?i=[t]:i.push(t),p++}h=n===p,s=s||h}if(!s){const t={params:{}};return null===i?i=[t]:i.push(t),p++,r.errors=i,!1}p=a,null!==i&&(a?i.length=a:i=null),u=n===p}else u=!0}}}}}}return r.errors=i,0===p}function e(t,{instancePath:n="",parentData:a,parentDataProperty:s,rootData:o=t}={}){let l=null,i=0;return r(t,{instancePath:n,parentData:a,parentDataProperty:s,rootData:o})||(l=null===l?r.errors:l.concat(r.errors),i=l.length),e.errors=l,0===i}module.exports=e,module.exports.default=e;
|
|
@ -3,4 +3,4 @@
|
|||
* DO NOT MODIFY BY HAND.
|
||||
* Run `yarn special-lint-fix` to update
|
||||
*/
|
||||
const t=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function r(n,{instancePath:e="",parentData:a,parentDataProperty:s,rootData:o=n}={}){let l=null,i=0;if(0===i){if(!n||"object"!=typeof n||Array.isArray(n))return r.errors=[{params:{type:"object"}}],!1;{const e=i;for(const t in n)if("emit"!==t&&"filename"!==t&&"publicPath"!==t)return r.errors=[{params:{additionalProperty:t}}],!1;if(e===i){if(void 0!==n.emit){const t=i;if("boolean"!=typeof n.emit)return r.errors=[{params:{type:"boolean"}}],!1;var p=t===i}else p=!0;if(p){if(void 0!==n.filename){let e=n.filename;const a=i,s=i;let o=!1;const c=i;if(i===c)if("string"==typeof e){if(e.includes("!")||!1!==t.test(e)){const t={params:{}};null===l?l=[t]:l.push(t),i++}else if(e.length<1){const t={params:{}};null===l?l=[t]:l.push(t),i++}}else{const t={params:{type:"string"}};null===l?l=[t]:l.push(t),i++}var u=c===i;if(o=o||u,!o){const t=i;if(!(e instanceof Function)){const t={params:{}};null===l?l=[t]:l.push(t),i++}u=t===i,o=o||u}if(!o){const t={params:{}};return null===l?l=[t]:l.push(t),i++,r.errors=l,!1}i=s,null!==l&&(s?l.length=s:l=null),p=a===i}else p=!0;if(p)if(void 0!==n.publicPath){let t=n.publicPath;const e=i,a=i;let s=!1;const o=i;if("string"!=typeof t){const t={params:{type:"string"}};null===l?l=[t]:l.push(t),i++}var c=o===i;if(s=s||c,!s){const r=i;if(!(t instanceof Function)){const t={params:{}};null===l?l=[t]:l.push(t),i++}c=r===i,s=s||c}if(!s){const t={params:{}};return null===l?l=[t]:l.push(t),i++,r.errors=l,!1}i=a,null!==l&&(a?l.length=a:l=null),p=e===i}else p=!0}}}}return r.errors=l,0===i}function n(t,{instancePath:e="",parentData:a,parentDataProperty:s,rootData:o=t}={}){let l=null,i=0;return r(t,{instancePath:e,parentData:a,parentDataProperty:s,rootData:o})||(l=null===l?r.errors:l.concat(r.errors),i=l.length),n.errors=l,0===i}module.exports=n,module.exports.default=n;
|
||||
const t=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;function n(r,{instancePath:e="",parentData:s,parentDataProperty:a,rootData:o=r}={}){let l=null,i=0;if(0===i){if(!r||"object"!=typeof r||Array.isArray(r))return n.errors=[{params:{type:"object"}}],!1;{const e=i;for(const t in r)if("emit"!==t&&"filename"!==t&&"outputPath"!==t&&"publicPath"!==t)return n.errors=[{params:{additionalProperty:t}}],!1;if(e===i){if(void 0!==r.emit){const t=i;if("boolean"!=typeof r.emit)return n.errors=[{params:{type:"boolean"}}],!1;var u=t===i}else u=!0;if(u){if(void 0!==r.filename){let e=r.filename;const s=i,a=i;let o=!1;const c=i;if(i===c)if("string"==typeof e){if(e.includes("!")||!1!==t.test(e)){const t={params:{}};null===l?l=[t]:l.push(t),i++}else if(e.length<1){const t={params:{}};null===l?l=[t]:l.push(t),i++}}else{const t={params:{type:"string"}};null===l?l=[t]:l.push(t),i++}var p=c===i;if(o=o||p,!o){const t=i;if(!(e instanceof Function)){const t={params:{}};null===l?l=[t]:l.push(t),i++}p=t===i,o=o||p}if(!o){const t={params:{}};return null===l?l=[t]:l.push(t),i++,n.errors=l,!1}i=a,null!==l&&(a?l.length=a:l=null),u=s===i}else u=!0;if(u){if(void 0!==r.outputPath){let e=r.outputPath;const s=i,a=i;let o=!1;const p=i;if(i===p)if("string"==typeof e){if(e.includes("!")||!1!==t.test(e)){const t={params:{}};null===l?l=[t]:l.push(t),i++}}else{const t={params:{type:"string"}};null===l?l=[t]:l.push(t),i++}var c=p===i;if(o=o||c,!o){const t=i;if(!(e instanceof Function)){const t={params:{}};null===l?l=[t]:l.push(t),i++}c=t===i,o=o||c}if(!o){const t={params:{}};return null===l?l=[t]:l.push(t),i++,n.errors=l,!1}i=a,null!==l&&(a?l.length=a:l=null),u=s===i}else u=!0;if(u)if(void 0!==r.publicPath){let t=r.publicPath;const e=i,s=i;let a=!1;const o=i;if("string"!=typeof t){const t={params:{type:"string"}};null===l?l=[t]:l.push(t),i++}var f=o===i;if(a=a||f,!a){const n=i;if(!(t instanceof Function)){const t={params:{}};null===l?l=[t]:l.push(t),i++}f=n===i,a=a||f}if(!a){const t={params:{}};return null===l?l=[t]:l.push(t),i++,n.errors=l,!1}i=s,null!==l&&(s?l.length=s:l=null),u=e===i}else u=!0}}}}}return n.errors=l,0===i}function r(t,{instancePath:e="",parentData:s,parentDataProperty:a,rootData:o=t}={}){let l=null,i=0;return n(t,{instancePath:e,parentData:s,parentDataProperty:a,rootData:o})||(l=null===l?n.errors:l.concat(n.errors),i=l.length),r.errors=l,0===i}module.exports=r,module.exports.default=r;
|
|
@ -1283,6 +1283,19 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"module-generator-asset-output-path": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.",
|
||||
"multiple": false,
|
||||
"path": "module.generator.asset.outputPath",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"description": "Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.",
|
||||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"module-generator-asset-public-path": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
@ -1322,6 +1335,19 @@ Object {
|
|||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"module-generator-asset-resource-output-path": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
"description": "Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.",
|
||||
"multiple": false,
|
||||
"path": "module.generator.asset/resource.outputPath",
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
"description": "Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.",
|
||||
"multiple": false,
|
||||
"simpleType": "string",
|
||||
},
|
||||
"module-generator-asset-resource-public-path": Object {
|
||||
"configs": Array [
|
||||
Object {
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import url from "../_images/file.png";
|
||||
import url2 from "../_images/file.jpg";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
it("should output asset with path", () => {
|
||||
expect(url).toEqual("images/file.png");
|
||||
expect(() => fs.statSync(url)).toThrowError(
|
||||
expect.objectContaining({
|
||||
code: "ENOENT"
|
||||
})
|
||||
);
|
||||
expect(url2).toEqual("images/file.jpg");
|
||||
|
||||
expect(fs.existsSync(path.join(__STATS__.outputPath, url))).toBe(false);
|
||||
expect(fs.existsSync(path.join(__STATS__.outputPath, url2))).toBe(true);
|
||||
});
|
||||
|
|
|
@ -8,10 +8,14 @@ module.exports = {
|
|||
rules: [
|
||||
{
|
||||
test: /\.png$/,
|
||||
type: "asset",
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
emit: false
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.jpg$/,
|
||||
type: "asset/resource"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import url from "../_images/file.png";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
it("should emit asset with module.generator.asset.outputPath", () => {
|
||||
expect(url).toEqual("https://cdn/assets/file.png");
|
||||
|
||||
const emitPath = path.join(__STATS__.outputPath, "cdn-assets/file.png")
|
||||
expect(fs.existsSync(emitPath)).toBe(true);
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
/** @type {import("../../../../").Configuration} */
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
output: {
|
||||
assetModuleFilename: "file[ext]"
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.png$/,
|
||||
type: "asset/resource",
|
||||
generator: {
|
||||
publicPath: "https://cdn/assets/",
|
||||
outputPath: "cdn-assets/"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
|
@ -321,6 +321,11 @@ declare interface AssetResourceGeneratorOptions {
|
|||
*/
|
||||
filename?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
|
||||
|
||||
/**
|
||||
* Emit the asset in the specified folder instead relative to 'output.path'. This should only be needed when custom 'publicPath' is specified to match the folder structure there.
|
||||
*/
|
||||
outputPath?: string | ((pathData: PathData, assetInfo?: AssetInfo) => string);
|
||||
|
||||
/**
|
||||
* The 'publicPath' specifies the public URL address of the output files when referenced in a browser.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue