As an author of (open source) packages, I think you have the responsibility to protect the bundle size of your package consumer. When you publish a package that exports a whole range of modules (for example lodash, ramda, date-fns…) you want to make sure the package is exported in such a way that the consumer of your package (mostly bundlers) can optimize size.

One of the techniques a bundler applies is tree shaking. Tree shaking is a dead code removal technique that makes sure all unused modules are excluded from the output. It’s not hard to prepare your package for tree shaking, the decisive factor is the module format you choose.


Let’s have a brief intro on the 2 most popular module formats in JavaScript.

CommonJS was originally created in 2009 by Mozilla. Initially, it was called ServerJS but was renamed to CommonJS in the same year. This format was popularized by Node.js as it is their de facto module system. You export a module using module.exports & import via require( ).

add.js (module)

const add = () => a + b;
module.exports = add;

index.js (consumer)

const add = require('./add.js');
console.log(add(1, 2));

CommonJS is dynamic which means you can use require( ) within loops/functions etc, this enables lazy loading patterns that can be useful in performance sensitive scenarios.

In this function add.js or subtract.js will only be loaded when the require( ) is reached.

const addOrSubtract = (a, b, action = 'ADD') => {
  if (action === 'ADD') {
    return require('./add.js')(a, b);
  }

  if (action === 'SUBTRACT') {
    return require('./subtract.js')(a, b);
  }

  throw new Error('Please provide a valid action (ADD or SUBTRACT).');
}

In 2015 a module format was added to the ECMAScript specification, which makes it the ‘official’ JavaScript module format. It’s mostly referred to as ES2015 or ES modules. This specification uses a combination of import & export.

add.js (module)

const add = () => a + b;
export default add;

index.js (consumer)

import add from './add.js';
console.log(add(1, 2));

This is just a basic example of importing and exporting, there is a lot more in the spec (and open proposals). ES Modules are (mostly) static, you define 1 or multiple imports at the top of a file and use them in the code below. If you need a dynamic CommonJS style import (e.g. require) you can use import( ).

While some browsers support