-
-
Notifications
You must be signed in to change notification settings - Fork 8.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adding output.devtoolNamespace
option
#5844
Conversation
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
lib/ModuleFilenameHelpers.js
Outdated
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use static variables.
Instead pass the namespace
to the createFilename
method.
createFilename(module, options, requestShortener)
options: { namespace, moduleFilenameTemplate }
Also add a backward-compatibility layer when typeof options === "string"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it's now refactored to use options
you can remove this method.
lib/WebpackOptionsApply.js
Outdated
if(!options.output.devtoolNamespace) { | ||
options.output.devtoolNamespace = options.output.library; | ||
} | ||
ModuleFilenameHelpers.setModuleNamespace(options.output.devtoolNamespace); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass namespace
to the SourceMapDevtoolPlugin (next section) instead. Similar to devtoolModuleFilenameTemplate
@MagicDuck Thanks for your update. I labeled the Pull Request so reviewers will review it again. @sokra Please review the new changes. |
Hi @MagicDuck. Just a little hint from a friendly bot about the best practice when submitting pull requests:
You don't have to change it for this PR, just make sure to follow this hint the next time you submit a PR. |
I'll make it default to empty string in the webpack options defaulter to pass the tests. |
lib/EvalDevToolModulePlugin.js
Outdated
@@ -14,7 +14,7 @@ class EvalDevToolModulePlugin { | |||
|
|||
apply(compiler) { | |||
compiler.plugin("compilation", (compilation) => { | |||
compilation.moduleTemplate.apply(new EvalDevToolModuleTemplatePlugin(this.sourceUrlComment, this.moduleFilenameTemplate)); | |||
compilation.moduleTemplate.apply(new EvalDevToolModuleTemplatePlugin(this.sourceUrlComment, this.moduleFilenameTemplate, compiler.options.output.devtoolNamespace)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change the EvalDevToolModulePlugin
constructor to EvalDevToolModulePlugin(options)
with options
including sourceUrlComment
, moduleFilenameTemplate
and namespace
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you guys have any standard for documenting what the options are?
There is no way to guess from seeing something like:
constructor(options) {
this.options = options;
}
Should I add some jsdoc comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or do you completely destructure all options in the constructor?
@@ -8,15 +8,19 @@ const RawSource = require("webpack-sources").RawSource; | |||
const ModuleFilenameHelpers = require("./ModuleFilenameHelpers"); | |||
|
|||
class EvalDevToolModuleTemplatePlugin { | |||
constructor(sourceUrlComment, moduleFilenameTemplate) { | |||
constructor(sourceUrlComment, moduleFilenameTemplate, namespace) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constructor(options)
@@ -11,7 +11,8 @@ 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.namespace = compilation.options.output.devtoolNamespace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add namespace
to options
lib/ModuleFilenameHelpers.js
Outdated
@@ -48,7 +50,17 @@ function asRegExp(test) { | |||
return test; | |||
} | |||
|
|||
ModuleFilenameHelpers.createFilename = function createFilename(module, moduleFilenameTemplate, requestShortener) { | |||
ModuleFilenameHelpers.createFilename = function createFilename(module, options, requestShortener) { | |||
let opts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could do something like:
const opts = Object.assign({
namespace: "",
moduleFilenameTemplate: ""
}, typeof options === "object" ? options : { moduleFilenameTemplate: options });
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Object.assign()
can have weird consequences sometimes for your defaults:
Object.assign({foo: "default"}, {foo: undefined}) --> {foo: undefined}
Can we use extend lib instead? (https://www.npmjs.com/package/extend)
var extend = require("extend")
extend({foo: "default"}, {foo: undefined}) ---> {foo: "default"}
lib/ModuleFilenameHelpers.js
Outdated
opts = options; | ||
} else { | ||
opts = { | ||
moduleFilenameTemplate: arguments[1], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general try to avoid using arguments
.
lib/ModuleFilenameHelpers.js
Outdated
@@ -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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As it's now refactored to use options
you can remove this method.
lib/SourceMapDevToolPlugin.js
Outdated
@@ -72,6 +72,7 @@ class SourceMapDevToolPlugin { | |||
const sourceMappingURLComment = this.sourceMappingURLComment; | |||
const moduleFilenameTemplate = this.moduleFilenameTemplate; | |||
const fallbackModuleFilenameTemplate = this.fallbackModuleFilenameTemplate; | |||
const namespace = compiler.options.output.devtoolNamespace; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use compiler.options
. The plugin could be used directly without using devtool
.
Pass namespace
via the options
object in the constructor.
lib/WebpackOptionsApply.js
Outdated
@@ -193,6 +193,11 @@ 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not happen here. You can do this in WebpackOptionsDefaulter
.
@sokra when you get a chance, let me know what approach I should follow regarding documenting and defaulting options (see my comments) |
Thank you for your pull request! The most important CI builds succeeded, we’ll review the pull request soon. |
Thanks |
Yay, thanks! |
What kind of change does this PR introduce?
feature
Did you add tests for your changes?
yes
If relevant, link to documentation update:
webpack/webpack.js.org#1653
Summary
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 tooutput.library
whennot 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:
#5767
Does this PR introduce a breaking change?
No
Other information