How to Fix Your Server-Side TypeScript Call Stack With webpack.BannerPlugin

TypeScript is a great language choice when you’re writing a large server-side Node.js project such as a universal React+Redux web application. However, debugging errors is challenging if you’re not set up for it properly.

Take an error call stack, for example…

An Insane Call Stack…

This is what TypeScript server-side errors can look like (without source map support):

Error: Big scary error message
    at Object.defineProperty.value (D:\BitBucket\Project\dist\server.js:2:8875)
    at t (D:\BitBucket\Project\dist\server.js:1:163)
    at Object.defineProperty.value (D:\BitBucket\Project\dist\server.js:22:2851)
    at t (D:\BitBucket\Project\dist\server.js:1:163)
    at Object.e.exports (D:\BitBucket\Project\dist\server.js:30:27387)
    at t (D:\BitBucket\Project\dist\server.js:1:163)
    at Object. (D:\BitBucket\Project\dist\server.js:21:29025)
    at t (D:\BitBucket\Project\dist\server.js:1:163)

Oh, I have an error on line 2… at column 8875 of a minified JavaScript bundle.

Thanks, log file.

A Sane Call Stack…

Once you have source map support enabled, the stack traces show you real line and column numbers from your actual source files. It’s almost like being back in C#. Almost.

This is what TypeScript server-side errors look like with source map support enabled:

Error: Big scary error message
    at Object.defineProperty.value (...\src\app\reducers\sessionReducer.ts:9:37)
    at __webpack_require__ (...\webpack\bootstrap af0efb5a57f02f296438:19:1)
    at Object.defineProperty.value (...\src\app\reducers\appReducer.ts:4:26)
    at __webpack_require__ (...\webpack\bootstrap af0efb5a57f02f296438:19:1)
    at Object.module.exports (...\src\server\webRequestHandler.ts:5:22)
    at __webpack_require__ (...\webpack\bootstrap af0efb5a57f02f296438:19:1)
    at Object. (...\src\server\webServer.ts:8:29)
    at __webpack_require__ (...\webpack\bootstrap af0efb5a57f02f296438:19:1)

Oh, okay. Hello… error on line 9 of sessionReducer.ts.

FIXED

How do we do it?
Simple, with webpack.BannerPlugin.

Banner Plugin to the Rescue

Webpack includes a plugin called BannerPlugin that allows you to insert content at the beginning of a bundle. I think it’s intended for things like copyright and license statements (you’d never know, though, because the documentation is… sparse).

Fortunately, we can also use it to inject a require statement to setup source map support.

First, add the source-map-support package to your project

npm install --save source-map-support

Then update the webpack configuration for your server bundle to include the BannerPlugin as follows:

Webpack v1.x

module.exports = {
  devtool: 'source-map',
  plugins: [
    new webpack.BannerPlugin(
      'require("source-map-support").install();',
      { raw: true, entryOnly: false }
    ),
  ],
};

Webpack v2.x

(BannerPlugin had a breaking change from v1 to v2)

module.exports = {
  devtool: 'source-map',
  plugins: [
    new webpack.BannerPlugin({
      banner: 'require("source-map-support").install();',
      raw: true,
      entryOnly: false
    }),
  ],
};

Good luck with your debugging!

Want Modern web development to be easier?

I've got lots of tools, tips, best practices, and code to share with you.
Sign up on my list to be notified when new posts are published.

(100% spam free and one-click unsubscribe)

How to Fix Your Server-Side TypeScript Call Stack With webpack.BannerPlugin

Leave a Reply

Your email address will not be published. Required fields are marked *