Tree shaking with Webpack 2, TypeScript and Babel

Posted on Mar 6, 2017

Some time ago I updated typescript-library-starter, a zero-config starter repo for writting a TypeScript library, with tree-shaking, babel-preset-env, and more:

Right now it uses RollupJS, but same concepts apply. So I thought, why not sharing that to the people? Hope you find it useful and safes you some time I had to spend 😃

What is really tree-shaking?

Tree shaking is an algorithm introduced first by RollupJS and also implemented by Webpack 2 that removes any unused code when bundling your code. It relies on ES2015 modules in order to achieve that.

Let's see an example. You have a file greetings.js:

/* greetings.js */

export function sayHello() {
  console.log("Hello");
}

export function sayBye() {
  console.log("Bye");
}

Which you import in your index.js:

/* index.js */

import { sayHello } from "./greetings";

sayHello();

We can see that sayBye is not used. When using tree-shaking, that code will be removed from the final bundle. Otherwise it will be included even if it's not used.

Why Typescript + Babel?

You have a good explanation in the typescript-library-starter repo.

Cool, show me how to do it!

As mentioned, tree-shaking relies on ES2015 modules, so we need to make sure we use them. For that:

  • Use ES2015 in TypeScript
  • Use ES2015 modules in Babel
  • Just run webpack -p (production mode) and that should be it

1. Use ES2015 in TypeScript

You need to set "target": "es2015" in tsconfig.json file. Note that is not necessary to set "module": "es2015".

{
    "compilerOptions": {
        "moduleResolution": "node",
        "target": "es2015",
        "lib": ["es2016", "dom"],
        ...
    }
}

More info in compiler options TypeScript page.

2. Use ES2015 modules in Babel

I'd strongly suggest you using babel-preset-env. By far the most flexible and useful Babel preset 😃

Anyways, whatever preset you use, you must indicate module: false in your .babelrc file:

{
  "presets": [
    [
      "env",
      {
        "targets": {
          "browsers": ["last 2 versions", "safari >= 7"]
        },
        "modules": false
      }
    ]
  ]
}

3. Let's see the results

Now, when you have your webpack.config.js setup, if you run webpack, you'll see within the generated output an unused harmony comment, like:

...
/* unused harmony export sayBye */
/* harmony export (immutable) */ __webpack_exports__["a"] = sayHello;
// This function isn't used anywhere
function sayBye() {
  console.log('Bye')
}
...

And if we run webpack -p for production build, that code will be stripped out. To check that you can search for the string 'Bye' on the generated output. It shouldn't be there.

Try it yourself!

typescript-library-starter uses tree-shaking! Download the repo, follow the instructions and, be curious and try the code we used at the beginning of this article! Right now it uses RollupJS, but same tree-shaking happens when you run npm run build. If you wanna check the Webpack version, check out this commit in particular to see how it was.

Alex Jover

ALEX JOVER

Google Dev Expert, Vue team member, cats and dance lover. Find here all my teachings about web development, web performance and more.

Alex Jover Morales © 2018