NodeJS, Nodeunit and require

Hi

I have a couple of possibly related problems running tests and apps in NodeJS.

First, I've set up NodeJS (I think) and I can happily click on the "otherfile" link in this line

require("otherfile");

to jump to another of my source files. BUT, I cannot click on the "subfolder/otherfile" in this line to go to one of my source files that's in a subfolder

require("subfolder/otherfile");

This seems like an error?


Separately, if I try to run my code, I have to set the NODE_PATH environment variable in the run configuration. This isn't too bad - I also have to do this at the command line. There doesn't seem to be any way to set this for a nodeunit test configuration, so I can't run tests that require any other files, other than by setting NODE_PATH before starting webstorm. Is this right?

- Dave

9 comments
Comment actions Permalink

Hi Dave,

Well, you can not click on the "a/a.js", but you can click on the "./a/a.js".
Evaluating "require('a/a.js')" expression also should fail. See http://nodejs.org/docs/latest/api/modules.html#modules_file_modules :

Without a leading '/' or './' to indicate a file, the module is either a "core module" or is loaded from a 
node_modules
folder.

 
Do you still have problems with nodeunit? Its Run Configuration has "Nodeunit module" parameter.
If you still have problems please provide the version of your IDE and the version fo NodeJS plugin installed.

Thanks,
Sergey

Attachment(s):
nodeunit-run-configuration.png
0
Comment actions Permalink

Hi Sergey,

thanks for the response. I'm sorry I wasn't clear enough before. The point in both cases is really that WebStorm doesn't deal well with the NODE_PATH variable.

On the topic of the require links: we have the NODE_PATH environment variable set. If you look again at the nodejs doc page you linked to, there's a section titled "Loading from the global folders". It's a bit ambiguous, but my reading of this is that I should be able to do require("subfolder/otherfile"); and it should search relative to the folders in NODE_PATH. That is certainly how node actually behaves. This is much more convenient for us, as using require paths relative to NODE_PATH means that we don't have to edit the require statements inside a file each time we move it to a new folder.


Also, I did try out the require("./subfolder/otherfile") style. Clicking "otherfile" does work. However, if I have inside foo.js

var Thing = require("./subfolder/otherfile").Thing;

and then inside otherfile.js I put

module.exports.Thing = {};

I get an "unresolved variable Thing" error in foo.js, so that's not working exactly right. However, fixing that doesn't really help me: I would really like NODE_PATH to be respected. I have my NODE_PATH directories set up in the Project settings/directories tab as content roots but this doesn't help.

On the other question about Node Unit, the point is again that I can't specify NODE_PATH in the Nodeunit configuration. I can in a "Node JS" run configuration, because there's an "environment variables" field, but there's no such field in the Nodeunit configuration. I can work around this by launching WebStorm from a command line in which I've already set NODE_PATH, so actually this doesn't other me as much as the first problem.

Regards,

- Dave
0
Comment actions Permalink

Thanks, Dave. I see your point.
It seems we need to support NODE_PATH. I think it will be a single global setting (project level). Of course you will be able to change NODE_PATH in a Run Configuration in a old fashion, but these changes won't be taken into account in a code analysis.
As a side question, did you consider moving all dependent modules inside project root (and get rid of NODE_PATH)? See http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/ .

0
Comment actions Permalink

Not sure that's quite relevant is it? That post is all about the use of npm, which is not how people generally install the components of their app - it's more for third party libraries.

As it happens we do install all our npm modules locally: in fact reinstalling them is part of our teamcity builds, and as we run more than one agent per server, we don't have a lot of choice :). But that's fine and I much prefer local installs.

- Dave

0
Comment actions Permalink

Dave, I am not sure it's possible for you to get rid of NODE_PATH environment variable.
Well, as for me I can't say I like NODE_PATH very much because it adds "implicit" search paths. So a new developer can't quickly understand why an application can not find a module or why application finds a wrong module version.

See http://nodejs.org/docs/latest/api/modules.html#modules_loading_from_the_global_folders 

These are mostly for historic reasons. You are highly encouraged to place your dependencies locally in

node_modules
folders. They will be loaded faster, and more reliably.



Could you please provide more info about teamcity build? AFAIK teamcity checkouts whole project into a directory, so all application dependencies should be checked out too.

0
Comment actions Permalink

Sergey

that doc is quite ambiguous. However,

1. You seem to be advocating putting the application code in the node_modules folder. The node_modules is for external modules that you depend on. I don't believe the authors of node.js expect you to put your application in there.

2. I think your comment about "implicit" paths is slightly misguided. We specify the route of our source tree as NODE_PATH. For example, we have for various reasons a folder "config" containing a folder "app", and another root folder called "model". I personally think if you're reading source code inside config/app, then reading require('../../model/Thing") is less obvious than require("model/Thing"). But whatever.

3. Team city: we don't have all application dependencies checked into our source tree: we prefer not to check in other peoples' binaries, and we treat the npm modules on which we depend as binaries. So, we refetch the npm modules we depend on from github each time we build the app. The benefit we get from this is that we can change version in a heartbeat - most of the active modules tend to update frequently, and we try to follow fairly close to the head. Our entire external dependencies configuration is stored in one file.

- Dave

0
Comment actions Permalink

Hi Dave,

See my answers below

1. You seem to be advocating putting the application code in the node_modules folder. The node_modules is for external modules that you depend on. I don't believe the authors of node.js expect you to put your application in there.

2. I think your comment about "implicit" paths is slightly misguided. We specify the route of our source tree as NODE_PATH. For example, we have for various reasons a folder "config" containing a folder "app", and another root folder called "model". I personally think if you're reading source code inside config/app, then reading require('../../model/Thing") is less obvious than require("model/Thing"). But whatever.

Actually I'm advocating putting only external dependencies in the node_modules folder.
Now I see you use NODE_PATH environment variable to make "require" statements from your application code more obvious.
Thank you for the clarification.

3. Team city: we don't have all application dependencies checked into our source tree: we prefer not to check in other peoples' binaries, and we treat the npm modules on which we depend as binaries. So, we refetch the npm modules we depend on from github each time we build the app. The benefit we get from this is that we can change version in a heartbeat - most of the active modules tend to update frequently, and we try to follow fairly close to the head. Our entire external dependencies configuration is stored in one file.

So first you checkout your application source tree and then you run "npm install" command to fetch all external dependencies. External dependencies are fetched into root "node_modules" folder (${APPLICATION_ROOT}/node_modules I mean).
Am I correct?

It seems you don't have to list application's external dependencies in NODE_PATH environemnt variable, because these modules should be successfully found if they are installed in ${APPLICATION_ROOT}/node_modules.
So the only advantage of using NODE_PATH is easy reading require statements from your application code.
Am I correct?

Thanks,
Sergey

0
Comment actions Permalink

Yes, I think that's correct.

- Dave

0
Comment actions Permalink

To add to the discussion: NODE_PATH is also relevenat when you're running external tools. For example: If I try to run a yeoman, it is unable to use any of the other global modules (namely the generators).

0

Please sign in to leave a comment.