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

module: require relative from package root #1979

Closed
KoryNunn opened this issue Jun 15, 2015 · 23 comments
Closed

module: require relative from package root #1979

KoryNunn opened this issue Jun 15, 2015 · 23 comments
Labels
feature request Issues that request new features to be added to Node.js. module Issues and PRs related to the module subsystem.

Comments

@KoryNunn
Copy link

Hope this hasn't been raised before, i did search..

Everyone has done this:

    var thing = require('../../../../thing');

Why not add a symbol that resolves to the closest package.json?

    var thing = require('^/thing');

Doesn't have to be a ^.

@KoryNunn KoryNunn changed the title require from root. Request: require from root. Jun 15, 2015
@mscdex mscdex added module Issues and PRs related to the module subsystem. feature request Issues that request new features to be added to Node.js. labels Jun 15, 2015
@silverwind silverwind changed the title Request: require from root. Request: require closest package Jun 15, 2015
@silverwind
Copy link
Contributor

+0 from me. If we add it, I'd rather have this in a seperate method to avoid dealing with special characters.

@KoryNunn
Copy link
Author

totally ok with separate method. Can even omit the ./ then.

require.[root/self/local]('thing');

@jbergstroem
Copy link
Member

I prefer a non-magic require() -- the more obvious include path the better.

@silverwind
Copy link
Contributor

Could you clarify a bit what you want? ../../../../thing looks like you're requiring a file, not a package. I don't think we can reliably search for files easily.

As for packages, it should already work as expected and search the parent directories containing node_module folders.

@KoryNunn
Copy link
Author

requiring files. especially helpful when you have a few top-level singletons, like 'services' 'router' etc.

so in ./router/public/whatever you could just grab a service via:

var myService = require.local('services/myService');

@Trott
Copy link
Member

Trott commented Jun 15, 2015

It would seem like proof-of-concept for this could happen in user-land as a module published to npm. And, in fact, that might be the better place for it to live permanently.

Currently, io.js has nearly no awareness of package.json. See "Folders As Modules" in the Modules documentation.

So that would have to be added in just for this functionality.

I am aware of at least two projects that have a sort of "find the root of this project" logic/module in them. The first is npm. See find-prefix.js if you might be interested in using that as a model or starting point. The other is git-validate which has a findProjectRoot() function.

@silverwind silverwind changed the title Request: require closest package Request: require relative from root Jun 15, 2015
@silverwind
Copy link
Contributor

Ah, alright. Now I get what you meant. Maybe require.fromRoot would be an fitting name, if we decide to add it.

@KoryNunn
Copy link
Author

@Trott yeah I was thinking a userland module would be the best way to do it, but then it's going to be an uphill battle to get things like browserify to support it (since a userland module would be digging into the extra stuff that node require has on it).

Might be possible with a browserify transform I guess..?

also, node does know about node_modules, in which case this issue could be redefined to say, go to the closes folder that contains node_modules.

@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

Why does this have to be in core?

Unobvious require semantics for files could introduce weird bugs when one has several files with the same name in different places.

If this was really needed, there would have been a module that does that already.
If you need this — why not just make a module?

If you base on package.json location, it means that your require statements for files change their behaviour based on the presense or absense of some other files (namely package.json).

@monsanto
Copy link
Contributor

On behalf of Babel, it would be easier for our ES6 import <-> node modules interop if there was not a different require.local function. Right now we are agnostic to the format of the from string: we can assume import X from 'loc' is (roughly) var X = require('loc'). There is no way to extend this syntax for local imports except in the from string, which would bring us back to the ^ syntax that was originally suggested. On top of that, we would have to inspect this string ourselves and transpile differently depending on the format of the string.

As for the functionality itself, this is a common problem, and it would be nice to have a canonical solution to it. OTOH making a symlink isn't that big of a deal. So I guess I'm neutral.

@KoryNunn
Copy link
Author

@ChALkeR

  • File names shouldn't clash, because there is only one 'root' probably?
  • A module would probably work for non-clientside code. I'm interested in some form of standard to follow regardless of server/browser

@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

@KoryNunn What will happen if you (accidently or not) put an unrelated package.json in a subfolder?

@KoryNunn
Copy link
Author

@ChALkeR it wouldn't work. Bit of an edge case, and easy to debug, since the error would be:

Error: Cannot find module '/home/<user>/dev/packageJsonIsHere/bar'

which would tell you where the package.json is.

@Fishrock123
Copy link
Contributor

@KoryNunn may I ask why you chose ^ for this? As far as I am aware, that is not a regular path operator?

I think I would perfer less magic also, ala require.[root/self/local]('thing');.

Is there any significant disadvantages to having such functionality in an npm module?

@KoryNunn
Copy link
Author

@Fishrock123 I used ^ because it wasn't a standard path operator. Didn't want it to clash with anything else.

As above, the reason to make it a 'nodeism' and not a module, is that it would create a standard which could be followed by other implementation such as browserify.

I actually don't agree that a path symbol such as '^' is "magic" any more than '..' or '.', it'd just be new syntax.

@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

@KoryNunn That's quite common actually (I just made a quick search for package.json).

Also, if we start to speak about standards, there are ES6 modules, and I hope to see everything converted to that at some point. And AFAIK there is no such thing as package.json-relative paths in ES6 modules, so this would make the transition harder.

Also, please note that the modules API is locked atm.

Only fixes related to security, performance, or bug fixes will be accepted.
Please do not suggest API changes in this area; they will be refused.

@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

Implementing this would require unlocking the modules API.
https://iojs.org/api/documentation.html#documentation_stability_index
https://iojs.org/api/modules.html#modules_modules
Documentation states that this feature request should be rejected.

@Fishrock123
Copy link
Contributor

Implementing this would require unlocking the modules API.
https://iojs.org/api/documentation.html#documentation_stability_index
https://iojs.org/api/modules.html#modules_modules
Documentation states that this feature request should be rejected.

That isn't entirely correct per-say, but it is very likely to be, yes. module has a huge amount of edge-cases we do actually need to preserve, and touching it effects nearly everything.

@silverwind silverwind changed the title Request: require relative from root module: require relative from package root Jun 15, 2015
@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

@Fishrock123

That isn't entirely correct per-say

Why isn't it?

@cjihrig
Copy link
Contributor

cjihrig commented Jun 15, 2015

-1. This seems like something that can be done in userland. We shouldn't add more edge cases to the already locked module system.

@ChALkeR
Copy link
Member

ChALkeR commented Jun 15, 2015

While I understand why this would be useful, I'm -1 on this for the reasons that I mentioned above.

@chrisdickinson
Copy link
Contributor

@KoryNunn A browserify transform should be able to pick this style of require up, especially if it's added as a separate API or module. One thing to note about changing the require statement – any package published that relies on new behavior has an implicit hard dependency on whatever version of io.js/node that it was first published in. That means packages that use that package also inherit that implicit hard dependency. It's difficult to introduce such changes because they have the potential of fracturing the ecosystem. It's safer to write this as a module + browserify transform that way the effects are self-contained. Packages using this functionality through such a module are usable by any version of Node, too!

Closing this for now – if you write a package + transform for this functionality, let me know on this thread! I'd love to add it to a "modules solving common pain points" document that I'm working on.

@MauriceButler
Copy link
Contributor

@chrisdickinson just noticed you asked to be informed of the userland implementations as per this discussion we created rooty and for browserify rootify

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request Issues that request new features to be added to Node.js. module Issues and PRs related to the module subsystem.
Projects
None yet
Development

No branches or pull requests