diff --git a/declarations/plugins/SourceMapDevToolPlugin.d.ts b/declarations/plugins/SourceMapDevToolPlugin.d.ts index c9f8b431c05..e0104874453 100644 --- a/declarations/plugins/SourceMapDevToolPlugin.d.ts +++ b/declarations/plugins/SourceMapDevToolPlugin.d.ts @@ -17,7 +17,13 @@ export interface SourceMapDevToolPluginOptions { /** * Appends the given value to the original asset. Usually the #sourceMappingURL comment. [url] is replaced with a URL to the source map file. false disables the appending. */ - append?: (false | null) | string; + append?: + | (false | null) + | string + | (( + pathData: import("../../lib/Compilation").PathData, + assetInfo?: import("../../lib/Compilation").AssetInfo + ) => string); /** * Indicates whether column mappings should be used (defaults to true). */ diff --git a/lib/EvalSourceMapDevToolPlugin.js b/lib/EvalSourceMapDevToolPlugin.js index c03b09007b2..e4d85cbb131 100644 --- a/lib/EvalSourceMapDevToolPlugin.js +++ b/lib/EvalSourceMapDevToolPlugin.js @@ -48,7 +48,9 @@ class EvalSourceMapDevToolPlugin { options = inputOptions; } this.sourceMapComment = - options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; + options.append && typeof options.append !== "function" + ? options.append + : "//# sourceURL=[module]\n//# sourceMappingURL=[url]"; this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resource-path]?[hash]"; diff --git a/lib/SourceMapDevToolPlugin.js b/lib/SourceMapDevToolPlugin.js index 49ebabc9b30..1a0a581657e 100644 --- a/lib/SourceMapDevToolPlugin.js +++ b/lib/SourceMapDevToolPlugin.js @@ -23,6 +23,7 @@ const { makePathsAbsolute } = require("./util/identifier"); /** @typedef {import("./CacheFacade").ItemCacheFacade} ItemCacheFacade */ /** @typedef {import("./Chunk")} Chunk */ /** @typedef {import("./Compilation").AssetInfo} AssetInfo */ +/** @typedef {import("./Compilation").PathData} PathData */ /** @typedef {import("./Compiler")} Compiler */ /** @typedef {import("./Module")} Module */ /** @typedef {import("./NormalModule").SourceMap} SourceMap */ @@ -139,7 +140,7 @@ class SourceMapDevToolPlugin { /** @type {string | false} */ this.sourceMapFilename = options.filename; - /** @type {string | false} */ + /** @type {string | false | (function(PathData, AssetInfo=): string)}} */ this.sourceMappingURLComment = options.append === false ? false @@ -447,13 +448,14 @@ class SourceMapDevToolPlugin { ); } - /** @type {string | false} */ + /** @type {string | false | (function(PathData, AssetInfo=): string)} */ let currentSourceMappingURLComment = sourceMappingURLComment; let cssExtensionDetected = CSS_EXTENSION_DETECT_REGEXP.test(file); resetRegexpState(CSS_EXTENSION_DETECT_REGEXP); if ( currentSourceMappingURLComment !== false && + typeof currentSourceMappingURLComment !== "function" && cssExtensionDetected ) { currentSourceMappingURLComment = @@ -534,6 +536,11 @@ class SourceMapDevToolPlugin { "SourceMapDevToolPlugin: append can't be false when no filename is provided" ); } + if (typeof currentSourceMappingURLComment === "function") { + throw new Error( + "SourceMapDevToolPlugin: append can't be a function when no filename is provided" + ); + } /** * Add source map as data url to asset */ diff --git a/schemas/plugins/SourceMapDevToolPlugin.check.js b/schemas/plugins/SourceMapDevToolPlugin.check.js index f5b72577f8a..c821ebe496a 100644 --- a/schemas/plugins/SourceMapDevToolPlugin.check.js +++ b/schemas/plugins/SourceMapDevToolPlugin.check.js @@ -3,4 +3,4 @@ * DO NOT MODIFY BY HAND. * Run `yarn special-lint-fix` to update */ -const e=/^(?:[A-Za-z]:[\\/]|\\\\|\/)/;module.exports=l,module.exports.default=l;const n={definitions:{rule:{anyOf:[{instanceof:"RegExp"},{type:"string",minLength:1}]},rules:{anyOf:[{type:"array",items:{oneOf:[{$ref:"#/definitions/rule"}]}},{$ref:"#/definitions/rule"}]}},type:"object",additionalProperties:!1,properties:{append:{anyOf:[{enum:[!1,null]},{type:"string",minLength:1}]},columns:{type:"boolean"},exclude:{oneOf:[{$ref:"#/definitions/rules"}]},fallbackModuleFilenameTemplate:{anyOf:[{type:"string",minLength:1},{instanceof:"Function"}]},fileContext:{type:"string"},filename:{anyOf:[{enum:[!1,null]},{type:"string",absolutePath:!1,minLength:1}]},include:{oneOf:[{$ref:"#/definitions/rules"}]},module:{type:"boolean"},moduleFilenameTemplate:{anyOf:[{type:"string",minLength:1},{instanceof:"Function"}]},namespace:{type:"string"},noSources:{type:"boolean"},publicPath:{type:"string"},sourceRoot:{type:"string"},test:{$ref:"#/definitions/rules"}}},t=Object.prototype.hasOwnProperty;function s(e,{instancePath:n="",parentData:t,parentDataProperty:l,rootData:r=e}={}){let o=null,a=0;const i=a;let p=!1;const u=a;if(a===u)if(Array.isArray(e)){const n=e.length;for(let t=0;t string)" } ] }, diff --git a/test/configCases/plugins/source-map-dev-tool-plugin-append-function/index.js b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/index.js new file mode 100644 index 00000000000..464fe983765 --- /dev/null +++ b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/index.js @@ -0,0 +1,6 @@ +it("should have [file] replaced with chunk filename in append", function() { + const fs = require("fs"), + path = require("path"); + const source = fs.readFileSync(path.join(__dirname, "some-test.js"), "utf-8"); + expect(source).toMatch("//# sourceMappingURL=http://localhost:50505/some-test.js.map"); +}); diff --git a/test/configCases/plugins/source-map-dev-tool-plugin-append-function/test.js b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/test.js new file mode 100644 index 00000000000..a6b9cb13401 --- /dev/null +++ b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/test.js @@ -0,0 +1,5 @@ +const testObject = { + a: 1 +}; + +module.exports = testObject; diff --git a/test/configCases/plugins/source-map-dev-tool-plugin-append-function/webpack.config.js b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/webpack.config.js new file mode 100644 index 00000000000..052cc917dfe --- /dev/null +++ b/test/configCases/plugins/source-map-dev-tool-plugin-append-function/webpack.config.js @@ -0,0 +1,26 @@ +const webpack = require("../../../../"); +const TerserPlugin = require("terser-webpack-plugin"); + +/** @type {import("../../../../types").Configuration} */ +module.exports = { + node: { + __dirname: false, + __filename: false + }, + entry: { + bundle0: ["./index.js"], + "some-test": ["./test.js"] + }, + output: { + filename: "[name].js" + }, + optimization: { + minimizer: [new TerserPlugin()] + }, + plugins: [ + new webpack.SourceMapDevToolPlugin({ + filename: "sourcemaps/[file].map", + append: data => `\n//# sourceMappingURL=http://localhost:50505/[file].map` + }) + ] +}; diff --git a/types.d.ts b/types.d.ts index f4724c187a2..ae02564fb63 100644 --- a/types.d.ts +++ b/types.d.ts @@ -11648,7 +11648,10 @@ declare interface SourceMap { declare class SourceMapDevToolPlugin { constructor(options?: SourceMapDevToolPluginOptions); sourceMapFilename: string | false; - sourceMappingURLComment: string | false; + sourceMappingURLComment: + | string + | false + | ((arg0: PathData, arg1?: AssetInfo) => string); moduleFilenameTemplate: string | Function; fallbackModuleFilenameTemplate: string | Function; namespace: string; @@ -11663,7 +11666,11 @@ declare interface SourceMapDevToolPluginOptions { /** * Appends the given value to the original asset. Usually the #sourceMappingURL comment. [url] is replaced with a URL to the source map file. false disables the appending. */ - append?: null | string | false; + append?: + | null + | string + | false + | ((pathData: PathData, assetInfo?: AssetInfo) => string); /** * Indicates whether column mappings should be used (defaults to true).