Dynamically generate Express routes fails in production environment - node.js

I've seen a lot of folks dynaimcally generating all their routes in the thier routes/index.js like so:
require("fs").readdirSync("./routes", 'utf8').forEach(function(file) {
if (file != 'index.js' && file != '.DS_Store') {
require("./"+file);
}
});
This works fine in development but not in production. If I remove this and add the routes manually it works fine. Any Ideas?
Here's my error if you think that would help:
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
Error: ENOENT, No such file or directory './routes'
at Object.readdirSync (fs.js:376:18)
at Object.<anonymous> (/app/routes/index.js:4:15)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
at Module.load (module.js:334:31)
at Function._load (module.js:293:12)
at require (module.js:346:19)
at Object.<anonymous> (/app/server.js:50:14)
at Module._compile (module.js:402:26)
at Object..js (module.js:408:10)
Process died with exit code 1. Restarting...

As Mark Bessey says in his answer, you are resolving the routes directory from your current directory -- not relative to where your main script lives. You should probably use __dirname. From the docs:
The name of the directory that the currently executing script resides in.
fs.readdirSync(path.join(__dirname, "routes"))
Also, you don't need to pass 'utf8'. Also, be very careful using any Sync functions in your code -- generally, it's ok in the top level scope, before the server starts accepting requests, so it should be ok in this case.

It seems likely that in production, the current directory is not getting set to the parent of your "routes" directory. How are you launching your app in production? What output do you get from
console.log(process.cwd());

Related

Expressjs change context where the server executes the app from

I'd like to know if it's possible to change the context from where the Express server is serving from, to avoid issues in the import/require files in the App that is served.
I'm serving from [root]/server.js, this file checks for the process.env.NODE_ENV and then requires a file in let's say ./dist/ENVIRONMENT/server.js
if (['staging', 'production'].indexOf(process.env.NODE_ENV) > -1) {
require('./dist/' + process.env.NODE_ENV + '/server.js')
} else {
require('babel-register')
require('./server.dev.js')
}
The files that are served are triggering an error related with the import/require locations that fails for the reason explained in the previous paragraph
Error: Cannot find module '../../../../xxxxx'
Why am I doing this? I'm transpiling the server source code for non development (that runs with babel) and then copied to the distribution directory. I understand that I can have tasks to rename and move this accordingly during deployment, that also solves the problem, but I'd like to learn or understand if we're able to change the context where the Express server, serves from!
From the top of my head, I guess I'll have to solve it through something like (which I'll be testing):
var dist = path.resolve(__dirname, '../../')
app.use(express.static(dist))
Which I attempted, but failed, same error:
Error: Cannot find module '../../../../config'
at Function.Module._resolveFilename (module.js:485:15)
at Function.Module._load (module.js:437:25)
at Module.require (module.js:513:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/Users/xxxx/www/projectFoobar/dist/staging/lib/services/foobarService/index.js:13:15)
at Module._compile (module.js:569:30)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:503:32)
at tryModuleLoad (module.js:466:12)
at Function.Module._load (module.js:458:3)
The config file happens to be in the [root] directory.
** OK just realised that using import/export is a bad practice
https://nodesource.com/blog/es-modules-and-node-js-hard-choices/

how can add a new view / route into express?

I'm new at this, I'm trying to absorb as much as possible.
I am using this template https://github.com/primaryobjects/Node.js-Bootstrap-Starter-Template
Okay, all right till here, but when I try to add a new page, it returns me the following error:
C:\server\node_modules\express\lib\router\route.js:196
throw new Error(msg);
^
Error: Route.get() requires callback functions but got a [object Undefined]
at Route.(anonymous function) [as get] (C:\server\node_modules\express\lib\r
outer\route.js:196:15)
at EventEmitter.app.(anonymous function) (C:\server\node_modules\express\lib
\application.js:481:19)
at Object.<anonymous> (C:\server\app.js:31:5)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Function.Module.runMain (module.js:501:10)
at startup (node.js:129:16)
at node.js:814:3
The aim would be to answer me a new page at the following address:
http://localhost:3000/ask?america=
The steps I followed were:
Create a view and a path
/views/ask.jade
extends layout
block content
div.container
h1 ASK
2n
/routes/ask.js
exports.ask= function(req, res){
res.render('ask');
};
3r
app.js
app.get('/ask', routes.ask);
But when I try to start "node app" returns me the error mentioned above.
Where am I mistaken?
Have you tried requiring specifically your routes/ask.js file? I'm pretty certain when using
require('folder')
require looks directly for an index file and uses that index file which I believe may mean that your routes/ask.js file might actually not be getting "required" by the app.
So
var askRoutes = require('./routes/ask')
...
...
app.get('/', routes),
app.get('/ask', askRoutes)
To modularize your code you could utilize your routes/index.js file as a routes module load file, where you load your route modules (like routes/ask.js) into your index file so you won't get bogged down by having a ton of required route modules in your app.js file. Just the index.js file would be required.
Can you try the followings :
use the default route first : app.get('/', routes.index); and then put your code after app.get('/ask', routes.ask);
if it doesn't work, put instead of res.render('ask'); the minimal return res.send('some json');

Node.js TypeError: object is not a function

I'm trying to run Mike Wilson's book sample app, but receiving the following error:
pcassiano#...:~/socialnet$ sudo node app.js
/home/pcassiano/socialnet/app.js:60
require('./routes/' + routeName)(app, models);
^
TypeError: object is not a function
at /home/pcassiano/socialnet/app.js:60:35
at Array.forEach (native)
at Object.<anonymous> (/home/pcassiano/socialnet/app.js:57:26)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Module.runMain (module.js:492:10)
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
i'm running the latest code from the book's repo.
what should i do in order to run this sample app properly?
thanks in advance.
You likely have .js files in the routes directory that do not export a function.
app.js is calling require on all files in the routes directory and then calling them as a function. So if any of those files do not follow the general pattern below you'll get the error you're seeing:
module.exports = function(app, models) {
// Add this file's routes using app.get, etc. calls.
...
};
The error reports that the value of require('./routes/' + routeName) is not a function. So you have only one real possible source of the problem.
If './routes/'+routeName doesn't exist, node should throw an error (in v0.8.16 at least), so that isn't it. So the most obvious one is that the module being loaded doesn't export a function (as the error suggests).
You should run console.log('routeName: ', routeName) right before the require statement that is on line 60 of app.js and try running it again. Then, after finding the value of routeName, look in the file it's trying to open. Odds are either module.exports is either exporting an object (or an array, string etc), or is not set at all.
If you're adding routes in the routes folder, take care to follow the same exporting style as the author, namely module.exports = function(app, models) {...}

NODE_PATH is being ignored or not working

I'm trying to run my node app on a new server and am having some issues with the NODE_PATH environment variable. The app works fine on my local machine (OSX Lion) but not on the server (Redhat linux). When starting my app with node app.js from within my project directory /development/nodeproject, I get the following error :
Error: Cannot find module 'mod/core/models/Category'
at Function._resolveFilename (module.js:334:11)
at Function._load (module.js:279:25)
at Module.require (module.js:357:17)
at require (module.js:368:17)
at /development/nodeproject/app.js:57:5
at Object.<anonymous> (/development/nodeproject/app.js:258:1)
at Module._compile (module.js:432:26)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
mod/core/models/Category is the first require() in my app.js and looks like this: var Category = require('mod/core/models/Category'). So apparently node is not looking for modules in my project directory.
I'm not sure why though, because I made the following changes (that are working just fine on my local machine).
added export NODE_PATH=/development/nodeproject to my ~/.bash_profile
ran source ~/.bash_profile
if I run env I see NODE_PATH=/development/nodeproject listed there
in my app.js if I console log process.env.NODE_PATH I get /development/framework (should this output an array instead of a string?)
Other information that might be relevant:
I'm on node v0.6.7
I'm doing all of this as root (sudo su -)
At this point I'm not sure what else I can do. Any help would be greatly appreciated.
NODE_PATH used for modules, not for solutions files.
Try
module.paths.push("/development/nodeproject", "one/more/path");
before any require() call. And you really should use a relative require like require('./mod/core/models/Category') for files in your nodeproject directory
The functionality you are looking for was removed. Use the node_modules directory or a relative require like require('./mod/core/models/Category').
This answer has more info: NODE_PATH error with node.js while attempting to setup jsctags for vim

couchapp dosen't work! (node.couchapp.js)

I have a problem: couchapp has been installed by me, but it works not too well.
I try to repeat shown here: http://vimeo.com/26147136 but:
master#master:~/WebDev/superblog$ couchapp push app.js http://localhost:5984/superblog
The "sys" module is now called "util". It should have a similar interface.
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
Error: require.paths is removed. Use node_modules folders, or the
NODE_PATH environment variable instead.
at Function. (module.js:376:11)
at Object. (/home/master/.node_libraries/couchapp#9999.0.0-LINK-b6f5885b/index.js:4:21)
at Module._compile (module.js:432:26)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
at Module.require (module.js:357:17)
at require (module.js:368:17)
at Object. (/home/master/WebDev/superblog/app.js:1:79)
at Module._compile (module.js:432:26)
I don't know as it to correct. Help me, please!
You can also use Kanso to push apps written to the node.couchapp.js API: http://kan.so/docs/Kanso_for_node.couchapp.js_and_reupholster_developers
This does not help you directly, but you can use Reupholster until node.couchapp.js runs for you.
http://reupholster.iriscouch.com/reupholster/_design/app/index.html
(Disclaimer: it is my project)
The format of the project is pretty much the same as node.couchapp.js, so you can get your couchapp development going, and switch back to the node version at any point. Reupholster is just a little easier to get running.
Hope that helps.

Resources