Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a tree shakable library with rollup

I am trying to create a component library wie rollup and Vue that can be tree shakable when others import it. My setup goes as follows:

Relevant excerpt from package.json

{
  "name": "red-components-with-rollup",
  "version": "1.0.0",
  "sideEffects": false,
  "main": "dist/lib.cjs.js",
  "module": "dist/lib.esm.js",
  "browser": "dist/lib.umd.js",
  "scripts": {
    "build": "rollup -c",
    "dev": "rollup -c -w"
  },
  "devDependencies": {
    /* ... */
}

And this is my entire rollup.config.js

import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";
import vue from "rollup-plugin-vue";
import pkg from "./package.json";

export default {
  input: "lib/index.js",
  output: [
    {
      file: pkg.browser,
      format: "umd",
      name: "red-components"
    },
    { file: pkg.main, format: "cjs" },
    { file: pkg.module, format: "es" }
  ],
  plugins: [resolve(), commonjs(), vue()]
};

I have a fairly simple project structure with an index.js file and 2 Vue components:

root
 ∟ lib
    ∟ index.js
    ∟ components
       ∟ Anchor.vue
       ∟ Button.vue
 ∟ package.json
 ∟ rollup.config.js

My index.js imports the Vue files and exports them:

export { default as Anchor } from "./components/Anchor.vue";
export { default as Button } from "./components/Button.vue";

export default undefined;

If I don't do export default undefined; somehow any app importing my library cannot find any exports. Weird.


Now when I create another app and I import red-components-with-rollup like so:

import { Anchor } from "red-components-with-rollup";

and I open the bundle from my app, I will also find the source code of the Button.vue in my bundle, it has not been eliminated as dead code.

What am I doing wrong?

like image 324
Lukas Avatar asked Jun 26 '19 14:06

Lukas


People also ask

What is tree shaking with rollup?

Tree-shaking is the process of analyzing the code files that are required to run your application and then including only code that is actually used by your application.

Does CommonJS support tree shaking?

In webpack, tree shaking works with both ECMAScript modules (ESM) and CommonJS, but it does not work with Asynchronous Module Definition (AMD) or Universal Module Definition (UMD).

Does create react app use tree shaking?

If you're using modern tooling, such as webpack, create-react-app and similars, you already have tree shaking set up. Tree shaking or dead code elimination means that unused modules will not be included in the bundle during the build process.


1 Answers

What is the build result of the ES format? Is it a single file or multiples, similar to your sources?

Considering your Rollup options, I’m guessing it bundles everything into a single file, which is most probably the reason it isn’t able to tree-shake it.

To keep your ES build into multiple files, you should change:

{ file: pkg.module, format: "es" }

Into:

{
  format: "es",
  // Use a directory instead of a file as it will output multiple
  dir: 'dist/esm'
  // Keep a separate file for each module
  preserveModules: true,
  // Optionally strip useless path from source
  preserveModulesRoot: 'lib',
}

You’ll need to update your package.json to point module to the new build file, something like "module": "dist/esm/index.js".

like image 118
LeBen Avatar answered Oct 16 '22 00:10

LeBen