mirror of https://github.com/webpack/webpack.git
adding `output.devtoolNamespace` option
When loading multiple libraries built with webpack, you can run into collisions of the sourcemap file paths. For examle, both have "webpack:///src/index.js". This change addresses the problem by introducing a new output option `output.devtoolNamespace` which defaults to `output.library` when not specified. The defaults moduleFilenameTemplates in all the sourcemap plugins have been modified to start with: "webpack://[namespace]/...", where [namespace] will be replaced by the `output.devtoolNamespace`. Notice that there are only two slashes following "webpack:" now. This is to make it behave just as before when not building with a namespace. When building with a namespace you only get the two slashes, but from what I've seen the chrome dev tools only care about the first 2 slashes anyways. Discussed with sokra here: https://github.com/webpack/webpack/issues/5767
This commit is contained in:
parent
168f92330e
commit
f925032d5a
|
@ -10,7 +10,7 @@ const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
|||
class EvalDevToolModuleTemplatePlugin {
|
||||
constructor(sourceUrlComment, moduleFilenameTemplate) {
|
||||
this.sourceUrlComment = sourceUrlComment || "\n//# sourceURL=[url]";
|
||||
this.moduleFilenameTemplate = moduleFilenameTemplate || "webpack:///[resourcePath]?[loaders]";
|
||||
this.moduleFilenameTemplate = moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]?[loaders]";
|
||||
}
|
||||
|
||||
apply(moduleTemplate) {
|
||||
|
|
|
@ -11,7 +11,7 @@ class EvalSourceMapDevToolModuleTemplatePlugin {
|
|||
constructor(compilation, options) {
|
||||
this.compilation = compilation;
|
||||
this.sourceMapComment = options.append || "//# sourceURL=[module]\n//# sourceMappingURL=[url]";
|
||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack:///[resource-path]?[hash]";
|
||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resource-path]?[hash]";
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ ModuleFilenameHelpers.ID = "[id]";
|
|||
ModuleFilenameHelpers.REGEXP_ID = /\[id\]/gi;
|
||||
ModuleFilenameHelpers.HASH = "[hash]";
|
||||
ModuleFilenameHelpers.REGEXP_HASH = /\[hash\]/gi;
|
||||
ModuleFilenameHelpers.NAMESPACE = "[namespace]";
|
||||
ModuleFilenameHelpers.REGEXP_NAMESPACE = /\[namespace\]/gi;
|
||||
|
||||
function getAfter(str, token) {
|
||||
const idx = str.indexOf(token);
|
||||
|
@ -73,6 +75,7 @@ ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFil
|
|||
const allLoaders = getBefore(identifier, "!");
|
||||
const query = getAfter(resource, "?");
|
||||
const resourcePath = resource.substr(0, resource.length - query.length);
|
||||
const namespace = this._moduleNamespace || "";
|
||||
if(typeof moduleFilenameTemplate === "function") {
|
||||
return moduleFilenameTemplate({
|
||||
identifier: identifier,
|
||||
|
@ -83,7 +86,8 @@ ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFil
|
|||
allLoaders: allLoaders,
|
||||
query: query,
|
||||
moduleId: moduleId,
|
||||
hash: hash
|
||||
hash: hash,
|
||||
namespace: namespace
|
||||
});
|
||||
}
|
||||
return moduleFilenameTemplate
|
||||
|
@ -96,7 +100,8 @@ ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFil
|
|||
.replace(ModuleFilenameHelpers.REGEXP_LOADERS, loaders)
|
||||
.replace(ModuleFilenameHelpers.REGEXP_QUERY, query)
|
||||
.replace(ModuleFilenameHelpers.REGEXP_ID, moduleId)
|
||||
.replace(ModuleFilenameHelpers.REGEXP_HASH, hash);
|
||||
.replace(ModuleFilenameHelpers.REGEXP_HASH, hash)
|
||||
.replace(ModuleFilenameHelpers.REGEXP_NAMESPACE, namespace);
|
||||
};
|
||||
|
||||
ModuleFilenameHelpers.createFooter = function createFooter(module, requestShortener) {
|
||||
|
@ -160,3 +165,7 @@ ModuleFilenameHelpers.matchObject = function matchObject(obj, str) {
|
|||
if(ModuleFilenameHelpers.matchPart(str, obj.exclude)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
ModuleFilenameHelpers.setModuleNamespace = function setModuleNamespace(moduleNamespace) {
|
||||
this._moduleNamespace = moduleNamespace;
|
||||
};
|
||||
|
|
|
@ -62,8 +62,8 @@ class SourceMapDevToolPlugin {
|
|||
if(!options) options = {};
|
||||
this.sourceMapFilename = options.filename;
|
||||
this.sourceMappingURLComment = options.append === false ? false : options.append || "\n//# sourceMappingURL=[url]";
|
||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack:///[resourcePath]";
|
||||
this.fallbackModuleFilenameTemplate = options.fallbackModuleFilenameTemplate || "webpack:///[resourcePath]?[hash]";
|
||||
this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack://[namespace]/[resourcePath]";
|
||||
this.fallbackModuleFilenameTemplate = options.fallbackModuleFilenameTemplate || "webpack://[namespace]/[resourcePath]?[hash]";
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");
|
|||
const SizeLimitsPlugin = require("./performance/SizeLimitsPlugin");
|
||||
|
||||
const ResolverFactory = require("enhanced-resolve").ResolverFactory;
|
||||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
|
||||
|
||||
class WebpackOptionsApply extends OptionsApply {
|
||||
constructor() {
|
||||
|
@ -193,6 +194,12 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
ExternalsPlugin = require("./ExternalsPlugin");
|
||||
compiler.apply(new ExternalsPlugin(options.output.libraryTarget, options.externals));
|
||||
}
|
||||
|
||||
if(!options.output.devtoolNamespace) {
|
||||
options.output.devtoolNamespace = options.output.library;
|
||||
}
|
||||
ModuleFilenameHelpers.setModuleNamespace(options.output.devtoolNamespace);
|
||||
|
||||
let noSources;
|
||||
let legacy;
|
||||
let modern;
|
||||
|
|
|
@ -326,6 +326,10 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"devtoolNamespace": {
|
||||
"description": "Module namespace to use when interpolating filename template string for the sources array in a generated SourceMap. Defaults to `output.library` if not set. It's useful for avoiding runtime collisions in sourcemaps from multiple webpack projects built as libraries.",
|
||||
"type": "string"
|
||||
},
|
||||
"filename": {
|
||||
"description": "Specifies the name of each output file on disk. You must **not** specify an absolute path here! The `output.path` option determines the location on disk the files are written to, filename is used solely for naming the individual files.",
|
||||
"type": "string",
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
it("should include webpack://mylibrary/./test.js in SourceMap", function() {
|
||||
var fs = require("fs");
|
||||
var source = fs.readFileSync(__filename + ".map", "utf-8");
|
||||
var map = JSON.parse(source);
|
||||
map.sources.should.containEql("webpack://mylibrary/./test.js");
|
||||
});
|
||||
|
||||
require.include("./test.js");
|
|
@ -0,0 +1,3 @@
|
|||
var foo = {};
|
||||
|
||||
module.exports = foo;
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = {
|
||||
output: {
|
||||
library: "mylibrary"
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false
|
||||
},
|
||||
devtool: "cheap-source-map"
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
it("should include webpack://mynamespace/./test.js in SourceMap", function() {
|
||||
var fs = require("fs");
|
||||
var source = fs.readFileSync(__filename + ".map", "utf-8");
|
||||
var map = JSON.parse(source);
|
||||
map.sources.should.containEql("webpack://mynamespace/./test.js");
|
||||
});
|
||||
|
||||
require.include("./test.js");
|
|
@ -0,0 +1,3 @@
|
|||
var foo = {};
|
||||
|
||||
module.exports = foo;
|
|
@ -0,0 +1,10 @@
|
|||
module.exports = {
|
||||
output: {
|
||||
devtoolNamespace: "mynamespace"
|
||||
},
|
||||
node: {
|
||||
__dirname: false,
|
||||
__filename: false
|
||||
},
|
||||
devtool: "cheap-source-map"
|
||||
};
|
Loading…
Reference in New Issue