remap/alias module dependencies #2943

Closed
millermedeiros opened this Issue Nov 13, 2012 · 11 comments

Projects

None yet

8 participants

@millermedeiros

One feature that I really feel that is missing in npm is the ability to rename/remap module dependencies so our app code doesn't need to reference the module by its canonical name.

This would reduce the need of namespaces (#798) since you can simply remap your complex name to a simpler one. Quoting @unscriptable:

npm+node_modules won't let us change the name once the package is installed. For instance, if we're forced to name our project "cujojs-poly" in npm (and "poly" everywhere else), then code that uses poly.js has to be written differently if it's going to be retrieved with npm. require("poly/array"); vs require("cujojs-poly/array");
That's not a maintainable solution.
Source: #798 (comment)

I would suggest something like the RequireJS paths config:

// package.json ---
{
    "name" : "example",
    "version" : "0.1.0",
    "dependencies" : {
        "cujojs-poly" : "0.1.x",
        "lodash" : "0.9.x"
    },
    "paths" : {
        "underscore" : "lodash",
        "poly" : "cujojs-poly"
    }
}
// index.js ---
var _ = require('underscore');
// > "node_modules/lodash/index.js"
var arr = require('poly/array');
// > "node_modules/cujojs-poly/array.js"
// OR "node_modules/cujojs-poly/array/index.js"

PS: Of course this feature shouldn't be abused, it is just for the cases where you might need to swap some old dependency and/or want to keep consistency between multiple environments.

@unscriptable

+1, except paths is loaded with footguns. I recommend packages, which are a bit less prone to user errors.

@jrburke
jrburke commented Nov 13, 2012

This is actually what map config is for in amd loaders. If I were to do it over maybe call it alias. Anyway, just background from amd loaders. The change above would require modifying node for it to work completely, so expect extremely low odds on happening.

@isaacs
Member
isaacs commented Nov 14, 2012

This will never happen in npm.

npm leverages node's module loading architecture. It does things in a very predictable way that makes it easy to figure out where things are located by reading the code.

If your code does require('underscore'), and it's actually pulling in lodash rather than underscore, then that's a lie. You can do var underscore = require('lodash') if you like, and that's fine. Anyone reading your source can tell what's going on.

What you're asking for is to make it harder to understand what your code is actually doing from reading the code. There is absolutely no need for this, and it's a terrible idea.

extremely low odds on happening.

Indeed. As long as I have any say in the matter, those odds are roughly zero.

@isaacs isaacs closed this Nov 14, 2012
@brianc
brianc commented Nov 15, 2012

👍 to @isaacs.

@brianc
brianc commented Nov 15, 2012

I guess the point is sometimes it's hard to have an "over my dead body" opinion on something. Especially from the (admittedly very little) I know about isaacs, he seems very level headed, humble, and truly interested in the success of node much more than his own success. So I was just trying to offer my support. I dunno...I feel like saying 'no' to features is sometimes harder, but the almost fanatical commitment to simplicity and minimalism within node-core is something that's kept the community around it so white-hot. Node is like that extremely reactive 1st period element that can and will combine with anything because it's own electron field is so sparse and ready to form a covalent bond with all it's modules. Or something... 😄

Wasn't trying to troll!

@jdalton
jdalton commented Nov 15, 2012

@brianc I like your glass half full view. I can dig it 🍻

@brianc
brianc commented Nov 15, 2012

🍻 💃

@millermedeiros

I just added this feature request since it could be a potential solution for the whole namespace discussion. If you don't like the absurdly-long-name-that-makes-no-sense you could just swap it to something else. So far I didn't need this feature but the cujojs-poly is a good example of what will happen. write once, run everywhere ain't going to happen anytime soon, the tools aren't flexible enough. 😞

@unscriptable unscriptable referenced this issue in eclipse/vert.x Dec 12, 2012
Closed

Provide setImmediate #448

@pajtai
pajtai commented Jun 1, 2014

After using requirejs in the browser , this is the one big missing feature of npm.

I understand the argument of predictability, but the cost of this predictability is to kill the ability of large scale dir tree refactoring. If there are aliases then the actual paths only have to be refactored in one place.... Without aliases, the paths must be refactored everywhere.... which in dynamic languages is painful to the point of killing dir tree refactors.

@creynders

👍 for aliasing.

If your code does require('underscore'), and it's actually pulling in lodash rather than underscore, then that's a lie.

@isaacs No more so than having a property called model which is injected with an instance of UserModel. I.e. that's what dependency injection is all about.

TBH I don't quite get that someone would favour changing dozens, maybe hundreds of call sites over a single central place where this could be configured in one line. That, to me, is the definition of absurdity.
Could this please be reconsidered? It's at popular demand as well.

@isaacs isaacs locked and limited conversation to collaborators Sep 15, 2014
@isaacs
Member
isaacs commented Sep 15, 2014

This isn't going to be reconsidered, sorry.

If you want to replace all instances of a module, you can use a perl one-liner pretty easily.

Or, you can do echo 'module.exports=require("lodash")' > node_modules/underscore/index.js or something like that, and add it as a bundled dependency, if you REALLY REALLY MUST lie about what it is you're actually loading.

Or, if you must do this programmatically, and cannot be bothered to edit and bundle dep files, you can do something like this in JS:

var lodash = require('lodash') // prime cache
require.cache[require.resolve('underscore')] = require.cache[require.resolve('lodash')]
require('assert').equal(require('underscore'), require('lodash'))

npm won't help you or encourage this kind of sloppiness, however.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.