Uploading Source Maps to Sentry with Webpack

“round gray framed compass on brown map” by Himesh Kumar Behera on Unsplash

Prereqs:

  • Sentry — Open-source error tracking that helps developers monitor and fix crashes in real time.
  • Raven-JS — Sentry SDK for JavaScript
  • Webpack — Webpack is an open-source JavaScript module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

If you’re like us at INTURN, you’ve found great value in having live error tracking integrated with your apps. Not only can you see if there are any issues in your production applications, but you can hook up error tracking to any environment and see when and where an error is thrown. After doing some research, we chose Sentry for our error tracking because of its ability to track in multiple environments, and across multiple releases.

When hooking this up to our front-end application, we used React’s Error Boundaries to manage our calls to Sentry with this bit of code:

import React from 'react';
import InternalErrorBoundary from 'react-error-boundary';
import Raven from 'raven-js';
const defaultOnErrorHandler = (error, stack) => {
console.error(error, stack);
  Raven.captureException(
error,
{ extra: stack, tags: { errorBoundary: true } }
);
};
const ErrorBoundary = props => (
<InternalErrorBoundary
onError={defaultOnErrorHandler}
{...props}
/>
);
export default ErrorBoundary;

This way, whenever an Error Boundary is hit, we send a request to Sentry with the error and stack information. While we have a few other custom exceptions, the majority of the errors in our app are reported this way. At the end of the day, it was a simple way to get a ton of information about any errors our users see.


After some time using Sentry in our production app, we noticed a couple issues with how our errors were being reported. The first issue was that we had no context in terms of which version of our software was throwing this error. The second, and most important, was that we were getting minified code in our reports, which made it difficult to figure out where the actual issue was in our files. We decided to make these two improvements to our Sentry setup:

  • Adding versions to our Sentry reporting by using git’s SHA-1 hash
  • Adding source maps to our error traces

Adding versions to Sentry seemed like the low-hanging fruit, so we decided to tackle that first. In setting up Sentry, we had created a raven.js file that housed our configuration for Raven (if you need help doing this, see the Sentry docs here). This config accepts a release key, and since we already pass that into our build command as process.env.GIT_SHA1, we added that to our Raven config. And just like that, errors were attached to a specific git hash!


Now for adding source maps. The easiest solution was to build and bundle them with our application, but there are many obvious issues with doing this (security, bundle size, etc.). So we did some digging, and the first thing that we found was sentry-webpack-plugin, which we were excited about. Reading the docs, it seemed like a pretty simple setup to get source maps hooked up to Sentry.

Unfortunately, two days later, we still couldn’t figure out how to get it working. We re-read the docs and tried every configuration that might make sense, but still got nothing. We weren’t even seeing files attempting to be uploaded to Sentry (if you had success with this plugin, please let us know what you did!).

This is when frustration started to kick in.

“grayscale photography of woman opening her mouth while hanging her hands near her face” by Gabriel Matula on Unsplash

After no success with the plugin, we decided to try using Sentry’s CLI tool, sentry-cli. The first step was to yarn add -D @sentry/cli. Then, we needed to figure out how to use sentry-cli. After reading the docs here, we were able to access our projects with this command:

yarn sentry-cli --auth-token=${SENTRY_API_KEY} projects --org={SENTRY_ORG} list

NOTE: If you haven’t created an API Key for Sentry, you can do so by following this link (just make sure to enable the project:write option or you won’t be able to upload your source maps).

Now that we were able to access the project, let’s try to create a release using the following command:

yarn sentry-cli --auth-token=${SENTRY_API_KEY} projects --org={SENTRY_ORG} --project={SENTRY_PROJECT_NAME} new test-release

This creates a new release in Sentry called test-release , which you should be able to see in your Sentry web app.

NOTE: If you are using a git hash for your release name, the title of the release will be shown as a short version of that hash. However, actual release name is the full git hash. This threw us for quite some time, but hopefully our pain can save you some.

The next step is to upload some source maps to a release, but first, we need some generated source maps to upload.


During your build process, you want to make sure that you build source map files. For us, this meant turning the sourceMap option on in UglifyJsPlugin , and adding SourceMapDevToolPlugin to our build with the following configuration (appending the sourceMappingURL is required in Sentry’s docs):

new webpack.SourceMapDevToolPlugin({
filename: '[name].[hash].js.map',
exclude: ['vendor'],
append: '//# sourceMappingURL=[url]',
}),

Next, you need to upload these files to Sentry with the following command:

yarn sentry-cli --auth-token=${SENTRY_API_KEY} releases --org={SENTRY_ORG} --project={SENTRY_PROJECT_NAME} files ${GIT_SHA1} upload-sourcemaps "./dist/*.js.map" --url-prefix "~/dist/"

This assumes you’re using the git hash for your release name, but if you’re not, you just need to substitute the GIT_SHA1 with whatever name or variable you decide to use for your release name. Just make sure it matches whatever is set in your app’s raven.js file.

Also, you’ll notice we added a --url-prefix . This was the last big hurdle for us to jump over to get these source maps working. Essentially, Sentry’s source map paths must match the file names exactly. We noticed that since we’re using a dist directory for our assets, we needed to prefix the url when we upload to Sentry. If you get stuck here, just check the names of the source maps in webpack’s output and compare it to the name of the uploaded files in your Sentry release.

One final step here is to delete the generated source maps before you put this app into production, so clients don’t see them. We do this in our builds by running rm -rf ./dist/*.js.map after we upload.

And that’s it! You should see the source maps uploaded to your release in Sentry, and when you use a version of your app that has the same release name set in its raven.js file, the source maps will be applied in Sentry.

Photo by rawpixel on Unsplash