How to know what path to specify in Node for require - node.js

All:
When I use Express.js(but I believe this is more of a Node question), if I want to import some modules, I need to use require(module path).
But I am a little confused what root path should be used for each require, are they all same to the path we execute the node command?
Sometime, It works when I use require("../modelname") while sometimes require("./modelname") even I did not change the modelname.js location.
Thanks

Node documentation provides a pseudo-code algorithm for how it resolves the path for require()
To sum up:
require(X) from module at path Y
If X begins with './' or '/' or '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.json is a file, parse X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP
LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
a. Parse X/package.json, and look for "main" field.
b. let M = X + (json main field)
c. LOAD_AS_FILE(M)
2. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
4. If X/index.node is a file, load X/index.node as binary addon. STOP

If you are in a directory where you want to access modelname there are two scenarios given below
if modelname is in the same directory then you can use require("./modelname")
if calling directory is different and one level above to your modelname directory then you have to use require("../modelname").

When you do require( 'express' ), node will begin in your current folder, and step up the file tree until it locates a folder that has a package.json inside it.
Once it finds this file, it will check for a node_modules folder and look for node_modules/express. It will then follow the instructions in node_modules/express/package.json as to how to go about including the module.
If you want to require your own code that lacks a package.json, you'd do something like this.
require( './router' )
or
require( '../middleware/site-data' )
In the first example, the . refers to the folder the file doing the import is in, and will import either ./router.js or ./router/index.js, depending on which exists. In require, . is effectively translated into __dirname + '/'.
In the second example, the .. refers to the parent of the directory the importing file is in. In require, .. is effectively translated into __dirname + '/../'.
Good luck!

use webstorm tool where you have debugging facility like we have in eclipse, start your application in debug mode and put breakpoints.

Related

fs.writeFile() and fs.readFile() strange behavior

I'm writing a desktop app using electron and react. I want to store some information in a JSON file. I've tried both web-fs and browserify-fs to accomplish this, and neither is working as expected. My setup is as follows
project/app/(react files)
project/index.html
project/js/bundle.js
project/main.js
I'm using watchify to compile all the changes in the react files to the bundle.js file (which is read by index.html).
The following is ran from app.js in project/app/ (which is also where the JSON file is stored)
import * as fs from 'browserify-fs';
...
fs.writeFile('./fileData.json', data, function(err){
if(err)console.log(err);
else console.log("success");
});
'success' is always logged to the console, however the contents of the file is not updated, regardless of how I specify the path.
I've tried './fileData.json'
'/fileData.json'
__dirname + '/fileData.json' (which tells me that __dirname couldn't be found)
(absolute path to fileData.json) (which tells me that /Users could not be found)
After doing the above, if I change the writeFile to readFile and log the contents to the console, the updated file is printed. Even if I delete the fileData.json file, the file is successfully read.
This makes me believe that fs.writeFile() is writing to a different directory, not the one the process is being ran from. Despite this, I cannot find any other fileData.json files anywhere on my computer. There's a couple other weird behaviors:
When logging __filename (which should log the entire filepath), the only thing printed is "/app.js" with no leading file path.
Calling "process.cwd()" just gives me "/"
When calling fs.writeFile() with the full file path "/Users/...." I get a folder not found error
Anyone know what could be causing this behavior and how to fix it?
Edit - I also tried getting the absolute path by adding
var path = require('path')
var appDir = path.resolve('./app');
which again only gives me /app when it should be returning an absolute path
Can you confirm the same behavior when not using browserify-fs? Just use plain old fs. (Note you can do this straight from the Chrome dev tools console).
Looking at browserify-fs's page, it looks like it implements a kind of virtual file system using a dependency called level-filesystem (which uses level db). So the files you're expecting to get created aren't. They're being created within a level db database. You could probably find a level db file somewhere that has the information you're trying to write directly to the file system in it.
For simple writing/reading of a JSON file, I'd recommend https://github.com/sindresorhus/electron-config.

ENOENT no such file on Express Endpoint for readFileSync

I've been going slightly crazy trying to figure this out. I have some certs that I need to pass through to an authentication client from my api; however, the application continues to throw ENOENT exceptions even though the file clearly exists within the same directory (I've fiddled with this to make sure). I'm using readFileSync, effectively doing the following:
key: fs.readFileSync('./privateKey.pem'),
Strangely, if I run this on a standalone Node server not as a part of an api, the file is able to be found without a problem. Is there some consideration I'm not aware of when trying to use readFileSync in such a scenario?
Thanks!
In node you need to be very careful with relative file paths. The only place where I'd ever really use them is in require('./_____') statements, where ./ to mean "relative to this file". However, require is kind of a special case because it is a function that node automatically creates per-file, so it knows the path of the current file.
In general, standard functions have no way of knowing the directory containing the script that happened to call a function, so in almost all cases, ./ means relative to the current working directory (the directory you were in when you ran node <scriptname>.js). The only time that is not the case is if your script or a module you use explicitly calls process.chdir to set the working directory to something else. The correct way to reference files relative to the current script file is to explicitly use an absolute path by using __dirname + '/file.js'.

Node.js path.join removes leading period

I came home with a work project that I planned on fiddling with on my personal computer, I installed everything, using the exact same environment (Node v0.11.12), etc. Start the project, then I'm greeted with messages complaining that the config loader module cannot locate a file (that exists and is at the path exposed by the error).
Looking closer at the error, I realize that the problem is path.join(). Where
path.join('./foo/bar');
// 'foo/bar'
Which is not good. Why does path.join remove the leading period?
** Note **
The above is simply an example. The program make use of the function like
var configFile = require(path.join(modulePath, 'conf', file));
for example, where modulePath is relative to the current working directory (i.e. ./app/module/)
This is correct behavior, and is documented in the Path.join documentation:
Join all arguments together and normalize the resulting path.
It is correct because foo/bar is the normalized (canoncial) form of ./foo/bar, just as it is the normalized form of ./foo/././bar/. or foo/baz/../bar.
(Differences between require('./foo/bar') and require('foo/bar'), and any resulting problems of such, should be specifically addressed in a different question without path.join.)

Order of resolution with nodejs require module

Suppose I have all of foo.js, foo.coffee, and foo.jsonin the same directory, and I say require './foo' from another (coffeescript) file in that location, what rule governs which one will be loaded?
A short experiment (using require.resolve './foo') would seem to indicate that the javascript file wins over the other two.
Indeed, looking at require.extensions it looks like .js being mentioned there as the first item—but then, object attribute names are inherently unordered in javascript, right?, so any name added to that property could potentially re-order the entries—could that lead to another resolution order?
Just wondering, as i couldn't find any documentation. it does become relevant when you do (and maybe you shouldn't) coffee --compile route/to/directory.
.js is loaded first (this also means that it's better to use full name.json for your fixture instead of name as it could be shadowed by name.js)
From "modules" documentation:
If the exact filename is not found, then node will attempt to load the required filename with the added extension of .js, .json, and then .node.
Also, read name resolution algorithm in pseudo-code:
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
2. If X.js is a file, load X.js as JavaScript text. STOP
3. If X.node is a file, load X.node as binary addon. STOP
After (1,2,3) extensions set in require.extensions are checked in the order they a set (for CoffeScript, require("coffe-script") installs .coffee handler).
The behavior in V8 is to iterate over named properties in the order they were originally assigned, so I would expect .js to always be first.
This post references that behavior

require.js - runtime dynamic variables to build path

Is it possible to inject runtime information in to a require.js "data main" script and use to build paths? More explanation...
In my node.js app.js I dynamically find the path to the configured 'theme' like this:
var themePath = require('./conf/config.js').config.theme.full_path;
and later in the require.js data main script, I'd like to prepend this theme path when defining paths. So assuming I've set my requirejs data-main="xxx" and the following is the xxx file, I'd like to do something like the following:
require.config({
baseUrl: "/js/",
paths: {
"templates" : DYNAMIC_THEME_PATH + '/templates',
"views" : DYNAMIC_THEME_PATH + '/views'
}
});
I'm not sure 1. how I can "see" the themePath from within this require.js data main file, and 2. is this even possible?
EDIT - My solution
So the real challenge I was having was getting a runtime variable discovered on the server in to the require.js data main script. In node land, global doesn't correspond to the window on the client side (of course) because the javascript isn't in to the browser yet .. duh. So I don't see how you can get this discoverable in the client side script.
Ok, so what I WAS able to do was inject the discovered theme path in the ejs, then, dynamically load the data main script with that prepended like:
<script data-main="<%= theme_path %>/main" src="../js/libs/require-jquery.js"></script>
Of course this means I have to have the data main script in the theme directory which wasn't my initial plan; however, it does have the advantage that I can then use relative paths to load my path/to/templates path/to/views, etc. etc.
Lastly, I sort of hate when folks answer they're own questions .. so I'm going to leave this up in hopes that someone can either give me a better recommendation or better explain this and they can get the credit ;)

Resources