im writing my own MEAN stack. I want to structure it in a horizontal architecture similar to how mean.io does theirs. Each package has its own server and public folder with its own routes.
I have a server.js which is my main express file at the root level. When I start things with npm start I would like to have each package register its own routes / mount its own routes on my main app instance. For some reason though im getting express errors when I try to do this.
Can anyone advise me? Thanks so much. https://github.com/peb7268/LMFM.git
In the submodule / package ( in this case users ) I needed to mount things differently:
var express = require('express');
var router = express.Router();
var Users = function(){
var self = this;
self._name = 'users';
console.log('initializing ' + self._name);
router.route('/')
.get(function(req, res){
res.send('finding '+ self._name);
});
}
module.exports = {'router': router, 'instance': new Users()};
Instead of router.route('/users');
Because when you do app.use('/users', router); the '/', default path will collide with '/users' in the sub module.
Related
I ran into issues on calling a Express route from my Angular template route and Express -> Angular. This code shows my attempt into tackling this issue.
// Server.js file, the main Node.js code
var Outlook = require('Outlook');
// Bootstrap db connection
var db = mongoose.connect(config.db, function(err) {
etc..
});
// Init the express application
var app = require('./config/express')(db);
app.listen('8443'); // Main server.
// App.js - The Outlook module Express route example code
var app = require('express');
var app = express();
// Configure express
// Set up rendering of static files
app.use(express.static('static'));
// Need JSON body parser for most API responses
app.use(bodyParser.json());
// Set up cookies and sessions to save tokens
app.use(cookieParser());
// Home page
app.get('/', function(req, res) {
res.send(pages.loginPage(authHelper.getAuthUrl()));
});
app.get('/express', function(req, res) {
console.log(req.params.msg);
return 'Your EXPRESS DATA IS HERE!';
});
app.listen(3000); // Is this really necessary?
// outlook.cliet.routes.js
'use strict';
//Setting up route
angular.module('outlook').config(['$stateProvider', '$http',
function($http) {
$http.get('http://localhost:3000/express',{"msg":"hi"}).success(function(data){
console.log(data);
});
]);
Issue 1: I don't want to make express run two different servers in different ports in the same instance. That lead me to next issue.
I am using oauth-sign and simple-oauth2 when I bounce back from the outlook module to the main express server, I am logged off the main server.
I don't think it is required a separate express server. Is it possible to make app.js express routing work without listening to a second express server? Notice that express is initialized in a different way. Perhaps module.exports could help?
Thanks
everyone. I'm making my first Node + Express + Angular app.
I kinda used https://github.com/codeschool/StayingSharpWithAngularSTB as a boiler plate.
The general layout is
[folder] app
--------- [Sub-Folder] Assets (Javascript, css, images etc.)
--------- [Sub-Folder] Pages (This contains ng-view stuff)
--------- [Sub-Folder] Views
-------------------- index.html (This is the main index.html that holds everything together)
[folder] node_modules
[folder] server
--------- [Sub-Folder] Controllers
---------------------- core.server.controller.js
--------- expressConfig.js
--------- routes.js
app.js
package.json
So here's the my server configuring files:
app.js
var app = require("./server/routes");
// Start the server
var port = process.env.PORT || 8000;
app.listen(port, function(){
console.log('Listening on port ' + port);
});
/server/expressConfig.js
var bodyParser = require('body-parser');
module.exports = function(app, express) {
// Serve static assets from the app folder. This enables things like javascript
// and stylesheets to be loaded as expected. You would normally use something like
// nginx for this, but this makes for a simpler demo app to just let express do it.
app.use("/", express.static("app/"));
// Set the view directory, this enables us to use the .render method inside routes
app.set('views', __dirname + '/../app/views');
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
};
/server/routes.js
var express = require('express');
var app = express();
var core = require('./controllers/core.server.controller')
// Load Express Configuration
require('./expressConfig')(app, express);
// Root route
app.get('/', function(req, res){
res.sendfile('index.html', {root: app.settings.views});
});
// routes for sending forms
app.route('/contact-form').post(core.sendMail);
app.route('/table-form').post(core.sendTableRes);
app.route('/artist-form').post(core.sendArtistRes);
module.exports = app;
/server/controllers/core.server.controller.js
var nodemailer = require('nodemailer');
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: //my gmail,
pass: //my gmail password
}
});
// Send an email when the volunteer form is submitted
exports.sendMail = function (req, res){
var data = req.body;
transporter.sendMail({
from: //my gmail,
to: //another gmail,
subject: data.volunteerName+ ' wants to volunteer for our event 2016',
text: 'Volunteer Info \n Name : '+data.volunteerName+'\n Phone Number : '
+data.volunteerNum+'\n E-mail : ' +data.volunteerEmail
});
res.json(data);
};
// Other similar mailing functions
And here's one of the angular controllers that sends the mail
volunteerFormController.js
angular.module('MyApp').controller('FormController', function($http){
this.volunteer = {
};
this.addVolunteer = function(){
var data = ({
volunteerName : this.volunteer.name,
volunteerEmail : this.volunteer.email,
volunteerNum : this.volunteer.phone
});
$http.post('/contact-form', data).
then(function(response) {
//show thank you message with animate.css classes and hide form
$(".thanksFriend").addClass("animated tada showBlock");
$("form").addClass("flipOutX animated hideBlock");
}, function(response) {
$(".sorryFriend").addClass("animated tada showBlock");
});
};
});
And this works just fine! But if I enable html5 mode in Angular and serve up the index in Express using
app.use(function(req, res){
res.sendfile('index.html', {root: app.settings.views});
});
in the routes.js file, Html 5 mode works great! No 404s when I remove the pound and refresh but then the none of my contact forms work, and the console isn't giving me any errors... My server files are pretty small and it's not super complicated so it should be pretty easy to figure out how to have both HTML5 mode AND working contact forms. Any ideas? I don't know much about Express and I used a tutorial http://www.bossable.com/1910/angularjs-nodemailer-contact-form/ to figure out how to use nodemailer. Is there another way to set up nodemailer so this works?
I would REALLY appreciate some help with this. It's driving me absolutely crazy ;__;
So, you had to serve every request return index.html,
by changing app.get('/', to app.get('/*',
I am following the directory structure given here:
angular-fullstack
I have a folder name Musician in server/api.
In this folder,
Musician
|
|----->index.js
|----->Musician.controller.js
|----->Musician.model.js
In index.js,
I give the routes as:
use strict';
var express = require('express');
var musicians = require('./Musician.controller');
var auth = require('../../auth/auth.service');
var router = express.Router();
router.get('/musicians', musicians.findAll);
router.get('/musicians/:id', musicians.findById);
router.post('/musicians', auth.isAuthenticated(), musicians.add);
router.put('/musicians/:id', musicians.update);
router.delete('/musicians/:id', musicians.delete);
router.get('/import', musicians.import);
module.exports = router;
It gives the error that way. But if I put this in my routes.js, It works.
How do I get these routes working right from index.js?
As per the directory structure and articles on web, it should be working from index.js.
Error:
I've been learning how to use the MEAN stack in order to build web apps and so far it's been a lot of fun. Instead of using yeoman generators or npm app to generate my code for me, I've been building my whole app from the ground up. This way I know how each piece connects and what is going on with my app. I was just starting to connect the front and back end of my app when I looked at the developer console and saw
GET http://blog.dev/bower_components/angular/angular.js
Not only angular, but every other resource I have (Modernizr, angular-routes, mootools, restangular, etc ...). When you use the yeoman angular generator you are suppose to run the grunt serve command to start up the angular side. Because I built the app from scratch and I am using npm for my build tool I didn't know how to build the front end server. So, I just went with a simple nginx virtual host pointing to my index.html. Here's the config:
server {
listen 80;
server_name blog.dev;
root /home/michael/Workspace/blog/app;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
I'm not sure what other variables could be affecting the situation, so if I missed something please tell me and I'll be happy to give you what you need!
If you're using the mean stack, you should be able to host both the back end and serve the front end directly with node.
I'm not sure of your project structure but here's the structure for one I'm working on now.
/bin --contains a file called www.js (used to launch app)
/data
/models
/node_modules
/public -- contains my angular implementation
/routes -- contains express routes
/temp
/upload
/views
app.js -- main configuration for express
api.js -- my apis
package.json
in the /bin/www.js file you have the code to start your node server.
var app = require('../app');
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function() {
debug('Express server listening on port ' + server.address().port);
});
You'll also need to setup express and your routes so well look at routes first
in the routes directory I have a file called index.js
In this file, I define one route that leads to my angular index.html page.
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res) {
res.redirect('/pages/index.html');
});
module.exports = router;
And of course you'll need to set up express.
process.env.TMPDIR = 'tmp'; // to avoid the EXDEV rename error, see http://stackoverflow.com/q/21071303/76173
var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var multer = require('multer');
var flow = require('./flow-node.js')('tmp');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
var uuid = require('uuid');
var mongoose = require('mongoose');
var session = require('express-session');
var routes = require('./routes/index');
var app = express();
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(session({genid: function(req) { return uuid.v4()}, secret: 'XXXXXXXXXXX',
saveUninitialized: true,
resave: true}));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
module.exports = app;
Now assuming you have your Angular files and javascript in the 'public' directory somewhere, you should be able to start up Node with the following command.
node bin/www
And the point your browser at http://localhost:3000 and be in business.
Hope this helps and happy learning.
For easy maintenance, I would like to compartmentalize my server routes:
server.js (start app):
require('./routes/allRoutes')(app);
allRoutes.js:
module.exports = function(app){
//don't I need to pass (app) below? This will not work as is
var Group1 = require('../routes/Group1/groupRoutes')(app),
Group2 = require('../routes/Group2/groupRoutes')(app);
app.use('/group1', Group1);
app.use('/group2', Group2);
}
groupRoutes.js: (in Group1 Folder)
module.exports = function(app){
//don't I need to pass (app) below? This will not work as is
var SubGroup1 = require('../routes/Group1/subGroup1Route')(app);
.....
app.use('/subgroup1', SubGroup1);
}
subGroup1Routes.js: (in Group1 Folder)
var FooCrtl = require('../../controllers/Group1/subGroup1/FooCtrl');
module.exports = function(app){
app.get('/api/foo', FooCtrl.get);
app.post('/api/foo', FooCtrl.post);
}
AngularJs FooSvcs:
....
return {
getFoo: function(){
return $http({
method: 'GET',
url: '/group1/subgroup1/api/foo', <--- NOT WORKING
});
},
Two-Fold issues:
On the server side do I not need to pass the "app" as a parameter down the routes tree? I tried but recv'd an error.
In the scenario above, what is the correct url for my angular factory as I what have does not work.
OK, this was a tough one but I finally solved it.
My desire to compartmentalize my route structure on the server side to mirror my module structure on the client [angular] side is the right approach.
Where I erred was in thinking I needed to create a tree structure [<-- WRONG] for my server routes and that is NOT the case.
The Example:
Client [angular] side:
public
---- app
---- module A folder
---- module B folder
---- module C folder
Server [express] side structure:
server
---- routes
---- route A folder
--- foo apis
--- bar apis
---- route B folder
---- route C folder
foo api on server side structure:
var express = require('express'),
FooCtl = require('../../controllers/foo/FooCtl');
module.exports = function(app){
app.get('/api/foo', FooCtl.get);
....
}
I do not need to create a "parent route" to collect on my routes in that folder.
Instead, using "npm install --save wrench" in my root, server.js:
var express = require('express'),
path = require('path'),
wrench = require('wrench');
wrench.readdirRecursive("routes", function (error, files) {
if(files != null){
files.forEach(function (file) {
if (file.indexOf('.js') > -1 && file != undefined) {
fullPath = ('./routes/' + file);
console.log(fullPath);
require(fullPath)(app);
}
})} });
And everything works!