Squeeze your webpack bundles even more by extracting Babel helpers

Marko Stijak
Codaxy
Published in
3 min readAug 23, 2017

--

If you’re using webpack, Babel and React (or CxJS or Angular), you probably deal with a large number of classes. ES6 brings a nice class syntax, but it comes with a cost. In order to make things work in older browsers you’re probably using Babel to compile the code, so let’s see what Babel does.

ES6:

class MyComponent extends React.Component {

}

ES5:

“use strict”;function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(“Cannot call a class as a function”); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(“this hasn’t been initialised — super() hasn’t been called”); } return call && (typeof call === “object” || typeof call === “function”) ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== “function” && superClass !== null) { throw new TypeError(“Super expression must either be null or a function, not “ + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var MyComponent = function (_React$Component) {
_inherits(MyComponent, _React$Component);
function MyComponent() {
_classCallCheck(this, MyComponent);
return _possibleConstructorReturn(this, (MyComponent.__proto__ || Object.getPrototypeOf(MyComponent)).apply(this, arguments));
}
return MyComponent;
}(React.Component);

Yes, you’re seeing it right. Test it here. To make things even worse, Babel works on individual files which means that each file containing a class will be polluted like this.

Babel has a few helper functions that’ll be placed at the top of the generated code if needed so it’s not inlined multiple times throughout that file. This may become an issue if you have multiple files, especially when you’re sending them to the browser. gzip alleviates most of this concern but it’s still not ideal.

babel-plugin-external-helpers

Fortunately, Babel offers a plugin that helps with this problem. It is called babel-plugin-external-helpers. If you use this plugin, the helper functions will be accessed from a global variable called babelHelpers, instead of being added the generated code.

var MyComponent = function (_React$Component) {
babelHelpers.inherits(MyComponent, _React$Component);
function MyComponent() {
babelHelpers.classCallCheck(this, MyComponent);
return babelHelpers.possibleConstructorReturn(this, (MyComponent.__proto__ || Object.getPrototypeOf(MyComponent)).apply(this, arguments));
}
return MyComponent;
}(React.Component);

This is not perfect, but it’s much better. We can get a nice size reduction if we define a global variable called babelHelpers and use babel-plugin-external-helpers. Babel offers a way to automatically generate helpers in your application, but the proposed way doesn’t work well with Webpack. To overcome this problem, I simply made a new file and put all required helpers inside. Here is the babelHelpers.js file that I ended up with.

We still need to tweak the webpack configuration. Two changes are required here:

  1. Load babelHelpers.js before the rest of the code:
entry: {
app: [
__dirname + '/babelHelpers.js'
__dirname + '/index.js'
]
},

If you’re using a file to load polyfills, that might be a good place to include babelHelpers.js too.

2. Make sure babelHelpers.js is not processed by Babel:

{
test: /\.js$/,
loader: 'babel-loader',
exclude: /(babelHelpers)/,
...
}

That’s it. Your application bundles should be slightly smaller now. For CxJS Docs, savings are between 5% and 10%, or around 100 kB across all bundles.

Not bad for a small change like this.

If you’re a developer, you should definitely check out CxJS. There is no better tool for the job if you’re building an advanced JavaScript business application. Form widgets, data tables, charts, client-side routing, advanced layouts, themes, and many other features are available out of the box.

--

--