Easy Debugging In React With WebPack Source Maps

Linda Ikechukwu
4 min readFeb 14, 2019

--

image from undraw.co

Create-react-app is so cool, but if you’re just like me that wants to understand how things work underneath, then I’ll assume you’ve tried to setup react with Webpack from the ground up. Great !!! Now let’s talk about how debugging is done.

In these times , web assets such as CSS and Js aren’t loaded individually. Instead, they are either complied, transpiled or concatenated and served as one minified and/or bundled file with the aid of tools such as Webpack, Gulp etc for performance purposes. As awesome as this is, a difficulty arises when an error comes up in your application, say usage of an undefined constant only to head over to the console and be pointed to a main.js file which looks nothing like the code you have written. Enter source maps to the rescue.

A source map is a software that provides the browser with a means of mapping back code within a compressed file back to its original position in a source file. This way, when an error occurs, you’re pointed to the exact file and line from which it emanates from. So if you’re using any tool that minifies, concatenates or bundles up your code, you’ll definitely need to generate source maps

Setting Up Source Maps in Webpack.

For Development:

To incorporate the source map functionality , we just need to set up a single property, devtool in the webpack.config.js file which will be equal to a string which contains the type of source map to be used. There are quite a number of options, some best suited for development, others for production. You can take a look at all the options available at the official webpack documentation. It explains the pros and cons of each option. I recommend the inline-source-map .So to our webpack.config file we’ll simply add :

devtool : 'inline-source-map'

Now when we encounter an error in the console, It’ll point us to the correct file and line. Cool huh??

Remember whenever a change is made to the webpack.config.js file, you’ll need to stop and restart the DevServer for those changes to manifest.

For Production :

Source maps are great but the thing is when we run npm run build while using development based source maps, webpack ships both our application code and the generated source maps into the main.js file which may total 3MB and above in file size. This is totally ridiculous and not performance optimized.

For production, we would still need source maps in case we run into errors, but we will opt for a slower option which will ship generated source maps into an external file and load only when the devtool is opened up in a browser. I use the source-map option.

But first, to build for production we need to set up webpack to run in production mood. This automatically optimizes and minifies our code. To do that, we’ll simply set up two build options in our package.json under scripts :

"scripts" : {
"build:dev" : "webpack --mode development ",
"build:prod" : "webpack --mode production"
}

For more details take a look at this.

Next, we need a mechanism to tell webpack to use the source-map option for devtool when building for production. The webpack official doc advises having seperate webpack configuration file for each mode. For me I simply use a tweak which can be read about in details here.

In my webpack.config.js file, I export a function instead of an object. This function gets called with an env parameter, which equals whatever environment webpack is run in. So my webpack.config.js file goes from

const path = require('path');module.exports = {
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader']
}]
},
devServer :{
contentBase : path.join (__dirname,'public'),
historyApiFallback : true
},

devtool : 'inline-source-maps'
};

to :

const path = require('path');module.exports = (env) => {                     *
console.log(env); *
const isProduction = env === 'production'; *
return {
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader']
}]
},
devServer :{
contentBase : path.join (__dirname,'public'),
historyApiFallback : true
},

devtool : isProduction ?'source-map' : 'inline-source-map' *
};
};

We’ll also make a little modification also to our package.json file to define our environment variables.

"scripts" : {
"build:dev" : "webpack --mode development --env=development",
"build:prod" : "webpack --mode-production --env=production"
}

Now when we run npm run build:prod we should see ‘production’ outputted to the console and if we run npm run build:dev , we should see ‘development’ outputted to the console.

We have devised a means to keep track of what enviroment webpack runs on , let me go ahead to explain the changes made to the package.json file which were asterisked.

First, we exported our webpack configurations as a function which gets called with an env parameter instead of an object. Then we define a const isProduction which evaluates to true if env === production . Next we use the ternary operator on devtool to run source-map if isProduction is true and inline-source-map if it is false.

Now running npm run build:prod runs devtool with the source-map option giving rise to a less bulkier main.js file which is production friendly, while npm run build:dev runs devtool with the inline-source-map option.

this article covers how to generate source maps in webpack both for development and production mode without neglecting optimization principles for easier debugging. I hope you found it enlightening, don’t forget to clap too.

In a later article I will be publishing my how I configure my entire webpack + babel + React setup, both for development and production. Till then you can keep in touch with me or say hello via twitter.

--

--