Hello all,
I have been toiling with this issue for a day now and thought that the time has come to reach out to the community. I am hoping that @benvinegar or @mitsuhiko might be able to shed some light on this problem as they seem to be giving some great support to others with sourcemap problems. Forgive me if I have missed, but I have done quite a bit of searching and can’t find a question that encompasses my issue entirely. I will try to give as much detail as possible.
Description of issue:
The actual problem is that sourcemap artefacts are seemingly not being “linked” correctly in Sentry to the js files that are throwing the exception/error. The message I see on the issue’s page is:
(Source code was not found Url popup.js.map). The JSON errors object is:
[{“url”:“popup.js.map”,“type”:“js_no_source”}]
My artefacts seem to be uploaded correctly and are visible in the “Artefacts” tab for the particular release. (My Issues are also being correctly pinned to the release).
Summary of my thinking so far:
My suspicions about the root cause(s) of my issue are the following:
- Sentry documentation states that “~” replaces the need to state protocol and host in uploaded artefacts, however web extensions run on client browsers and have unique url-like structures - e.g. moz-extension://32183b6a-bed4-494f-9d0b-9c2dc5ff7d48/popup/popup.html. Every Installation of a web extension is given a UUID and this is used throughout its life (therefore we cannot use fully qualified urls like other web apps because every instance has a different “url”). Perhaps Sentry is not deeming “moz-extension://” as a valid protocol, or “32183b6a-bed4-494f-9d0b-9c2dc5ff7d48” as a valid host? If this were the case, the Sentry backend would potentially not be getting relative paths correct (i.e. “~/popup/popup.js.map” would not be correctly found for an exception that originated from moz-extension://32183b6a-bed4-494f-9d0b-9c2dc5ff7d48/popup/popup.js) even if correctly referenced in the js file as “//# sourceMappingURL=popup.js.map”.
- There may be a bug in the way that sourcemaps are created (or re-written) by the minifier or the sentry webpack-plugin which makes the “file” property of the .map file relative to the webpack.config.js, rather than relative to the directory that the js file resides in. For example, my “popup” map file contains: “file”:“popup/popup.js” rather than just “file”:“popup.js”. I don’t know how important the “file” property is for Sentry to link the map to the js? No matter what I try, I can’t seem to get this property to be relative to the js file that it sits next to.
Detail that got me to this point:
So I am building a web extension (for Firefox, although this is irrelevant). I’m using npm and webpack to build. The actual build output happens in ./dist/firefox/production/1.0.0/src
inside the build (i.e. the …1.0.0/src folder), the structure is broadly a bunch of directories, and a manifest file:
$ ls
assets content_scripts manifest.json popup
background options
each of these directories then contains js files and sub-directories. I will use the “popup” as my example through this post.
$ ls
popup.html popup.js popup.js.map
As you can see, the .map file is being generated as expected alongside the .js file. The .js file is minified and uglified as expected by the terser plugin (I have set sourceMap:true as explained in the Sentry docs). The .js file seems to have the correct sourceMappingURL comment at the end of the file:
//# sourceMappingURL=popup.js.map
The map file does contain the following properties (I won’t paste all content since it is too large):
"version":3,
"sources":["webpack:///webpack/bootstrap","webpack:///./node_modules/tslib/tslib.es6.js","webpack:///./src/libs/emptyLog.js" (I have shortened this),
"file":"popup/popup.js",
"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require"]...(I have shortened this),
"sourceRoot":""
My main observations about this file are that the file property seems to be a file path relative to my build script, not relative to where the map file is? Also the sourceRoot is not set (although I have tried setting this to “/” but still get the same issues)
The relevant sections of my webpack.config.js to build these maps are:
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const GitRevisionPlugin = require('git-revision-webpack-plugin');
const gitRevisionPlugin = new GitRevisionPlugin();
var entryPoints = {
...
"popup" : { outputPath: "popup", src: "./src/popup/popup.js" },
...
};
...
entry: {
...
"popup": "./src/popup/popup.js",
...
},
devtool: false, //see the webpack.SourceMapDevToolPlugin below
...
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
sourceMap: true
}),
new OptimizeCssAssetsPlugin({})
]
},
plugins: [
...
new webpack.SourceMapDevToolPlugin({
filename: "[file].map",
}),
new SentryCliPlugin({
include: "./dist/firefox/production/1.0.0/src",
ignoreFile: '.sentrycliignore',
configFile: ".sentryclirc",
ignore: ['node_modules', 'webpack.config.js', 'manifest.js', 'manifest.js.map', 'babel.config.js'],
release: gitRevisionPlugin.commithash(),
validate: true,
}),
...
],
output: {
path: path.resolve(__dirname, "dist/firefox/production/1.0.0/src"),
filename: (chunkData) => {
let ret = chunkData.chunk.name + ".js";
if(chunkData.chunk.name !== "manifest") {
ret = entryPoints[chunkData.chunk.name]["outputPath"] + "/" + chunkData.chunk.name + ".js";
}
return ret;
},
...
entryPoints is just a variable to hold output paths because I originally thought that having path structures in the chunk/entry point name was causing an issue.
One of my suspicions is that the SourceMapDevToolPlugin property “filename” is using the placeholder “[file]” which is the whole path+filename, meaning that the sourcemap gets written in the right place next to the .js file, however it is perhaps using this same filename property to write the “file” property in the .map file, whereas it should be using the path relative to the .js file?
When I run the build, the SentryCliPlugin does its job and correctly uploads the sourcemaps to the Artefacts section of the release. Since the validate option is on, the terminal also outputs sourcemap validation results (again, i’ve abbreviated a few results):
> Analyzing 23 sources
> Rewriting sources
> Adding source map references
> Validating sources
> Uploading source maps for release a0a0f443e60af88e63247f3b8d290578513e939c
Source Map Upload Report
Minified Scripts
~/assets/js/jquery.min.js (no sourcemap ref)
- warning: could not determine a source map reference (Could not auto-detect referenced sourcemap for ~/assets/js/jquery.min.js.)
- error: missing sourcemap!
~/background/background.js (sourcemap at background.js.map)
...
~/options/options.js (sourcemap at options.js.map)
~/popup/popup.js (sourcemap at popup.js.map)
Source Maps
~/background/background.js.map
...
~/options/options.js.map
~/popup/popup.js.map
OK - my bad about the jQuery one, but I can fix this easily by setting the exclude properly.
In Sentry.io, under Artefacts for the release:
Just to be sure, I have downloaded the popup.js file and confirm that the last line is still:
//# sourceMappingURL=popup.js.map
The ~/popup/popup.js.map file looks like:
{"version":3,"file":"popup/popup.js","sources":["webpack:///webpack/b..."], "sourcesContent":[" \t// The module cache\n \tvar installedMo..."],
Interestingly sourceRoot property doesn’t exist, and the “file” property has be written directly after the version (I assume this is something that the SentryCliPlugin does since “rewrite” is enabled by default).
So when I get an exception (I have just created a simple one when popup.html/popup.js is loaded, the issue is generated correctly in Sentry.io:
However:
“There was 1 error encountered while processing the event”. If I expand this out:
The relevant JSON message is:
So the error message seems to suggest that maybe Sentry could not find the sourcesContent property within the .map file? Or maybe Sentry has not found popup.js.map? The error message is not very explicit so I am at a loss!
Apologies for the mammoth post - Happy to provide any more detail or files if needed - greatly appreciate any help