Skip to content

🌳 A Rollup plugin that automatically annotates your module as tree shakeable.

License

Notifications You must be signed in to change notification settings

TomerAberbach/rollup-plugin-tree-shakeable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rollup-plugin-tree-shakeable

A Rollup plugin that automatically annotates your module as tree shakeable.

Install

$ npm i rollup-plugin-tree-shakeable

Usage

import treeShakeable from 'rollup-plugin-tree-shakeable'

export default {
  input: `src/index.js`,
  output: {
    dir: `output`,
    format: `esm`,
  },
  plugins: [treeShakeable()],
}

Why?

Imagine you have code similar to this:

src/index.js:

const withLogging =
  fn =>
  (...args) => {
    console.log(`Started call!`)
    try {
      return fn(...args)
    } finally {
      console.log(`Finished call!`)
    }
  }

export const f1 = withLogging(/* ... */)
export const f2 = withLogging(/* ... */)
export const f3 = withLogging(/* ... */)
// ...

You might expect that if a user of your package writes import { f1 } from 'your-package', then bundlers will tree shake and omit f1, f2, etc. from the final bundle. Unfortunately, bundlers will generally include all of your package's code in this case (yes, even if you set "sideEffects": false in your package.json) because withLogging is called at the "top-level" of your package and the bundler cannot easily tell the call is side-effect free. There are many other code patterns that cause the same issue.

This plugin solves the problem by automatically adding @__PURE__ annotations to all top-level expressions in your code that prevent tree-shaking, with the assumption that your package is actually pure, but bundlers need a little convincing of that.

For example, for the code above, running it through this plugin would result in the following code:

const withLogging =
  fn =>
  (...args) => {
    console.log(`Started call!`)
    try {
      return fn(...args)
    } finally {
      console.log(`Finished call!`)
    }
  }

export const f1 = /* @__PURE__*/ withLogging(/* ... */)
export const f2 = /* @__PURE__*/ withLogging(/* ... */)
export const f3 = /* @__PURE__*/ withLogging(/* ... */)
// ...

And if a user of your package writes import { f1 } from 'your-package', then bundlers will tree shake and strip out all functions other than f1 from the final bundle.

Caution

Only use this plugin if your package is actually tree-shakeable, meaning that each export would still function correctly if all the other exports were stripped out.

This plugin does not give your package that property. It only convinces bundlers that this is the case.

Contributing

Stars are always welcome!

For bugs and feature requests, please create an issue.

For pull requests, please read the contributing guidelines.

License

Apache License 2.0

This is not an official Google product.