Debugging Production Issues With Sentry and Nuxt.js

A short tutorial on how to display the source code in Sentry when using the Nuxt.js generate command

Photo by Hayley Maxwell on Unsplash

The Problem

Recently I was faced with a bunch of front end errors occurring only in the production environment. The error reports were coming from Sentry and it was really hard to understand exactly where in the application the error was occurring. I knew I needed to see the code in order to understand what was going on.

The site was generated using a nuxt generate Nuxt.js command, which caused another, less severe, problem. Each error was treated as unique by Sentry, since they were coming from files with different names (based on hash).

Here’s what I saw in Sentry:

The Solution

Source maps can be used to retrieve the source code when displaying error messages.

Source maps are for transpiled languages, what debugging symbols are for compiled languages. They contain the mapping between original human readable source code and the generated browser optimized code.

In terms of implementation, source maps are simple JSON files with .js.map extensions, containing original source code and some meta data. In the generated JavaScript files there’s a link to the corresponding source map on the last line, for example:

//# sourceMappingURL=cba699e9947bfbcefb70.js.map

The easiest way to use source maps is to deploy them on the server together with the application itself. This way, web browsers, DevTools Debugger, and Sentry will be able to easily find them.

It works great when developing and testing the application in a private environment, but unfortunately there’s a problem. In a public production environment the source code will be available to anyone visiting the site. If you want to hide the source code, you must avoid distributing source map files with it.

In Sentry, there’s a concept of release and it’s possible to attach source maps to it. It’s also possible to associate the error message with a given release.

When we combine these two things, Sentry is able to map a production issue to the source code and display it, even though it’s not available for your web application visitors.

The Implementation

In this example, I’m using a Nuxt.js community Sentry module. I am confident a similar solution could be applied to a Vanilla Vue application with sentry-cli utility.

To get this working, there are a couple of required steps:

I’ve created the following .sentryclirc configuration file in the root project directory:

[defaults]
org = <your-sentry-organisation-name>
project = <your-sentry-project-name>

I also need to specify the Sentry auth token. I can add it to the above file, but for security reasons it’s better to pass it through an environment variable:

SENTRY_AUTH_TOKEN=<your-sentry-auth-token>

I add the following section to nuxt.config.js file to tell the Sentry module to publish the release:

sentry: {
publishRelease: true,
},

By default the last commit hash will be used as release identifier during upload and at runtime, which is the best option in continuous delivery environments. However, you can also customize a release identifier as follows (make sure you use sentry-module 3.0.0 or later):

sentry: {
publishRelease: true,
config: {
release: '1.2.3'
}
},

Please also note that you can use environment variables to dynamically specify Sentry module options without touching the config file. For example, setting SENTRY_PUBLISH_RELEASE=true will enable the release upload.

I need to delete the .map.js files before uploading the site to the server, otherwise they will be published together with the website. Sentry CLI doesn’t have such an option yet, so I need to do it manually. I use a cross-platform rimraf utility for the job, by adding the following to my package.json file:

"scripts": {
...
"generate": "nuxt generate",
"dist": "npm run generate && rimraf dist/**/*.js.map"
}

Finally, I add the required library to my devDependencies section:

npm install --only=dev rimraf

The Result

Now I have the original source code beautifully displayed on the Sentry issue page, along with the correct source file name:

I hope this was useful — please do not hesitate to share your thoughts.

Happy debugging!

Edits

  • I clarified the release identifier handling and simplified the solution by using sentry-cli releases propose-version.
  • I simplified release identifier handling even further thanks to improvements in Sentry module 3.0.0. Mentioned environment variables to specify options.

Resources

  1. Releases in Sentry: https://docs.sentry.io/workflow/releases
  2. Uploading source maps to Sentry: https://docs.sentry.io/platforms/javascript/sourcemaps/
  3. Sentry JavaScript client configration file: https://docs.sentry.io/clients/javascript/config/
  4. Nuxt Sentry community module: https://github.com/nuxt-community/sentry-module
  5. Sentry official command line utility: https://github.com/getsentry/sentry-cli
  6. Sentry official Webpack plugin: https://github.com/getsentry/sentry-webpack-plugin

Full-Stack Developer / Agilist / Free and Open Source Software Fan.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store