The code side of life

Debugging a Webpack plugin / loader with webstorm.

Introduction

user

Shlomi Assaf


Debugging a Webpack plugin / loader with webstorm.

Posted by Shlomi Assaf on .
Featured

Debugging a Webpack plugin / loader with webstorm.

Posted by Shlomi Assaf on .

Updates: See bottom section for updates added to this article.

Webpack is awesome!

Webpack is a powerful build tool, it is so powerful that in most cases you will never need to extend it. The existing plugins and/or loaders covers most use cases.

If you do need to extend it, loaders are your first choice and if you need more freedom go for plugins.

More juice?

Recently I had a use case that wasn't covered by existing webpack plugins/loaders and I had to extend it by implementing a plugin extension.

While webpack loaders are relatively easy to implement plugins are a completely different story since they require understanding of webpack's internal objects and process workflow, in fact webpack itself is a composition of plugins (and loaders) that each performs a single task, this is what makes webpack so powerful yet complex.

If complexity wasn't enough, understanding the code was hard and tedious, webpack plugins communicate via plugin "hooks", these hooks are actually events that point to phases in the build process lifecycle.

Dive into the core

Since little documentation exist regarding plugin development the only real option left is step-through debugging, for this task proper tooling is essential, the more help you get the less time it will take you to understand, especially with an event driven code which isn't friendly to us human.

Debugging a Plugin/Loader is actually running webpack's compilation process for each debug session, I recommend using a light mock project as a compilation target. You can create it in the same project as the Plugin/Loader or use different locations and link the plugin/loader via symbolic link.

Diving gear

For debugging I have tried node-inspector but it took a lot of time for webpack to boot before hitting my breakpoint. Another issue was the fact that each debug session had to be executed from the command line since webpack runs once and finishes (opposed to a server for instance, that runs "forever"). Running it everytime means breakpoint wont work, the only break point option was to insert hardcode debugger; instructions.

My next target was iron-node, this one uses the electron shell to manage the debug console, while this worked fast it still didn't solve the 2nd problem, still every run used a new "electron" shell and all breaking points were cleared between runs.

My last resort was actually my first but I couldn't make it run so I turned to the other
2. It is always better to use your IDE as a debugger if it has a powerful one.

I'm using Webstorm, which has native support for Gulp/Grunt debugging but it doesn't have support for webpack at this point. (it has support for debugging application that use webpack)

Grunt/Gulp/Webpack/etc... use a command line script to execute the build process and this is tricky to configure in webstorm. You could do a remote debugging session but its not robust enough.

Solution

My solution is simple and easy to implement, I've added a file to the root of my folder and simply required the script that runs webpack CLI script, running this file as the entry point for the debug process will result in debug webpack bundle session.

If you install webpack locally you can debug webpack internals as well, cool.

Here is the code for the file with support for local webpack installtion that fallback to the global installation:

var path = require('path');

require('child_process').exec("npm config get prefix", function(err, stdout, stderr) {  
    var nixLib = (process.platform.indexOf("win") === 0) ? "" : "lib"; // win/*nix support

    var webpackPath = path.resolve(path.join(stdout.replace("\n", ""), nixLib, 'node_modules', 'webpack', 'bin', 'webpack.js'));
    require(webpackPath);
});

This was a quick attempt to debug Plugins/Loaders, it should work on linux/OSX/windows buy I've only tested it on OSX with local webpack installation, post a comment if it doesn't work for you or if you have any comments/notes.

Good luck.

Updates:

The article describes a way to debug webpack as if you were to run it from the CLI without any parameters. The following updates suggest more advanced options:

Update #1: Executing webpack programatically:

var WebpackDevServer = require("webpack-dev-server");  
var webpack = require("webpack");

// Set environment variables here...

var webpackConfig = require('./webpack.config.js');

webpackConfig.plugins.unshift(new webpack.HotModuleReplacementPlugin());

var compiler = webpack(webpackConfig); // load webpack  
// run dev-server
var server = new WebpackDevServer(compiler, {  
    devtool: "source-map",
    contentBase: "/",
    publicPath: "/",
    hot: true,
    inline: true,
    progress: true,
    colors: true
});
server.listen(8000);  

Now simply right click on this file and run a debug session.

UPDATE #2: With the recent changes in chrome dev tools you can now debug NodeJS apps inside chrome dev tools, this is true for webpack as it runs in NodeJS. This is pretty cool, you can debug both webpack core and your web app at the same time! See this cool article from Sean T. Larkin.

user

Shlomi Assaf