Is there a way in Rollup.js to substitute a dependency package's imported module with a local file?

I am currently working on a JavaScript project that needs to be bundled using Rollup.js. The project depends on package A, which in turn relies on package B:

"mypackage" ---import--> "A" ----import----> "B"

My package imports a function "connect" from package A, which in turn imports a "connect" function exported by module B. Here's an example of the code structure:

//mypackage index.js
import { connect } from 'A'

//A index.js
import { connect } from 'B'

//B index.js
export function connect() {}

As my package requires a bundled version of package B (let's call it "B.bundle.js"), I need to configure Rollup.js to replace every dependency in my project that requires B (which is A in this case) with the local bundled version (i.e. B.bundle.js, exporting the "connect" function). How can I achieve this?

When Rollup.js creates the bundled version of my project, I want the result to look something like this:

//A index.js after Rollup processing
import { connect } from './src/B.bundle.js'

Is it possible to achieve this with Rollup or using a plugin? I apologize for my lack of experience with rollup and bundling in general.

Answer №1

I managed to resolve the issue by tweaking the configuration in my package's package.json and utilizing the rollup plugin @rollup/plugin-node-resolve.

Within the package.json file of my package, I included the browser option which dictates how modules should be resolved when the package is used in a browser environment. As per the npm documentation on the browser option in package.json:

If your module is designed for client-side usage, the browser field should be utilized instead of the main field. This can help indicate to users that it might rely on features not available in Node.js modules (e.g., window).

Thus, using the example provided in the initial question, the npm package might contain something like this:

{
  "name": "mypackage",
  "version": "1.5.1",
  "description": "A brand new package",
  "main": "index.js",
  "browser": {
    "B": "./B.bundle.js"
  },
}

This setup ensures that when "mypackage" is utilized within a browser context, the module B import will load from the specified file location at "./B.bundle.js".

Furthermore, when using rollup, I needed to specify that the bundle I was creating was intended for the browser environment. The plugin responsible for handling node module imports is @rollup/plugin-node-resolve. Within this plugin, there is an option to specify the context as browser. According to the plugin documentation regarding the browser option:

If true, directs the plugin to utilize browser module resolutions in package.json and includes 'browser' in exportConditions if absent to apply browser conditionals in exports. If false, any browser properties in package files are disregarded. Alternatively, a value of 'browser' can be added to both the mainFields and exportConditions options, with this option taking precedence over mainFields.

For my rollup configuration file, I had something along these lines:

// rollup.config.js

import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";
import nodePolyfills from "rollup-plugin-node-polyfills";

export default {
  input: "index.js",
  output: {
    file: "dist/mypackage.bundle.js",
    format: "es",
  },
  plugins: [
    nodePolyfills(),
    resolve({
      browser: true, //<- instructs rollup to use browser module resolution
    }),
    commonjs(),
  ],
},

While @vrajpaljhala's solution may appear viable, in my opinion, using @rollup/plugin-replace could be too complex and risky as it involves directly replacing strings enclosed in "". This approach could lead to challenging-to-discover errors if the package name being replaced is a common word found as a string in the code rather than solely in an import statement.

Answer №2

In a similar situation, we had a specific requirement that we were able to address by utilizing the @rollup/plugin-replace package.

Our project follows a monorepo structure but we opted not to use tools like learna or workspace for its management. This led to a scenario where two of our packages had dependencies on each other. For example, the ui-kit package relied on the icons package for various icon functionalities, while the icons package used the Icon component from the ui-kit package. To resolve this issue, we decided to modify the imports for the ui-kit by specifying a local path as shown below:

import replace from '@rollup/plugin-replace';

...
...

export default {
  ...
  ...
  plugins: [
    replace({
      'ui-kit': JSON.stringify('../../../../src/components/Icon'),
      delimiters: ['"', '"'],
    }),
  ]
  ...
  ...
}

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

Are there any methods to implement object-oriented programming in JavaScript?

The concept of prototype-based object-oriented programming in JavaScript is intriguing, but there are many scenarios where the need for class-based object creation arises. Consider a vector drawing application, where the workspace begins empty and you can ...

Issue with AngularJS: Dynamically generated tab does not become active or selected

Exploring an AngularJS code snippet that generates tabs upon clicking the new button. However, there's an issue where the newly created tab doesn't become active or selected automatically after creation. It seems like the one before the last tab ...

How can you delay the return of a function until after another asynchronous call has finished executing?

Currently, I am working on implementing route authentication in my project. To achieve this, I have decided to store the authenticated status in a context so that other React components can check whether a user is logged in or not. Below is the relevant co ...

Update the class of the appropriate navigation tab when the corresponding div is scrolled into view

After reading similar questions and doing some research on scrollspy, I don't think it will provide the functionality I need. It seems to only support bootstrap style highlighting. If there is more to it that I'm not aware of, please inform me! ...

Send a file using ajax with the help of JavaScript and PHP

Currently, I am looking to implement a method for uploading files using Ajax and JavaScript/PHP without having the page refresh. My initial thought is to use Ajax to send the file using xmlhttp.send(file) and then retrieve it in the PHP script, but I' ...

Issues related to ng-model within a dropdown list

Currently, I am facing an issue with retrieving the selected value from a select element using ng-model. Even though the value is displayed correctly on the application page, it remains at the initial value in the app controller. Despite my efforts to find ...

Error in React Material UI: 'theme' variable is not defined - no-undef

In the process of developing a basic React application with material-ui, I am incorporating MuiThemeProvider and ThemeProvider for themes. App.js import React from 'react'; import { createMuiTheme, MuiThemeProvider } from '@material-ui/co ...

Ways to identify when the socket has been opened by the client?

When utilizing socket.io on the client browser side, is there a way to identify when the socket connection has been successfully opened? I am also interested in monitoring other standard messages such as errors and disconnections. In comparison to the Web ...

Why include HTML in our webpack bundle?

Hello there, I am currently working on an angular 2 app using this starter pack as a base. I am trying to understand what our build process will entail. I have noticed that when running: npm run build:prod npm run server:prod The HTML content is incl ...

Mastering the correct usage of the submitHandler method in the jQuery validation plugin

Here is a snippet of documentation from the jQuery validation plugin: "Use submitHandler to execute some code before submitting the form, without triggering the validation again." submitHandler: function(form) { $.ajax({ type: 'POST&apos ...

Is there a way to dynamically load a file on scroll using JavaScript specifically on the element <ngx-monaco-diff-editor>?

I've been attempting this task for over a week now in Angular without success. Would someone be able to provide guidance? The onContainerScroll() function isn't being triggered, and I'm considering using JavaScript instead. How can I achiev ...

Error: Trying to destroy a property that does not exist

I need assistance with deleting a product in my NODE JS application, and here is the relevant code snippet: exports.postEditProduct = (req, res, next) => { // working fine so far const prodId = req.body.productId; const updatedTitle = req.body.title ...

Issue with NPM and Vite: Unable to locate "vue" in Framework7 project

I'm running into an unusual issue while working on a simple Framework7 project with vue. After setting up a Framework7 Vue project using the command: framework7 create --ui and installing dependencies with npm i, I encountered the following problem: ...

Exploring the Power of GraphQL Args in Mutation Operations

Currently, I am in the process of developing a blog service using express and apollo-express in conjunction with mongodb (mongoose). While implementing mutation queries, I have encountered difficulties in accessing the arguments of a mutation query. I am ...

Tips for utilizing the onClick function in jQuery on an element nested within a div that was dynamically added using jQuery beforehand

I have added some elements inside a div with the class .display_noti like this: $(document).ready(function(){ setTimeout(done,200); }); function done() { setTimeout(updates, 200); // Call updates in 200ms } function updates(){ $.getJSON("notificatio ...

The onclick function is malfunctioning when attempting to use the Windows Phone app in Visual Studio 2015

web development <div class="align_center"> <div class="btn EmployeeloginBtn" **onclick="new Employee().connect()**>CONNECT</div> </div> Employee.js: var Employee = function() { var self = this; self.connect = fu ...

There appears to be an issue with Javascript's ability to handle JSON API requests

I'm currently working on a webpage that utilizes the openweathermap API to showcase the user's city and local temperature. Unfortunately, I'm encountering an issue where the JSON API is not being processed and nothing is happening. Despite r ...

Utilizing JavaScript in AJAX Responses

Can I include JavaScript in an AJAX response and run it, or should I only use JSON or plain HTML for a more elegant solution? I'm trying to figure out the best way to handle AJAX requests that involve inserting HTML or running JavaScript based on user ...

When an array object is modified in Vue, it will automatically trigger the get method to validate any

One of the challenges I am facing is related to a button component that has a specific structure: <template> <button class="o-chip border-radius" :class="{ 'background-color-blue': theValue.isSelected, ...

Feeling a bit lost when trying to kickstart a project in node.js and utilizing npm install

Greetings, I am currently in the process of learning and consider myself a beginner. Recently, I explored the chat tutorial from the get-started section on socket.io. As I continue to expand my knowledge by exploring other resources, one question remains ...