Get access to Express mountpath from inside a module - javascript

In an attempt to build a truly modular express app (one that can run stand alone or as a part of another app) I need to find out the cleanest way to find the mount path from inside the subapp. For a short example, lets say that there are two files: main.js and subapp.js
main.js
var express = require('express');
var app = express();
var localApp = express();
var subapp = require('./subapp');
app.use('/foo', subapp);
app.use('/bar', localApp);
console.log(localApp.mountpath); // yes, this prints '/bar' as expected
...
subapp.js
var express = require('express');
var app = express();
var truePath = app.mountpath; // I wish this would point to '/foo', but instead points to '/'
...
module.exports = app;
What is the best way (as in cleanest) to find the mountpath from inside the module? I'm doing this trying to solve this problem: Access to mountpath variable from inside a template using express in a non hardwired way.
As shown in the example, tried already with app.mountpath without success

As answered by alsotang, this is actually a problem of execution sequence, but it can be solved in what I think is a clean way. There is an event that is fired after the module is mounted, so you can do:
var truePath = = "/";
app.on('mount', function (parent) {
truePath = app.mountpath;
});
Where in real life truePath could be app.locals.truePath, so it can be accessed from inside the views.

eh..It's a problem of execution sequence.
In your subapp.js, the app.mountpath statement is before module.exports = app.
But only you export the app, then the app be mounted, then it would be set the mountpath property.
so, you should retrieve mountpath after the app be mounted by outer express.
My suggestion are two:
set the mountpath in your subapp.js. And outer express read this property.
perhaps you think 1 is not truly modular. so you can alternatively define a config file. and both main.js and subapp.js read mountpath from the config.

Try req.baseUrl:
app.js
var express = require('express');
var app = express();
var foo = require('./foo');
app.use('/foo', foo);
app.listen(3000);
foo.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
console.log(req.baseUrl); // '/foo'
res.send('foo');
});
module.exports = router;

Related

Can someone explain how i can use module.exports this way

I am trying to understand what is going on when I use module.exports with a variable in a model view controller type project. I just do not understand what the book means by using it in this way
var express = require("./config/express.js");
var app = express();
app.listen(3000);
module.exports = app; // my problem is right here what is it doing
console.log("Server running at http://localhost:3000/");
my config/ express file is also here
var express = require("express");
module.exports = function()
{
var app = express();
require("../app/routes/index.server.routes.js")(app);
return app;
}
The first example is exporting the Express app directly and the second example is exporting a function that returns the Express app.
This means that in the first example, require(...) will return app. In the second example, you would need to do require(...)() to have app returned.

Achieve best performance when passing variables through different node.js modules/files

In a node application it's common that you start loading some modules like this:
var express = require('express')
, app = express()
, mongodb = require('mongodb')
, http = require('http');
Now, let's say you have a routes.js file which looks like this:
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('homepage');
});
// other routes
};
So when you call that routes.js file, you pass the app var:
require('./routes')(app);
My question is: what is happening there? Is there resource consumption when passing the app variable to the routes module? I know that node.js caches modules, but I would like to know how that affects variables passed between them and I wonder if the following approach is efficient:
Let's start loading some modules, but let's do in a different way:
var _ = {};
_.express = require('express');
_.app = _.express();
_.mongodb = require('mongodb');
_.http = require('http');
Routes.js:
module.exports = function(_) {
_.app.get('/', function(req, res) {
res.render('homepage');
});
// other routes
};
Call to routes.js:
require('./routes')(_);
Obviously the _ variable will be a large one, but it will include anything you may need in any module. So I wonder if the size of the passed variable affects performance, in which case it would be just stupid to pass more data than needed.
I seek for achieving the best achievable performance in my applications while I try to simplify things when writing code, so any advice that may help with this, or any explanation about how this works behind the scenes in node.js will be appreciated.
Thanks in advance.
See here.
tl;dr: objects are passed by reference, not by value. So you are not expanding your memory consumption when you pass the same object multiple times to multiple modules.

ExpressJS require

I was reading over the Express.JS 4.x API and was curious about how they set this up. Here's my understanding of what is happening:
In this sample code in the Express.JS 4.x API, the express module is imported and assigned to a variable express. That variable is then used to call the express constructor and is assigned to the variable app.
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send('hello world');
});
app.listen(3000);
Is there a difference if the express module is directly assigned to app or is the assignment above just for readability? As follows:
var app = require('express')();
A node module can return a constructor that is both a constructor AND also has properties (since functions are objects that can have properties).
Your first method allows you to access any other properties or methods that the constructor might have. The second method does not permit that since it doesn't retain a reference to the constructor.
In the ExpressJS documentation, I do see some items that are referenced via the express object such as:
var express = require('express');
var app = express();
var router = express.Router();
router.get('/', function (req, res, next) {
next();
});
app.use(router);
and
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
If you don't need to retain a reference to the constructor in order to access these other methods on it, then there is no difference between your two options as they execute the same code. Your second one just doesn't retain a reference to an intermediate step that can be used later to access other things.

Access Express app within Express Router

I have an ExpressJS application that uses several routers. Here is the basic form of the main app that ties everything together.
var express = require('express');
var routes = require('./routes/index');
var app = express();
app.set('someKey', someObj);
app.use('/', routes);
module.exports = app;
I have removed most of the code for brevity.
In that ./routes/index.js file I have defined a Express Router in the form:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('index', { title: 'Express Test' });
});
module.exports = router;
I have attempted to use the following to access "somekey" from inside the router:
var app = require('../app');
var foo = app.get('somekey');
This crashes and burns with the runtime informing me that there is no such method get for app (further investigation yields that app is just a default Object).
I assume I am overlooking something that is completely obvious.
I plan to be passing a single knexjs object to each of the routers that deal with database calls. In the code's current state it is duplicated across each of the routers. I'd like to have it defined once in the main app and then be used by all of the routers such that if a change is made in the main app it is reflected across the routers.
When you require the app that way, you are not exactly referring to the app object you defined in your app.js. Instead, you are asking for whatever that file exported. To get what you want to achieve, may use something like this.
In your app.js
var express = require('express');
var app = express(); // Note the switched order
app.set('someKey', someObj);
var routes = require('./routes/index')(app);
app.use('/', routes);
module.exports = app;
Then in your routes:
var express = require('express');
var router = express.Router();
/* Wrap everything inside a function */
module.exports = function(app){
console.log(app.get('someKey')); // Access app passed to it from app.js
/* Declare all your routes here. app variable will be accessible */
router.get('/', function(req, res) {
res.render('index', { title: 'Express Test' });
});
return router;
};
Basically, whenever you are requiring a file B from A and want to pass a variable from A to B, this is the general pattern you follow.
See if if helps. :)

Node.js express nested routes

I am new to Node.js and Express and have tried to go through some of the tutorials. I am able to get basic routing working one level deep (e.g., http://localhost/help), but I'm having trouble getting it to work two levels deep (e.g., http://localhost/help/test).
Here are the relevant lines in app.js:
var help = require('./routes/help');
// also tried this
//var help_test = require('./routes/help/test');
var app = express();
app.use('/help', help);
app.use('/help/test', help.test);
// also tried this
//app.use('/help/test', test);
//app.use('/help/test', help_test);
Under the routes directory I have two files: index.js and test.js.
The index.js consists of:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('help');
});
module.exports = router;
The test.js file consists of:
var express = require('express');
var router = express.Router();
router.get('/test', function(req, res) {
res.send('help test!');
});
module.exports = router;
Right now I can't start the server due to the configuration in app.js, but any changes I make so that I can start it results in a 404 error when I try to hit http://localhost/help/test
I think some of your confusion is coming from the require in app.js. Let's look at this line:
var help = require('./routes/help');
That line loads the module in routes/help.js. This file is non-existent In your current configuration. Rename your ./routes/index.js file to ./routes/help.js.
Since the above file will only handle routes prefixed with /help and not /help/test, will need to have an additional require:
var help_test = require('./routes/test');
Your app.js file should now have the following:
var help = require('./routes/index');
var help_test = require('./routes/test');
var app = express();
app.use('/help', help);
app.use('/help/test', help_test);
It should be noted that since your help_test module defines a path at /test, and you "use" it at /help/test, the final path of that route will be: /help/test/test.
Tim's answer got me on the right track, but I ended up with a slightly different solution using his answer that I wanted to post:
In app.js I have:
var help = require('./routes/help');
var help_test = require('./routes/help/test');
....
app.use('/help', help);
app.use('/help/test', help_test);
Under the /routes directory I have this structure:
routes
|-- help
|-- index.js
|-- test.js

Categories

Resources