Want to get crystal clear about NodeJS app structure (Full JavaScript Stack) [closed] - node.js

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I would like to know the structure of a typical NodeJS app, because the more I read and see the projects, the more confused I am, specifically for questions like these (or even more after I updated this question):
Take the MEAN stack for example, from what I know, NodeJS and Express take care of the server part, providing the server interface, etc. MongoDB and Angular are pretty straightforward.
But where should the business logic go? Say if I have a controller.js which contains a function, and the route.js file binds the request with this controller function. My question is: under which module these files belong to/run under (Express or NodeJS?)
Where is the starting point of a NodeJS app? Say index.php is the starting point of a PHP app, but where is it for NodeJS app? I can see that all Nodejs projects have a file called server.js or app.js, etc.(containing something like module.exports = app;) But how can NodeJS know which file to find and execute?
I am a fresh noob on NodeJS, Express, sequelize.js/Mongoose, Jade/EJS but want to get started on a NodeJS project. Could you please elaborate on the actual function that each modules provide and a general introduction of the typical structure for a full JS stacked NodeJS app? Thanks in advance!

Alright, this is a pretty broad question and I'm definitely no expert, but I'll do my best here.
TL;DR
routes are controllers that tell what logic to execute when a user navigates their browser to a certain path within your app, including which views to render and what data to send to those views
models are just that - data models within your application
module.exports = tells a file what exactly it "exports", that is what code needs to be executed or accessible from your main app file.
require(..) includes a module. You can set this on a variable so that you may call module functions later, or simply execute a function if that is all that module.exports returns.
Combining these techniques can help you nail down a solid framework for any of your applications.
Long Answer
Express provides a solid framework for structuring your Node.js application. Node is completely independent of Express, but because of how popular Express is they practically go hand-in-hand. Once installed, Express can be used to generate a scaffold web project (with options) for you to build on top of if you'd like.
Controllers
A generated project will create /routes/index.js, which (if you understand MVC) is essentially your main controller. A route in express is written as so:
app.get('/path', function(req, res, next){ .. } );
Lets break that down: our application variable (app) is being told that on a GET request to '/path' to execute an anonymous callback function with req, res, next variables (request, response, callback respectively). I find it helpful to think of this like a custom event handler.
Its important to note at this point that we could also call app.post with the same syntax for posts to a URL as opposed to gets.
Within our anonymous callback, we handle any incoming data and render a view for the user. This is where most of my business logic ends up, so it actually makes sense to NOT use anonymous functions here. Here's an example of a basic callback that just displays a homepage:
app.get('/', function(req, res, next){
//some business logic
res.render('views/home');
});
When the user tries to GET the index path of our application (/), we simply render our home view that, from the root of our project, is stored in a views folder.
But what if we want to modularize this so that we aren't declaring all of our routes in our main app.js or server.js?
We use module.exports = .. in our modules to tell our server what exactly to include. In my controller, I export a single function that takes the application as an argument and uses that to define our routes like so:
Controllers/User.js
module.exports = function(app){
app.get('/users', function(req, res){
var users = req.db.collection('users').find();
if (!users) {
console.log("no users found");
res.redirect('/');
} else {
res.render('users/index', {users : users});
}
});
};
Don't worry about the req.db code, I attach the database to the request in my application but that isn't done by default. Simply understand that I'm getting a list of 'users' here, and redirecting the user to the index of my app if there aren't any.
Models
Mongoose provides us with a great interface for writing models. With mongoose, writing models is a three step process:
Define a schema
Define model logic
Generate and export the model
Here is an example of a User model:
Models/User.js
var mongoose = require('mongoose'),
userSchema = new mongoose.Schema({
name: { type: String, required: true },
joinDate: {type: Date, default: date.now }
}),
User = mongoose.model('user', userSchema);
module.exports = user;
Server App
module.exports is used to help us define some modularity to our codebase. When we run a node application, we're ultimately running a single JavaScript file (you've already seen that file with server.js or app.js).
To keep this file from getting too big with multiple models and routes, we use require(module) to include code from other JS files. module in our case would be a path to the module we want to require. If you have the following doc structure:
| Controllers
- User.js
| Models
- User.js
| Views
app.js
To include your user controller from app.js, you would write: require('./Controllers/User'). Since our controller modules simply export functions, we can call that function immediately after our require statement by simply adding parentheses at the end (with whatever parameters are required). Including my controllers looks like so:
require('./Controllers/User')(app)
I'm passing in the actual app, because my module (below) simply exports a function that adds business logic to my app's routes. This only needs to be called and never used, so I don't capture my controller as a variable to call methods on later.
Including models is a little different, since we may want to perform some operation that our model defines. We can do this by changing up our require code just a bit:
var User = require('./Models/User');
Now we can call methods of our User model whenever. Mongoose gives us a lot of base functionality for free:
User.find({}, function(err, users){ .. });
The above function will go find all of our users, and then execute an anonymous function with a potential err (is null if no issues) and then a list of our users in JSON format. Pretty nifty.
Combining all of these concepts is how you create a basic web application using Express and Node.js. Please let me know in the comments if there's anything I can clarify about how I use Express. This is very surface level knowledge, and I suggest digging into documentation and looking at plugins to extend the capabilities of your apps. Good luck!

Related

Register new route at runtime in NodeJs/ExpressJs

I want to extend this open topic: Add Routes at Runtime (ExpressJs) which sadly didn't help me enough.
I'm working on an application that allows the creation of different API's that runs on NodeJs. The UI looks like this:
As you can see, this piece of code contains two endpoints (GET, POST) and as soon as I press "Save", it creates a .js file located in a path where the Nodejs application is looking for its endpoints (e.g: myProject\dynamicRoutes\rule_test.js).
The problem that I have is that being that the Nodejs server is running while I'm developing the code, I'm not able to invoke these new endpoints unless I restart the server once again (and ExpressJs detects the file).
Is there a way to register new routes while the
NodeJs (ExpressJs) is running?
I tried to do the following things with no luck:
app.js
This works if the server is restarted. I tried to include this library (express-dynamic-router, but not working at runtime.)
//this is dynamic routing function
function handleDynamicRoutes(req,res,next) {
var path = req.path; //http://localhost:8080/api/rule_test
//LoadModules(path)
var controllerPath = path.replace("/api/", "./dynamicRoutes/");
var dynamicController = require(controllerPath);
dynamicRouter.index(dynamicController[req.method]).register(app);
dynamicController[req.method] = function(req, res) {
//invocation
}
next();
}
app.all('*', handleDynamicRoutes);
Finally, I readed this article (#NodeJS / #ExpressJS: Adding routes dynamically at runtime), but I couldn't figure out how this can help me.
I believe that this could be possible somehow, but I feel a bit lost. Anyone knows how can I achieve this? I'm getting a CANNOT GET error, after each file creation.
Disclaimer: please know that it is considered as bad design in terms of stability and security to allow the user or even administrator to inject executable code via web forms. Treat this thread as academic discussion and don't use this code in production!
Look at this simple example which adds new route in runtime:
app.get('/subpage', (req, res) => res.send('Hello subpage'))
So basically new route is being registered when app.get is called, no need to walk through routes directory.
All you need to do is simply load your newly created module and pass your app to module.exports function to register new routes. I guess this one-liner should work just fine (not tested):
require('path/to/new/module')(app)
Is req.params enough for you?
app.get('/basebath/:path, (req,res) => {
const content = require('content/' + req.params.path);
res.send(content);
});
So the user can enter whatever after /basepath, for example
http://www.mywebsite.com/basepath/bergur
The router would then try to get the file content/bergur.js
and send it's contents.

KeyStone JS Account Controller

I understand MVC structure when coding in NodeJS. I started using Keystone JS recently, and I really like it. But, the way they set their controllers up, it seems that the controllers ONLY serve the purpose of rendering a view.
In an earlier project, I had an Account.js model and an Account.js controller. I'm trying to see how it would copy over to keystone.
So: How would I allow users to signup/signin/logout in a Keystone project (not into the Admin UI, but like a member of a regular site)? How would I make an Account controller (obviously with no view to render)?
There are lots of ways you can implement your own methods of authentication and account management in keystone since it is based on express.js.
You can then add an array of 'middleware' functions to routes which will run before passing the request to the controller.
e.g
Route before middleware added
app.get('/admin', routes.views.userAdmin);
Middleware Function
function isAuthenticated(req, res, next) {
// do any checks you want to in here
// CHECK THE USER STORED IN SESSION FOR A CUSTOM VARIABLE
// you can do this however you want with whatever variables you set up
if (req.user.authenticated)
return next();
// IF A USER ISN'T LOGGED IN, THEN REDIRECT THEM SOMEWHERE
res.redirect('/');
}
Route with middleware added
app.get('/admin', isAuthenticated, routes.views.userAdmin);
It's a very broad questions so I'd recommend you go and decide on the best way you'd like to do it yourself as everyone has their own personal preference. The search terms you want are 'express middleware authentication'. A lot of people use PassporJS http://passportjs.org/
Hope that helps :)

Access Previously-Defined Middleware

Is there a way to access or delete middleware in connect or express that you already defined on the same instance? I have noticed that under koa you can do this, but we are not going to use koa yet because it is so new, so I am trying to do the same thing in express. I also noticed that it is possible with connect, with somewhat more complicated output, but connect does not have all the features I want, even with middleware.
var express = require('express');
var connect = require('connect');
var koa = require('koa');
var server1 = express();
var server2 = connect();
var server3 = koa();
server1.use(function express(req, res, next) {
console.log('Hello from express!');
});
server2.use(function connect(req, res, next) {
console.log('Hello from connect!');
});
server3.use(function* koa(next) {
console.log('Hello from koa!');
});
console.log(server1.middleware);
// logs 'undefined'
console.log(server2.middleware);
// logs 'undefined'
console.log(server2.stack);
logs [ { route: '', handle: [Function: connect] } ]
console.log(server3.middleware);
// logs [ [Function: koa] ]
koa's docs say that it added some sugar to its middleware, but never explicitly mentions any sugar, and in particular does not mention this behavior.
So is this possible in express? If it is not possible with the vanilla version, how hard would it be to implement? I would like to avoid modifying the library itself. Also, what are the drawbacks for doing this, in any of the 3 libraries?
EDIT:
My use case is that I am essentially re-engineering gulp-webserver, with some improvements, as that plugin, and all others like it, are blacklisted. gulp is a task runner, that has the concept of "file objects", and it is possible to access their contents and path, so I basically want to serve each file statically when the user goes to a corresponding URL in the browser. The trouble is watching, as I need to ensure that the user gets the new file, and not the old version. If I just add an app.use each time, the server would see the file as it is originally, and never get to the middleware with the new version.
I don't want to restart the server every time a file changes, though I will if I can find no better way, so it seems I need to either modify the original middleware on the fly (not a good idea), delete it, or add it to the beginning instead of the end. Either way, I first need to know where it "lives".
You might be able to find what your looking for in server1._router.stack, but it's not clear what exactly you're trying to do (what do you mean "access"?).
In any case, it's not a good idea to do any of these, since that relies strictly on implementation, and not on specification / API. As a result any and all assumptions made regarding the inner implementation of a library is eventually bound to break. You will eventually have to either rewrite your code (and "reverse engineer" the library again to do so), or lock yourself to a specific library version which will result in stale code, with potential bugs and vulnerabilities and no new features / improvements.

Concerns about separating front-end and back-end with a NodeJS UI server [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
During the last months, we at work have been looking for a solution to the following problem: front-end developers can't easily modify the appearance of the website without the help of back-end devs.
Our culture as a team is mostly based on full-stack frameworks such as Symfony 2 and Ruby on Rails. We use templating engines but the templates are mostly written by backend-devs according to designers' markups.
The step we are considering to make is separating that monolithic architecture into a backend rest API and a NodeJS server as "UI server". The NodeJS server would handle the client request, consume the backend API and return a rendered template. By specifying clearly the API and the JSONs served, frontend and backend devs could then work in parallel with less problems. More info here: http://www.nczonline.net/blog/2013/10/07/node-js-and-the-new-web-front-end/
The thing is, we strongly believe that this separation is a good thing from an architecture POV, but we fear about the drawbacks. We suspect that it will make things way harder. None of us in the team has never worked with this kind of architectures, so any hint or experience about that would be very valuable.
Is it worth it? When? Why?
What you need to do, is to have a clear line that separates your front-end from back-end. Then whatever the front-end needs from the backend-end team, it will documented comprehensively.
Let's say what you currently have is something like this:
app.get('/', function (req, res) {
database.query('select * from user', function (err, result) {
res.render(result);
});
});
But then then you want to make it like this:
in UI server:
app.get('/', function (req, res) {
request('apiServer/user', function (err, result) {
res.render(result);
});
});
in API server:
app.get('/user', function (req, res) {
database.query('select * from user', function (err, result) {
res.send(result);
});
});
This is good. This will separate the front-end and back-end, but not only logically but also physically by being in different servers.
I believe if they are under the same server it will be just ok. Instead of above, just have them in different files:
in user.js:
exports.getAll = function (cb) {
database.query('select * from user', cb);
};
in server.js:
var user = require('./user');
app.get('/', function (req, res) {
user.getAll(function (err, result) {
res.render(result);
});
});
Why this is better than your solution? Because it separates touching database, and rendering the data, and also it doesn't have a extra http round trip.
Following a MVC pattern, you put files that are like user.js in a models directory, you put files like server.js in a controller directory. You make sure both are documented for front-end developers.
Now if your front-end developers are just gonna make UI changes, they will just touch the HTML files. If they want to add a section with data, they will read the backend documentation, they will add another call to the model to get the data they in the respective controller that renders the HTML.
Just make sure you will standardize everything, so when something new comes along, programmers in your team can somehow predict how the interface is going to be, use a good ORM to the heavy lifting on making database calls. If using an ORM is not your choice then make good abstractions.
So your application in layers can be like this:
Database --> ORM --> Models --> Controllers --> Views(HTML files)
Now the front-end developers, work on the right side the above diagram. They only need to know the documented API of their left side if it's nicely abstracted away, but they don't need to know how it works. Anyone who works on the controllers, only need to know the documented API of their left side which is Models. You can continue it all the way to the database on the left.
Then on each layer you can have unit tests and integration tests all the way to the front to make sure the interfaces are consistent.
And if you're team is large, with a large code base, make sure you always keep the backward compatibility in your interfaces, but with warnings in logs for deprecated stuff. Never try to break anything.

Node.js Express: require/use one app within another

I'm facing the following situation. In order to further modulize my software development, I've written a few standard modules stand alone. Think for instance of an login module based upon Express and Passport, allowing users to login with all kinds of social services. The module also contains UI for user management, login, registration, profile, etc.
Now, the thing I'm trying to do is to just drop the Auth app folder (containing the express app, all it's routes, views, models, settings and dependecies) into another Express app (for instance, a CMS) and then load it with something like require('./lib/auth/app.js'). I know this is possible, take a look at Kue.
How would I go about doing this? And how do I manage namespacing problems? I could of cours append /auth/ to each route, but I can imagine the settings (app.use()'s) and public folder would conflict with the 'parent' app.js' settings and public folder.
Thanks in advance,
Fabian
Think I found my answer. So, I found this question, and this one. Guess my terminology was off.
I solved my problem by doing a few things. First of all, I changed all routes and url's to be "namespaced" (not really, but this does the job). All routes now have /auth/ in front of them. I did the same to all links, so that's all working.
Next, I removed the server part from my app.js. So, in stead of doing:
require('http').createServer(app).listen(app.get('port'));
I just do:
module.exports = app;
And I add some custom methods to the app object:
app.isLoggedIn = auth.isLoggedIn;
app.notLoggedIn = auth.notLoggedIn;
Then, in my root app, I just do the following to load the auth app in. Routing, public files, and all other stuff happens magically. pretty cool.
var auth = require('./vendor/auth/app');
var app = express();
app.configure(function() {
app.use(auth); // use our auth app
// do a lot of root-app related stuff...
});
Things still to do:
My auth app uses some session stuff. According to the second link, if I understand correctly, the app.use(session...) stuff in my auth app gets overridden by app.use. Also, I want to define an EJS helper to generate my urls (something like site_url('/facebook/callback') which then points to /auth/facebook/callback). Finally, I need to include settings from my root app. I'm thinking of wrapping my entire app.js (in auth) in a function, to which I pass a config object. Like this:
module.exports = function(config) {
var app = express();
app.set('config', config);
// various app settings, routes, etc
// return app so it's available in my root.
return app;
}
I hope this helps, if you need a bit more information I'll see if I can post some code to a gist. just let me know!

Resources