5

I'm new in the world of Node.js

According to this topic: What is Node.js' Connect, Express and “middleware”?
I learned that Connect was part of Express

I dug a little in the code, and I found two very interesting files :

./myProject/node_modules/express/lib/utils.js

and better :

./myProject/node_modules/express/node_modules/connect/lib/utils.js

These two files are full of useful functions and I was wondering how to invoke them correctly.

As far, in the ./myProject/app.js, that's what I do:

var express = require('express')
  , resource = require('express-resource')
  , mongoose = require('mongoose')
  , expresstUtils =
      require('./node_modules/express/lib/utils.js');
  , connectUtils =
      require('./node_modules/express/node_modules/connect/lib/utils.js');

But I found it a little clumsy, and what about my others files?

e.g., here is one of my routes:

myResources = app.resource(
                'myresources',
                require('./routes/myresources.js'));

and here is the content of myresources.js:

exports.index = function(req, res)
{
  res.render('./myresources.jade', { title: 'My Resources' });
};

exports.show = function(req, res)
{
  fonction resourceIsWellFormatted(param)
  {
    // Here is some code to determine whether the resource requested
    // match with the required format or not
    // return true if the format is ok
    // return false if not
  }

  if (resourceIsWellFormatted(req.params['myresources']))
  {
    // render the resource
  }
  else
  {
    res.send(400); // HEY! what about the nice Connect.badRequest in its utils.js?
  }
};

As you can see in the comment after the res.send(400), I ask myself if it is possible to use the badRequest function which is in the utils.js file of the Connect module.

What about the nice md5 function in the same file?

Do I have to place this hugly call at the start of my myresources.js to use them?:

var connectUtils =
      require('../node_modules/express/node_modules/connect/lib/utils.js');

or, is there a more elegant solution (even for the app.js)?

Chenmunka
  • 685
  • 4
  • 21
  • 25
Pascal Qyy
  • 4,442
  • 4
  • 31
  • 46

2 Answers2

2

the only more elegant way i came up with is (assuming express is inside your root "node_modules" folder):

require("express/node_modules/connect/lib/utils");

the node installation is on windows, node version 0.8.2


and a bit of extra information:

this way you don't need to know where you are in the path and be forced to use relative paths (./ or ../), this can be done on any file nesting level.

i put all my custom modules inside the root "node_modules" folder (i named my folder "custom_modules") and call them this way at any level of nesting:

require("custom_modules/mymodule/something")
Leonidaz
  • 236
  • 3
  • 4
  • 2
    You cannot expect this technique to be future-proof. `express@4.0.0` might completely change how it functions internally and for all you know might drop `connect` (not likely, but you get the point). And again, If you were to include `connect` (the same version used by `express`) in your project's dependencies, this technique will not work. – Gautham Badhrinathan Aug 29 '12 at 10:29
  • @GauthamBadhrinathan I don't foresee express dropping connect any time soon :) However, connect could easily change the location of their files or what is in them -- which IMHO is a much greater danger. this technique should still work even if you include connect in your project's dependencies, the path still points to express, so node.js will go to express first. from node.js documentation (File Modules) section: *Without a leading '/' or './' to indicate a file, the module is either a "core module" or is loaded from a node_modules folder.* http://nodejs.org/api/all.html#all_file_modules – Leonidaz Sep 09 '12 at 17:46
  • Yes, it would go to `express` which is either a "core module" or is in "node_modules". But if `connect` is added as a project dependency, then you wouldn't find a directory called `connect` *within* the `express/node_modules` directory. – Gautham Badhrinathan Sep 14 '12 at 13:32
  • @GauthamBadhrinathan Yes, you're right if you add connect as a dependency the location of connect would be different. However, one should be aware of what they're doing and know that if they do end up adding connect as a dependency they would have to refactor the code and change the paths that they're using in their `require()`. – Leonidaz Dec 12 '12 at 16:52
2

If you want to access connect directly, I suggest you install connect as a dependency of your project, along with express. Then you can var utils = require('connect').utils.

Linus Thiel
  • 38,647
  • 9
  • 109
  • 104
  • Install an whole framework twice, just to access some utility functions with shorter `require` does not seem more elegant… – Pascal Qyy Mar 28 '12 at 11:24
  • 2
    When you build a largish project, you will find that you have lots of duplication among the modules. E.g., I have several `mkdirp`, `async`, `eco` etc. It's not a big deal. – Linus Thiel Mar 28 '12 at 11:28
  • To respect a [DRY](http://en.wikipedia.org/wiki/Don't_repeat_yourself) "design pattern" is a big deal for me. At this point, i prefer copy/past juste the functions I need in my own utils module. But it's no very DRY, nor elegant… – Pascal Qyy Mar 28 '12 at 12:39
  • What can I say. Managing dependencies is hard. Node's dependency resolution is the best I've worked with, and I gladly keep around a few copies of each library if that means that my code works, testing works, and deploying works. I don't see the point of arguing about elegance with you though -- I'm just here to help! – Linus Thiel Mar 28 '12 at 15:44
  • so, calling `connectUtils = require('./node_modules/express/node_modules/connect/lib/utils.js');` seems to be sufficient regarding "_duplicate whole framework_" or "_copy/paste_" alteratives. My question was just: **is there a more elegant solution?** … – Pascal Qyy Mar 29 '12 at 06:28
  • var connnect = require('connect'), utils = connect.utils; essentially you are accessing connect's utils module, so connect.utils is a pretty nice way of saying that. i doubt any overhead this causes is anything more than negligable, and even if there is any, it will happen only once on application start. – alzclarke May 03 '12 at 01:17
  • It's hard to say whether this violates DRY or not but it is fundamental to the way node handles modules. You're introducing an explicit dependency on a module (rather than an indirect one through a second module) and the way to communicate that to node is to add it to your package.json and put in an explicit require('connect'). If you're wondering why node does things this way, you should read about npm. It is a very conscious choice. – Waylon Flinn Jul 20 '12 at 22:24
  • @LinusGThiel You should know that when you add a dependency (say `connect@0.4.3`) explicitly to a project and that particular dependency (same version) is also used by another dependency in your project (say `express@3.0.0`), then npm keeps only one copy of `connect@0.4.3` (at `node_modules` of your project dir). Furthermore, when you `require` modules, a particular module is only initialized once. When you `require` again, you merely get the reference to the initialized module. – Gautham Badhrinathan Aug 28 '12 at 17:17
  • @GauthamBadhrinathan: That's not true. If you do what you describe, there will be one connect in `./node_modules/connect` and another (potentially another version) in `.node_modules/express/node_modules/connect`. This is very much by design and IMO one of the best parts of node.js. – Linus Thiel Aug 28 '12 at 17:45
  • 3
    @LinusGThiel If they are different versions, yes. But if there are the same version, then you end up with just one as `/node_modules/connect`. I can't seem to find the article that explains this. Anyways see [An example dependencies list](https://gist.github.com/3509829/7c29788d8f33840fff57d7b33dd6cc227f28d04a). As you can see there, there is no `connect` or `cookie` under `express` even though they are dependencies. – Gautham Badhrinathan Aug 29 '12 at 10:22
  • @GauthamBadhrinathan: You are correct! I did not know this. Good to know! – Linus Thiel Aug 29 '12 at 10:53