简体   繁体   中英

How can I change in Rollup.js an import module of a dependency package to a local file replacing that module?

I have a JavaScript project that must be bundled using Rollup.js which depends on a package A which in turn depends on a package B:

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

Let's say that my package import a function "connect" from package A, which in turn import a "connect" function exported by the module B. Something like:

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

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

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

Since my package requires a bundled version of the package B (let's say "B.bundle.js"), how can i configure Rollup.js in order to replace for each dependency of my project requiring B (A in this case) to use my local bundled version (ie B.bundle.js, which of course exports the "connect" function too)?

When Rollup.js creates the bundled version of my project i would like to achieve something like the following:

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

Is something like this possible with Rollup or with a plugin? Sorry for the question, but I'm new to rollup and bundling in general.

We had the exact same requirement and we resolved it using @rollup/plugin-replace package.

Basically, our project uses a monorepo structure but we are not using any tools like learna or workspace for managing it. So we have two packages which are interdependent. Our ui-kit uses icons package for different icons and icons package uses the Icon component from ui-kit package. We just replaced the imports for ui-kit with local path with the following:

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

...
...

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

I solved this issue using some configuration of my package package.json and the rollup plugin @rollup/plugin-node-resolve .

In the package.json of my package I inserted the browser option that specifies how modules should be resolved when my package is used in the browser context. From the npm doc on the browser option of the package.json:

If your module is meant to be used client-side the browser field should be used instead of the main field. This is helpful to hint users that it might rely on primitives that aren't available in Node.js modules. (eg window)

So considering the example provided in the original question the npm package contains something like this:

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

This means that when mypackage is used in the context of the browser the module B import will load from the file located in "./B.bundle.js".

Now, with rollup i need to specify that the bundle i am creating is intended for browser context. The plugin that handle imports of node modules is @rollup/plugin-node-resolve . There is an option is this plugin that specify that the context is browser . From the plugin documentation about the option browser :

If true, instructs the plugin to use the browser module resolutions in package.json and adds 'browser' to exportConditions if it is not present so browser conditionals in exports are applied. If false, any browser properties in package files will be ignored. Alternatively, a value of 'browser' can be added to both the mainFields and exportConditions options, however this option takes precedence over mainFields.

So that in my rollup config file i have something like:

// 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, //<- tells to rollup to use browser module resolution
      }),
      commonjs(),
    ],
  },

The answer of @vrajpaljhala seems feasable for the purpose but imho @rollup/plugin-replace its kind of too tricky and raw approach to the problem because it involves direct replacmeent of strings surrounded by "" . We may face some very "hard to discover" errors if the package name we are going to replace is a common word that can be present as a string in the code but not in the context of an import statement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM