logo

Source Maps

Context

Adding a build step has lots of benefits: performance, security, new language features. One of the downsides though is that the compiled code can be obfuscated and difficult to debug.
Source maps exist to try and preserve the original debugging experience as best as possible. Today, most JS debuggers use source maps to show the original code, but struggle to show the original variables.
This can be frustrating because even though its possible to use the debugger to pause, once you pause then its hard to evaluate expressions or even find the variable you're looking for.

Our Approach

We take mapping very seriously and have gone to great lengths to preserve the original debugging experience. We believe most of the time folks just want to see the original context. The code should be unchanged, expressions should just work, and variables should be original.
If folks do want to see the built code, that's cool too, but we're going to assume the original context is preferred and just default to it. We'll also pull out all of the tricks to preserve the original context.

Uploading Source Maps

For production use cases where sourcemaps may not be exposed publicly, we provide tooling for preemptively uploading sourcemaps to our servers so that when recordings are made, they can make use of these maps. We provide both a CLI command, and a Webpack plugin to make integrating this into your build process as easy as possible.

API Keys

We recommend using the RECORD_REPLAY_API_KEY environment variable to set up the API for use in all of our following examples, but each also allows passing the key directly as an argument. API Keys are available in the Team Settings modal.

CLI

The sourcemap-upload CLI is available on npm at @recordreplay/sourcemap-upload-cli and you can explore the available options at https://github.com/RecordReplay/sourcemap-upload-cli.
The simplest usage will be running the following after your production JS build has finished
replay-sourcemap-upload --group <Version or SHA> <buildOutputDir>
You must ensure that your build tool is configured to output sourcemaps into the build directory you provide.

Webpack

The sourcemap-upload Webpack plugin is available on npm at @recordreplay/sourcemap-upload-webpack-plugin and you can explore the available options at https://github.com/RecordReplay/sourcemap-upload-webpack-plugin and https://github.com/recordreplay/sourcemap-upload.
The simplest usage will be to edit your webpack.config.js to include a new entry in the plugins array at the top level of the file, e.g.
javascript
const ReplaySourceMapUploadWebpackPlugin = require("@recordreplay/sourcemap-upload-webpack-plugin"); module.exports = { // ... // Ensure that Webpack has been configured to output sourcemaps. devtool: "source-map", // ... plugins: [ // Enable our plugin to upload the sourcemaps once the build has completed. // This assumes NODE_ENV is how you distinguish production builds. If that // is not the case for you, you will have to tweak this logic. process.env.NODE_ENV === "production" ? [new ReplaySourceMapUploadWebpackPlugin({ filepaths: ["outputDir/"], group: "<A unique version string or git SHA>" })] : [], ], // ... }
Keep in mind that your build output will now contain sourcemaps, so you should take care to ensure that these maps aren't also exposed on your production site.

NextJS

NextJS uses Webpack internally, so the plugin above will also be used for NextJS, but the config that needs editing is next.config.js instead. NextJS's own documentation is a good place to start and shows how to add Webpack plugins to your build process. You'll also need to enable production sourcemaps, so you'll end up with the following additional config in your next.config.js file:
javascript
module.exports = { // ... productionBrowserSourceMaps: true, // ... webpack: (config, { buildId, dev, isServer }) => { if (!dev && !isServer) { config.plugins.push(new ReplaySourceMapUploadWebpackPlugin({ // If you've configured a custom build directory, this should // point to that directory. filepaths: [".next/"], // Potentially the 'buildId' argument here could be used. group: "<A unique version string or git SHA>" })); // 'productionBrowserSourceMaps' will output your sourcemaps // into the build directory, which can expose them from your // production server as well, so you will likely want to delete // the .map files once they have been uploaded. config.plugins.push(compiler => compiler.hooks.afterEmit.tapPromise("DeleteSourceMaps", () => del(".next/**/*.map") ) ); } return config; }, // ... };
As mentioned, NextJS's buildId can be useful, but please see their docs to ensure verify if it is a good fit for your application.
πŸ’‘
If you are serving your site via Vercel, see their docs for information on setting up the RECORD_REPLAY_API_KEY environment variable.

Debugging problems

Each of these approaches will log the sourcemaps as they are uploaded so that you can validate that all of the files you expect are being detected. They each also have a verbose mode, either logLevel: "verbose" for the JS plugins, and --verbose for the CLI.
If you're feeling particularly adventurous, you can also run these with the DEBUG=recordreplay:sourcemap-upload environment variable set to enable tons of debug logging, though that will likely mostly be useful to pass along to us to work with you on any issues you may face.

Using Source Maps

Once source maps have been uploaded, you can toggle between the bundled code and the original source in a replay.
The toggle in the lower-left side of a source will indicate if it is an Original Source file. Clicking the toggle will automatically open the corresponding bundled file.

Source Maps Visualization

The Source Map Visualization is useful for seeing how original and generated sources map to each other. The visualization can help trace issues in minified code back to the original code. The visualization can also help identify issues with breakpoints or minified variables in DevTools.
πŸ’‘
Read more about how we developed this feature in the blog post here.
If a source map is available, click the Source Map icon next to the Original Source toggle to open the Visualization. The Original Source is shown on the left and the bundled code on the right. Hover over values to see how they map between the source and bundled code.
Image without caption

Was this page helpful?