Developing an easily optimized library using rollup to remove unnecessary code branches

I'm currently in the process of developing a component library using rollup and Vue with the goal of making it tree shakable for others who import it. The configuration setup is outlined below:

Here's a snippet 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 complete 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 straightforward project structure with an index.js file and two 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 include export default undefined; somehow, any application importing my library won't be able to find any exports. Strange.


Now, when I integrate my library into another app by importing red-components-with-rollup like this:

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

and inspect the bundle in my app, I notice that the source code of Button.vue is also included in the bundle; it hasn't been stripped out as dead code.

What could be the issue here?

Answer №1

What happens to the ES format build outcome? Does it result in a single file or multiple files similar to your source files?

It seems like with your Rollup options, everything is bundled into one file which may be why tree-shaking isn't working.

If you want your ES build to output multiple files, make the following changes:

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

Change it to:

{
  format: "es",
  // Specify a directory instead of a file for multiple outputs
  dir: 'dist/esm'
  // Keep each module in a separate file
  preserveModules: true,
  // Optionally remove unnecessary path from the source
  preserveModulesRoot: 'lib',
}

Update your package.json to point module to the new build file, something like

"module": "dist/esm/index.js"
.

Answer №2

There's an insightful discussion on tree shaking pitfalls in this article that you may find intriguing.

In addition, it's essential to ensure that your build tooling for the consumer app supports pure ES modules and has tree shaking capabilities. It's important to avoid any 'side-effecty' actions in your exported files that could confuse Rollup.

As a precaution, consider offering direct imports for each component along with a main index.js file that exports them all. This way, you provide the option for those who are concerned about including unused code ie -

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Check to see if a key exists within the entire JSON using jQuery

I'm struggling with checking if a specific key is contained in my JSON data array. I want to add a class or perform an action if the key is present, otherwise do something else. I've tried using inArray and hasOwnProperty but can't seem to g ...

What steps should I take to resolve this issue? ERROR TypeError: Unable to access property 'user' of null object

Is there a way to resolve the error I'm encountering in my project? The error message is: ERROR TypeError: null is not an object (evaluating 'userdata.user'). Using React Native Expo, I am facing this issue after logging into my app and navi ...

The curious case of Node.JS: The mysterious behaviour of await not waiting

I am currently utilizing a lambda function within AWS to perform certain tasks, and it is essential for the function to retrieve some data from the AWS SSM resource in order to carry out its operations effectively. However, I am encountering difficulties i ...

What is the best way to display only the current != wanted lines when using "npm outdated"?

Whenever I input npm outdated, it shows a similar output like this: Package Current Wanted Latest Location columnify 1.1.0 1.1.0 1.2.1 /usr/local/lib > npm > columnify cmd-shim 1.1.2 1.1.2 2.0.0 /usr/local/lib & ...

Is it possible to export multiple named exports in a single set without changing how variables are called?

In my constants file I have: export const CONSTANT1 = 'CONSTANT1'; export const CONSTANT2 = 'CONSTANT2'; export const CONSTANT3 = 'CONSTANT3'; export const CONSTANT4 = 'CONSTANT4'; export const CONSTANT5 = 'CONS ...

How can a debounce function be customized to work on multiple instances of the same Vue.js component autonomously?

I am encountering an issue with two Vue components that each have a "save to disk" call triggered on every change of data. These components utilize a mixin to load the data, and they save into separate files in order to function independently (each trigger ...

Escape a "for" loop from within a callback function in Node.js

My objective with the code snippet below is to exit FOR LOOP B and continue with FOR LOOP A by utilizing a callback function. for(var a of arrA) { // ... // ... for(var b of arrB) { // ... // ... PartService.getPart(a ...

Is there a way to encase each v-if statement in my Vue code with a transition effect?

Writing the code for transitions can be quite laborious. <transition name="fade"> <div v-if="condition"> </div> </transition> Is there a simpler way to automatically wrap each v-if with a transition? ...

The Javascript code I wrote is unable to detect the array element that was initially defined in Python

Trying to launch a new browser window through Selenium using driver.execute_script("window.open('');") However, the goal is to open a specific link provided by the user. For this purpose, extracted the link input from an array and inc ...

Retrieve the value when clicking on a tab panel using Vue.js

<div class="col-lg-6"> <a-tabs tabPosition="right"> <a-tab-pane v-for="config in listData" :tab="config.name" :key="config._id"> < ...

Delaying the activation of the code until the image upload is complete

I'm having trouble synchronizing code to upload an image using a vue composable, wait for the upload to finish, and then store the Firebase storage URL into a database. Despite getting the URL, the success code fires before the upload is complete. My ...

Exploring the Force-Directed Graph Demo on bl.ocks.org

I don't have much expertise in javascript, jquery, or json. My objective is to create a graph using the force-directed graph example from bl.ock.us. 1) I wrote a python script to generate the necessary json data. 2) I noticed others were us ...

Changing the color of a text box when it is disabled can be achieved through JavaScript

I'm facing an issue with the formatting of my HTML elements. Specifically, I have 2 combo boxes and one text box in which all 3 are disabled. However, when they are disabled, the background color of the text box does not match that of the combo boxes. ...

What exactly happens behind the scenes when utilizing the React hook useEffect()? Is an effect set up with useEffect able to halt the main thread

According to the documentation for the useEffect() hook in React, it states that: "Effects scheduled with useEffect don’t prevent the browser from updating the screen." Insight Unlike componentDidMount or componentDidUpdate, effects set with ...

detecting key presses on documents using javascript

I'm having trouble capturing document-level key press events on a webpage. I've tried using the following code: $(document).bind('keydown', 'a', keyevent_cb); It works fine in IE, but it's not consistent in Firefox. I&a ...

Creating a smooth entrance effect in VueJS using CSS transitions is a breeze

Even though it seems simple, I am struggling to get it to work properly. My goal is to have the existing elements in my list shift to make room for a new element added, and then have the new element appear with a smooth fade transition. I have tried to im ...

Leveraging React Native to position a view absolutely in the center of the screen without obstructing any other components

How can I center an image inside a view in the middle of the screen using position: "absolute"? The issue is that the view takes up 100% of the width and height of the screen, causing all components underneath it (such as input fields and buttons ...

Node.js module mishap

In the package.json file I'm working with, these are the content of my dependencies: "devDependencies": { "chai": "^4.1.2", ... "truffle": "4.1.3" } A new NodeJS script called getWeb3Version.js was created: let web3 = require("web3" ...

Guide for implementing async/await in conjunction with the eval() function within JavaScript

I'm currently using the eval function to evaluate strings and adding await to it to ensure all values are obtained, but unfortunately the await is not functioning correctly. Here is a snippet of my code: if (matchCard.card.status != "notstarted& ...

UI-router issue: UI view and links not functioning properly

Recently, I decided to implement ui-router for Angular in my project. After adding the following code snippet to my app module within the app.js file: angular .module("ngClassifieds", ['ngMaterial', 'ui.router']) .config(function($md ...