Skip to content

Commit

Permalink
adding output.devtoolNamespace option
Browse files Browse the repository at this point in the history
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:
webpack#5767
  • Loading branch information
MagicDuck authored and Stephan Badragan committed Oct 18, 2017
1 parent 168f923 commit fa8b790
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 6 deletions.
2 changes: 1 addition & 1 deletion lib/EvalDevToolModuleTemplatePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion lib/EvalSourceMapDevToolModuleTemplatePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
13 changes: 11 additions & 2 deletions lib/ModuleFilenameHelpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand All @@ -83,7 +86,8 @@ ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFil
allLoaders: allLoaders,
query: query,
moduleId: moduleId,
hash: hash
hash: hash,
namespace: namespace
});
}
return moduleFilenameTemplate
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
};
4 changes: 2 additions & 2 deletions lib/SourceMapDevToolPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
7 changes: 7 additions & 0 deletions lib/WebpackOptionsApply.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions schemas/webpackOptionsSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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");
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var foo = {};

module.exports = foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
output: {
library: "mylibrary"
},
node: {
__dirname: false,
__filename: false
},
devtool: "cheap-source-map"
};
8 changes: 8 additions & 0 deletions test/configCases/source-map/namespace-source-path/index.js
Original file line number Diff line number Diff line change
@@ -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");
3 changes: 3 additions & 0 deletions test/configCases/source-map/namespace-source-path/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var foo = {};

module.exports = foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
output: {
devtoolNamespace: "mynamespace"
},
node: {
__dirname: false,
__filename: false
},
devtool: "cheap-source-map"
};

0 comments on commit fa8b790

Please sign in to comment.