On Wed, Jan 23, 2013 at 9:13 AM, Jacob Groundwater <[email protected]> wrote: > Is `index.js` considered a non-preferred method of doing package imports? I > really like it, but arguing a stable feature is pointless. I'm just curious > what the reasons were for including it, and what has changed since? > > FOR SCIENCE!
index.js predates packages by quite a long time. It was the first "load a packagey folder thing as if it was a single module" feature, dating back to the 0.1.x days. It's not terrible. But personally I prefer a main script in package.json, since you can name it something more appropriate than "index.js", and somewhat like named functions, it makes the debugging experience a bit nicer. On Wed, Jan 23, 2013 at 6:18 AM, Austin William Wright <[email protected]> wrote: >> "Objectively correct"? Wow. > If you have a problem with my logic, the correct thing to do would be > describe what's actually wrong. Fair enough. There are two major problems with your argument. The first is a gross category error. You are asserting that the semantics of the require() function can be in any sense "objectively correct", when in fact we are discussing complicated trade-offs involving subjective values. Second, you are asserting that "correctness" is defined by adherence to a spec that has nothing to do with Node, and never did. > If you ignore the semantics of what > operations like require() actually *mean* then you're going to run into > problems, or stagnate growth. Where have you been the last 3 years? "Stagnating growth" isn't a problem we have. We have the problems that come from *not* stagnating growth. > So yes, there's an "objectively correct" way to do things. And you MUST NOT > assume that the filesystem is the only way someone would want to dereference > a module. I don't assume that. But it IS the only way that someone is capable of dereferencing a Node module. Look at the code. That's how it works. If you want your modules to live somewhere else, mount it with fuse. Apart from the buildin modules bundled in the binary, Node only loads modules using the fs. > But this response isn't unusual to see when people can't actually attack > logic. Ad hominem. > The cost is the value of the next best alternative that must be given up. > What's being given up? A few extra CPU cycles, worst case? That can't be it, The cost is time spent debugging programs you didn't write. That is the cost I was referring to, not CPU cycles. (Unnecessary stat() calls at startup are not ideal, but they're also not particularly costly.) In the normal case, you have three types of things: - Builtin module: require('fs') - Package main: require('request') - Local module: require('./mine.js') Package mains and builtins are similar in their appearance, and when you're working with your program, they're actually somewhat similar in how you tend to think of them, as well. They're a thing "outside" the current program that it depends on. This similarity in appearance is still a bit annoying, but changing it would be overly destabilizing. The fourth case, is depending on a local module within a file, and that's what we're talking about here. So, say that the file is at node_modules/foo/lib/utils/bar.js. Right now, you can do require('foo/lib/utils/bar.js'). It's pretty clear what file you're pulling out: it's lib/util/bar.js from the foo package. If we add directories.lib then foo/lib/utils/bar.js could become require('foo/bar.js'). What is the advantage of this? What is the cost? The advantage is that you can export more things from your package slightly more easily. There's a feature designed explicitly for that, so the API communicates that such a thing is a good idea. (Most in the node community are of the opinion that it's *not* a good idea!) Another advantage is that you can have shorter strings in your require() function. But you can also have that by just putting files in the root of the foo package. That is a much simpler solution, and simpler solutions are to be preferred unless they come along with a cost that outweighs the value of their simplicity. What is the cost of putting files in the root of your package? Clutter in your project folder. But is that clutter a bad thing, necessarily, and exactly how bad is it? The clutter is a motivation to build a more elegant module. The API is communicating that such an approach is ill-advised. (And this reflects the feelings of the node community.) The cost of directories.lib is that it's an extra step in figuring out how node programs work. Consider a module baz that depends on foo. In baz, there is the line `var Bar = require('foo/bar.js')`. I am using baz, and debugging an issue that seems to stem from this Bar thing. So, I want to look up its implementation. I type `npm explore foo` to go into that folder, or `npm edit foo` to open it up in my editor. Now what? Which file should I edit? There's a package.json here, and a lib folder. No bar.js. In lib, there's a folder called "exports" and a folder called "utils" and a folder called "browser" and a folder called "ringo". Each have a file called "bar.js" in them. Now I have to open up package.json, and understand it. (God help me if you're using "overlays", another feature that we have flat out refused.) It gets much much worse if you use the "modules" feature of package.json. Now it's not just a folder, but an arbitrary mapping of module IDs to filenames. The "mapping" feature makes it so that I can't even reliably read your code, since require("request") might actually be something entirely different from the "request" module. It may seem like I'm painting a bleak picture. I'm not. I'm actually describing a real-world situation that I personally encountered trying to build a real product for real customers at Joyent, back when npm supported this feature you guys want to revive. Supporting the "main" field is as far as we go. Why "main", but not "directories.lib" or "modules" or "mapping", especially when we already have "index.js" support? Well, having 25 files named "index.js" is not very helpful in the debugger, and most packages were already using the "main" field when we started putting node_modules/package awareness into the node module loader. Only a few were using modules or directories.lib, and they didn't have much traction already. The API that provides a specific interface for "export one thing" communicates that the correct way to build programs is with modules that do one thing. This is widely acknowledged in the node community as a best practice. Because of this, the experience of looking up a single "main" module is much less crazy-making in practice, especially since it's often the only .js file in the package. > the current Node.js implementation currently has to synchronously stat() for > package.json, which should have been done away with long ago. Why? Because sync IO is "icky"? It's only icky if it prevents you from servicing requests. At start-up time, it's actually much faster, and gets you to a running program sooner. The solution is quite easy in practice: don't do require() after start time, or suffer the consequences. > As mentioned, require() may be extended to load things other than files. > Take json, or coffeescript, for example. Those aren't examples of "things other than files". JSON and coffeescript are files. > I think you suggested at one point > that it'd be cool for require() to *load files off the Internet*. That's not > a good idea, anymore? The node team has rejected several proposals to do exactly that, and I've been convinced that it's a bad idea, or at least, would require a massive change to how Node works. Just because I think something would be neat doesn't mean it's actually a good idea. I AM a hypocrite, after all. >> > Cross-platform compatibility is a highly desirable feature. >> >> Cool story. > > Then help do something about it. "Cool story" is not a way of communicating agreement. It is a way of dismissing a non sequitur. "Desirability" is not an innate property of features. "Desire" is a feeling a person has. Something is "desirable" if anyone desires it. But really, the people in the Node community who care about being compatible with pinf-js and ringo are a rounding error. So, desirable to whom? Who feels this "desire" sensation? Not enough people to matter to me, I'm afraid, and certainly not enough to make the benefits outweigh the costs. Seriously, if you are so convinced, prove it. Fork node, add this feature, and then wait for the kudos to roll in. Or better yet, go get Meteor and Vert.x to be compatible with Node, and let the CommonJS experiment rest in peace. -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en
