Making nodejs "require" path-independent? - node.js

I write a fairly complicated node.js project, and the need to write the relative path in the "require" is driving me insane and is error prune.
Is there any way to avoid stuff like this
logger = require('../../modules/logger');
and be path-independent without turning every module into a full blown npm module?

I often use an "app symlink" where I create a symlink at node_modules/app that points to ../app. Then in my code I can require modules without relative paths: require('app/logger'). It avoids lots of ../../.. paths and having to change them when you move a file around. However, since it relies on symlinks and Windows does not support symlinks, it won't work on Windows. Thus I only use it in apps I know only need to work on posix systems.

Depending on how your directory structure is laid out for your project, it might be best to pass things like your logger to your other modules from the main app (and farther from there).
var logger = require('./helpers/logger');
var someModule = require ('./controllers/someModule')({ logger: logger });
Passing other things that way help too, like the db connection (or connection pool). Again, depends on how you have your project laid out.

Related

Refactor multiple, similar requires (using Browserify)

I've got a very crude implementation working:
var screens = {
a: require('./../react_components/screens/a.jsx'),
b: require('./../react_components/screens/b.jsx'),
c: require('./../react_components/screens/c.jsx'),
d: require('./../react_components/screens/d.jsx'),
e: require('./../react_components/screens/e.jsx')
};
Which works fine, however, I'd like to make it a little more scalable, so that when I change a filename, or add a new file to the /screens folder, I don't really have to keep updating this list of require statements.
I'm using Browserify, so I do have a build step I can hook into if need be (this will be ran in the browser)
So for node/commonjs itself there are modules such as requireindex that will automate this kind of thing. However, the fact that these approaches determine the dependencies at runtime by looking at the filesystem defeats browserify's static analysis so I'm not aware of any of them that are browserify-compatible. Therefore, I'd suggest a code generation route where you use a module such as glob to discover the files you want to export, but then write out a full .js file with the exports all statically coded, and point browserify at that file, which you can regenerate every time during your build step.

Avoiding require(../../../..) relative paths with grunt mocha

When unit testing, I tend to have a directory called test at the top of my project structure, with the directory structure mimicking the source code that is to be tested. However, these directories can get quite deep, for example
app/src/js/models/User.js
with perhaps a test in
test/app/src/js/models/User.js.
Now, when I want to include the User.js module, I use require('../../../../../app/src/js/models/Users.js') which is very cumbersome.
Ideally, I would like to use require('/app/src/js/models/User.js') or perhaps even require('User.js').
Is this possible? I am using grunt-mocha-test, but I think the question is a more general one.
There are multiple options you could use. Your best bet would probably be to use some npm module, for example this one. Search the npm registory for require, there are tons of options so choose whichever suits your needs.
Alternatively, you could write some helper function that does something similar.
If you were looking for some native way (built-in to Node.js) to achieve this, sadly there are none. You will have to use either a custom function or an npm module to do this in some nice, reusable way.

Typescript - Further Exploration into "require" and paths

I had resigned myself to the fact that every require statement in Typescript had to be relative to the file you were typing in, but I recently discovered an application that does this differently and it confuses me. I was hoping someone with enough skill could explain how this is working to me.
The application in question is the new Raven DB HTML5 Studio, which uses typescript, you can find the whole application here:
RavenDB HTML5 Studio
When browsing its source code, I came across something interesting... if you go and look at many of the files; In specific the one I am looking at... app/viewmodels/deleteItems.ts, it has a reference at the top that reads..
import document = require("models/document");
but models/document isn't a path relative to deleteItems.ts, but this works. Can someone explain how this is happening? I'm linking you RIGHT to the exact files I'm talking about. This kind of behavior is littered all over this application.
app/viewmodels/deleteItem.ts
app/models/document.ts
This is exactly the kind of behavior I really wanted to try and emulate in my own code, since trying to keep all of the paths relative to the file I'm working in is a headache, but this program seems to be completely free of that requirement.
This doesn't necessarily involve RavenDB, but I am tagging it anyway, because perhaps someone who has read over the Raven repository will understand it and be able to answer.
Update
I am trying to mimic this behavior in my own code, and not finding any success. I am sorry if I seem outright stupid, but this is all really confusing me. Here is what my structure looks like; My repository is private, so I cannot really just link to it.
app_content
scripts
home
controls
models
editors
utils
UserControls.ts
UserMapping.ts
UserElements.ts
ui
lib
jquery
jquery.js
jquery.validate.js
jquery.ui.js
kendo
kendo.all.js
kendo.aspnetmvc.js
// other libraries
Alright, that's a general feel for my folder layout. All typescript files are under the /home folder so that I can prevent github from saving their compiled javascript and locking that.
So then, in the file UserControls.ts, it looks like this right now...
import userElements = require('./UserElements');
import userMapping = require('./UserMapping');
export class UserControls {
// code
}
No matter what combinations I have tried, this is the only format/syntax that doesn't throw errors in Visual Studio. But from what I see in the RavenDB project, I should very much be able to declare it like ...
import userElements = require('utils/UserElements');
import userMapping = require('utils/UserMapping');
export class UserControls {
// some code
}
No matter what combinations I have tried, this is the only format/syntax that doesn't throw errors in Visual Studio. But from what I see in the RavenDB project, I should very much be able to declare it like ...
That is because they are using a drandalJS configuration to tell it how to resolve the file path. (see https://github.com/ayende/ravendb/blob/New3/Raven.Studio.Html5/App/main.js)
There isn't a similar configuration (basePath) for TypeScript at the moment. Your best option is to use relative paths as you've already noticed.
PS: an old but still relevant video that shows you how requirejs config works and relevance when using TypeScript https://www.youtube.com/watch?v=4AGQpv0MKsA&hd=1
The TypeScript compiler's module resolution algorithm is essentially undocumented, unfortunately. It tries to "split the difference" between AMD and CommonJS's module resolution rules, so it's somewhat hard to reason about.
What you're seeing here is an attempt to mimic CommonJS's "walk up the tree" resolution rule. When in the path C:\a\b\c\d resolving x, first C:\a\b\c\d\x is tried, then C:\a\b\c\x, then C:\a\b\x, and so on until it hits the root folder and gives up.

Where do I put modular logic?

I'm using Node and Express and I have a very beginner question. In fact it's so basic that I'm having trouble coming up with a title for it. I'm writing a modular piece of logic. It involves a few javascript files and I'd like to keep them together in one directory. When I person goes to my web app, this code is to be accessed from routes/index.js. I want to have something like
var foo = require('???/logic');
and then when somebody loads the page I will call
foo.getBar();
and then assign what it returns to a variable used in the jade template
So my questions are 1. Where should I put my directory of modular code? node_modules? and 2. Does this, generally, sound like the right way to design an express app?
Choose from the structure below based on the amount of code we are talking about.
A: single CommonJS module in a single .js file
You can export functions, constructor functions, properties
if you have 30 properties exported or more than X lines of code (for me X is 300ish, for others they are OK with 500ish), graduate to the next option
B: CommonJS module directory consisting of a my-module/index.js and other supporting .js files
other modules can require this with require('./my-module') and not know or care whether my-module is 1 .js file or many in a directory
Use this variant as your logic grows
loose coupling. High cohesion.
C: Put your logic in it's own npm module
This makes it shareable with the community and across your internal projects as well
The better you get at this and more comfortable with the process and tools, the more likely you are to skip A and B and just make standalone npm modules

require() in large, multi-file Node projects

I'm working on a large Node project. Naturally, I want to break this into multiple source files. There are many modules from the standard lib that I use in a majority of my source files, and there are also quite a few of my own files that I want to use almost everywhere.
I've been making this work by including a huge require block at the beginning of each source file, but this feels awfully redundant. Is there a better way to do this? Or is this an intended consequence of Node's admirable module system?
You can use a container module to load a series of modules. For example, given the following project structure:
lib/
index.js
module1.js
module2.js
main.js
You can have index.js import the other modules in the library.
# index.js
module.exports.module1 = require('./module1');
module.exports.module2 = require('./module2');
Then main.js need only import a single module:
# main.js
var lib = require('./lib');
lib.module1.doSomething();
lib.module2.doSomethingElse();
This technique can be expanded, reducing redundant imports.
I'd say generally that a require block is better practice than using global in Node.
You need to remember that requires are cached so when you put them in all of your code modules, you will always get the same instance not a new one each time.
Doing it this way ensures that you get the appropriate code with the expected name spaces exactly where you want it whereas using global will include things you don't need. Doing it the Node way with require will also tend to make your code slightly more portable.
Well, a couple of things, here.
First, if so many of your files are requiring the same libraries over and over again, you might want to step back and determine if you're really breaking your code up in the proper way. Perhaps there's a better organization where certain libraries are only needed by subsets of your source files?
Second, remember that the global object is shared between all of your required files in your Node.js app. Your "root" source file, say index.js, can do things like global.fs = require('fs'); and then it's accessible from all of your various files. This would eliminate the need to require a file full of requires. (In Node.js, you have to explicitly state that you're accessing a global variable by prepending global., unlike in the browser.)
This can be a good idea for CRUD-type Express apps where you have lots of code for controllers that are all almost the same but have to be slightly different for each view and you just want to split them apart not for any particular organization structure, but just to make it easier to debug (error in this file, not that file). If the structure of the app is more complex than that, take the usual warnings against global variables to heart before using that trick.
Require more than one file without absolute path through require-file-directory.
1- Can require more than one file in single statement.
2- Can require files with only their name.
Visit for solution: https://www.npmjs.com/package/require-file-directory

Resources