TypeScript Tips: How to reduce the size of a bundle

While developing with TypeScript, you might notice that your bundle size becomes bigger despite all minification techniques. Of course, as your code grows, your bundle will also grow. However there is one hint, which might help you and reduce the size of a resulting bundle. The hint works really good for web projects, which use TypeScript together with webpack. It also means, that this hint is applicable to SPFx solutions as well.

The new size of a bundle heavily depends on your TypeScript code, TypeScript features you use and the amount of TypeScript files you have in your solution. For small solutions it might not work, for mid and big ones it definitely works. Anyway you can verify it on your own solution to see the difference. Let’s get started!

ImportHelpers

TypeScript has a compiler option called importHelpersimport emit helpers (e.g. __extends, __rest, etc..) from tslib. What is “helpers” and what is “tslib”? Let’s see it.

Helpers

Helpers are small pre-build functions, which TS compiler uses in order to polyfill some missing JavaScript functionality. For example async\await feature, spread syntax, class inheritance and some other things. Take a look at this simple example. In my sample I have two simple classes, however a lot of extra code was generated in the right side pane. These __extends, __assign, __awaiter, __generator are our helper functions. The thing is, that if you have say 10 similar files, in every file helpers will be duplicated. When webpack bundles all files, it simply puts everything in one file without stripping out duplicated code (because from webpack’s perspective it’s not even duplicated, that’s simply different methods in different files). Now you see the space for improvements – there is no point to have helpers in every file, it’s much better to move it into a separate library or module. tslib is for rescue here.

tslib

tslib is a library from Microsoft, which holds all helpers, emitted by TS compiler. This library is used internally by importHelpers TS compiler flag.

--importHelpers

As soon as you provide this flag for TS compiler, it will emit different code for helpers. For example instead of

var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
exports.x = {};
exports.y = __assign({}, exports.x);

below will be emitted:

var tslib_1 = require("tslib");
exports.x = {};
exports.y = tslib_1.__assign({}, exports.x);

You see, we saved a lot of lines. Now imagine that in every file we also get rid of extra helpers. Total line saving might be significant! More files (and functionality) you have, more lines will be saved.

How to enable the feature for your project

It’s very simple. Firstly add tslib as a dependency:

npm install tslib --save

Then in your tsconfig.json, under compilerOptions add

"importHelpers": true

As soon as you do that, TS compiler will emit require(“tslib”)  statements for all helper functions. All helpers functions will be imported into your bundle only once. The downside is, that all of them will be imported (currently approx. 20 functions), despite that you probably don’t need all of them. The good thing is, that they are relatively small. And once again, by eliminating repeated TS code you might reduce the size of a bundle.

This feature available since TS 2.1, so you can safely use it.

Sample solution

I’ve created a sample project here at GitHub to test this feature. I created 5 TS classes, with inheritance, every class has async function. I added wepack 4 production build with minification. You can also try it. Minimal path to awesome:

clone the repo
npm install
npm run build

In dist folder two files will be generated: bundle.js and bundle-with-tslib.js. Bundle size without tslib: 12.6KB. With tslib: 9.5KB. Bundle with tslib is 25% smaller! Of course I got such impressive results because I have only a few lines of source code in my files. Most likely you will lot smaller results. Anyway just try it and see if it reduces the size for you.

As said, you can also enable –importHelpers for your SPFx project. Don’t forget to install tslib beforehand. While testing use –ship flag, in order to compare minified bundles.