Given the following situation:
A Node.js express app with some routes and modules
app.js
/routes
|-user.js
|-login.js
|-e.t.c.
/modules
|-logger.js
Let's say that all the routes need the logger to do proper error handling and logging. Would it be better to include the logger in all the routes or only in app.js and then inject the logger object into the routes?
The latter would seem to be less resource heavy because the object only gets created once, but is this the case?
Related
Hi I need some help with how express handles routes.
In setting up my express app, I have something like this:
app.use(express.static('public'));
Next, I mount some api routes:
app.use('/api', myrouter);
app.get('*', function(req, res) {
res.sendFile(path.resolve('public/index.html'));
});
But, when the frontend requests data via an api route, e.g. at 'localhost:3000/api/things', I am seeing in the Express debug logs that at some point (unsure when) it actually tries to serve this request as a static file, like:
send stat "C:\myproject\public\api\things" +230ms
Even though this folder doesn't exist in 'public' and should be solely handled by my api. FYI, the handler for /api/things route is only implemented for the GET method, and does get invoked at some point.
How do I stop express server from also trying to serve api requests from the static folder?
Thanks very much.
Answering my own question... which appears to be a duplicate of this one:
`express.static()` keeps routing my files from the route
So the answer is this one: https://stackoverflow.com/a/28143812/8670745
In short, the app.use() declarations that mount your api routers should appear before the app.use() statements which tell express.static where to serve your static files from. This way, the latter acts as a catchall AFTER api route handling is done. Router engine order matters...
Your answer is misinformed, or rather you've misinterpreted the problem. Your original configuration:
app.use(express.static(__dirname + 'public'));
app.use('/api', myrouter);
Looks absolutely fine because there's no clash between the routes. The threads you've linked too aren't really the same, and I can see why moving the routes in those cases would have worked.
The only thing I'd say is your path to your static folder isn't reliable, you should really use path.join, or actually in your case you can just do express.static('public') - express will infer the folder your app is served from.
I've picked up a project from another developer, uses the typical MEAN stack with the entry point being server.js.
Now, in server.js, the module that does:
var express = require('express');
var app = express();
var passport = require('passport');
There are another 2 lines of code that look like they are doing some sort of routing but I can't figure out what it actually means:
require('./routes.js')(app, passport);
require('./apiRequest/authenticate')(app, passport);
I'm confused because it looks like require() is called from the global scope, whereas all the other routing methods are called off app, i.e app.use(). Can someone explain what the sets of parameters mean, and why are there two sets also where is require() called from, is it provided by Express?
routes.js and apiRequest/authenticate are two local (project) modules / js files that are basically required here.
express and passport are node modules/libraries that are provided from npm_modules, via node module resolution.
app is simply an express instance created by invoking the express module/default function.
The parameters passed to the required local modules (routes and authenticate) are just parameters passed to those modules (default exported function) that can be used further in those files (e.g. if you look in routes.js you will probably see that they use app.use(..., where app is given as param as well as the passport module)
To explain the syntax require('./routes.js')(app, passport); more clearly:
require - node OOB function for importing modules into the current file/module
require('./routes.js') resolves the default export from the routes.js file which in this case is a function
...(app, passport) this function (from above point) is then invoked with the provided params (which were previously defined here - i.e. imported with require)
I set up a web server using node JS and the Express module. My code is as follows :
file tree:
/src
|
+-- server.js
+-- /app
|
+-- routes.js
server.js
// set up ======================================================================
var express = require('express');
var app = express();
var mongoose = require('mongoose');
...
// configuration ===============================================================
mongoose.connect(configDB.url);
...
// routes ======================================================================
require('./app/routes.js')(app, passport);
// launch ======================================================================
app.listen(port);
routes.js
module.exports = function(app, passport) {
app.get('/some-route', function(req, res) {
// this line bugs out
var User = mongoose.model('User', userSchema);
});
};
My question:
Calling mongoose.model() in routes.js throws the following error
ReferenceError:mongoose is not defined
Why is mongoose not known in this context when I've included it in server.js, the file in which routes.js is being included? Should I require() mongoose again in routes.js? What am I missing here?
Variables defined within a module are local only to that module. They are not in the scope of other modules that you require() in with that module. That's why mongoose is not know to your routes module. The require() operation does not insert the code right into the calling module. Instead, it loads that code from disk and then inserts it into its own function and calls that function. This gives each loaded module its own independent scope. It is not inserted into the current scope.
In cases like this, you have several choices:
Require() in the mongoose module again in routes. This is generally preferred when possible because this makes the routes module more self sufficient and easier to reuse as it requires in the things it needs.
Pass in the object you want to share with the routes constructor just like you are passing in app and passport. This method is preferred when the item needed by the other module is not just the result of a simple module load. For example, app is the result of calling a constructor function so the only way for another module to use the same app instance is for you to pass it.
You can have routes call out to some other module to request information. For example, since you've already passed the app object to routes, you could put the mongoose object as either a property on the app object so it could be referenced that way or you could add a method to the app object to retrieve it via the method call.
In this case, since mongoose is just a cached module, it probably makes the most sense to just require() it in again, but any one of the three methods above would work.
The modules that are included is on a file are not visible on another file. Here you can find a list of the global objects that are available on every module that you create:
https://nodejs.org/api/globals.html
All the other objects/variables that you define within a file they are defined within the context of this file. Otherwise, this could create huge problems with variables that overwrite other variables in other files and creating a mess within a project. You can think of a file like a function that includes all your code and everything that is defined in there, is not available to the global namespace.
In your case, you have to require('mongoose') in the files that you need it, and it is built like that so that can maintain the existing connection to the database.
My node/express/passport app works fine, but when I include my client requirejs app (which resides inside the /public/js/ folder) like this in my jade template:
script(src="js/vendor/requirejs/requirejs.js", data-main="js/main")
passport calls deserializeUser multiple times.
My static folder is declared before passport is initialized in my main.js:
app.use(express.static('public'));
app.use(passport.initialize());
app.use(passport.session());
The client requirejs project is not optimized by r.js, so it has to load the needed javascript files. When the client project is optimized by r.js it works fine - no extra deserialize calls (just 1).
Is this desired behavior for passport? It's not a huge problem as it's doing this in development, but is this a solvable issue?
May be you can add a logger middleware to your application like morgan and try to correlate the deserialization occurrence to specific static file by looking at the sequence of http request logs and logs associated to the deserialization call.
I am using node.js with express for rest api and i have main file "server.ts" and i can write api routes in server.ts. But i wanna separate controller layer from server.ts even different controllers for their purpose. I have searched on google and found [link][1] for it.
[1]: http://bigspaceship.github.io/blog/2014/05/14/how-to-create-a-rest-api-with-node-dot-js/#toc_17 but i need this answer in typescript.