Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin support for modifying external dependency references #350

Closed
icambron opened this issue Dec 7, 2015 · 10 comments
Closed

Plugin support for modifying external dependency references #350

icambron opened this issue Dec 7, 2015 · 10 comments

Comments

@icambron
Copy link

icambron commented Dec 7, 2015

I believe this is a feature request, but if there's a way to do it now, I'd love to know about it. I'm happy to do the work here if a PR would be accepted, but I'd appreciate any pointers on how/where to do it. Here's my scenario:

I have some tests written in ES6 and broken down into ES6 modules. They reference my library because they're testing it, so like:

import {functionToTest} from 'mylib'

For the sake of the example, let's say I'm compiling this to CJS-style modules so that I can run the tests in Node. My library code is rolled up and babeled to, say, [project root]/dist/cjs/mylib.js. AFAIK, I have these choices:

  1. Roll up the library with the test
  2. Leave it as an external dependency
  3. Leave it as external dependency and change the imports in the tests to use all use a path relative to the destination directory of the rolled up tests

1 is what I do now using a resolveId() plugin to track down the library code in the dist dir, and it's not ideal; I'd like my tests to reference my library externally. 2. doesn't work because it builds in a require() call that can't actually be satisfied; my library's code is built to a subdirectory, not installed into node_modules. 3 is gross and brittle, because I have to go change a zillion imports if I change where stuff goes.

So what I'd like to have is another plugin entry point that let's me rewrite the unresolved external dependency, so turning

var myLib = require('mylib');

into

var myLib = require('../dist/cjs/mylib');

I propose it looks something like this:

resolveExternal: (importee, importer) => 
   //return a different string or the original importee

and that's what gets stuffed into the require (or AMD define or ES6 import or whatever). Does this make sense as a proposal? Is it a good idea?

@Victorystick
Copy link
Contributor

@icambron Now I see what you're getting at! You want to make the generated external module id something different from that in the sources?

@icambron
Copy link
Author

icambron commented Dec 8, 2015

@Victorystick correct! Sorry I didn't make that clear.

@Rich-Harris
Copy link
Contributor

As I see it there's two possible approaches:

  1. Add an option to rewrite import paths when we finalise the bundle. That does feel a bit weird and specific, and I think it's better to resist new options until there's no doubt that they're necessary, but on the other hand perhaps this isn't a totally unusual requirement?
  2. Add a plugin hook that allows the generated bundle to be replaced, so you could make arbitrary changes like replacing /['"]mylib['"]/g with "../dist/cjs/mylib". Would potentially solve a broader class of problems, but feels a tiny bit brittle in this situation. We'd also need to be careful about sourcemaps.

Thoughts welcome!

@icambron
Copy link
Author

icambron commented Apr 3, 2016

I'm in favor of 1. I think 2 is way too brittle and it just seems icky to operate on the text directly like that. I suspect this is not an unusual case. I'm not doing anything weird at all; I'm just trying to allow some tests to consume my module. Hard not to conclude this is going to come up a lot.

@Rich-Harris
Copy link
Contributor

Sorry for the loooooong delay in responding. For anyone who ends up here: we actually ended up implementing both 1 and 2:

  1. You can use the paths option to replace module IDs with paths in the generated bundle
  2. Plugins can export a transformBundle hook

@icambron
Copy link
Author

Woo, thanks!

@javadbat
Copy link

javadbat commented Mar 5, 2019

Sorry for the loooooong delay in responding. For anyone who ends up here: we actually ended up implementing both 1 and 2:

  1. You can use the paths option to replace module IDs with paths in the generated bundle
  2. Plugins can export a transformBundle hook

please update links

@lukastaegert
Copy link
Member

As a matter of fact I have just prepared a PR that will give you another option, much closer to what was originally proposed: #2734

The reason I implemented it was because I needed an object form of resolveId to support providing additional meta information about modules (such as package side-effects) and adding another hook seemed wasteful to me. As a side-effect, once #2734 is merged you will be able to mark dependencies as external and resolve them to a different dependency at the same time.

@lukastaegert
Copy link
Member

About the missing links, this is the paths option:
https://rollupjs.org/guide/en#output-paths

transformBundle is now renderChunk:
https://rollupjs.org/guide/en#renderchunk

@gogoend
Copy link

gogoend commented Feb 13, 2024

https://rollupjs.org/configuration-options/#output-paths

Is it possible to config output-paths to dynamic paths?
The path of the external module in my project is known until runtime rether than build time.

like this

	external: ['d3'],
	output: {
		file: 'bundle.js',
		format: 'amd',
		paths: {
			// d3: 'https://d3js.org/d3.v4.min'
			d3: '"eval(`false ? \'path/to/external/module/1\' : \'path/to/external/module/2\'`)"' // the eval statement will run at runtime.
		}
	}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants