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.
Related
I have a server/website that is using express and react. I'd like to serve the website using app.use(express.static()). This is working the way I'd like to except it is interfering with a single server handled url /parse-dashboard which is served as a separate middleware.
const path = require( 'path' )
var express = require('express');
var bodyParser = require('body-parser');
var basicAuth = require('express-basic-auth');
var ParseServer = require('parse-server').ParseServer;
var ParseDashboard = require('parse-dashboard');
var url = require('url');
var app = express();
var config = require( path.join( __dirname, 'config' ) )
app.use('/parse-dashboard', ParseDashboard(config.dashboard, true));
// Middleware for reading request body
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, './client/build')));
app.set( 'port', process.env.PORT || 3000 )
const server = require( 'http' ).createServer( app )
server.listen( app.get( 'port' ), () => {
console.log('express server listening on port ' + ( process.env.PORT || server.address().port ));
});
When I go to /parse-dashboard, the React app (which is using react-router-dom) takes the url and shows a blank route. How can I have this route be shown by the server instead?
I figured it out and boy do I feel dumb. In the React app folder contained inside my server(Express) folder I have a package.json file to declare the React dependencies. The package.json file still had the proxy key contained in it that some guides have mentioned to use in order to get api calls to your own server to go through when working locally. After removing that key it all works as expected, /parse-dashboard is handled by express and the rest are handled by react-router-dom
I am trying to setup a base for a MEAN application. I created the new project using Angular CLI, added Express.js, MongoDB modules to the application. In the app.js file I have the following configuration:
var express = require('express');
var bodyParser = require('body-parser');
var session = require('express-session');
var path = require("path")
var app = express();
var conf = require('./config/conf');
var server = require('http').Server(app);
var mongoDB = require('./adapters/mongodb')
var mongoClient = new mongoDB(conf);
app.use(bodyParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type,__setXHR_');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
mongoClient.connect(function (dbconn) {
app.dbconn = dbconn;
app.conf = conf;
console.log("************************************************************");
console.log(new Date() + ' | CRUD Server Listening on ' + conf['web']['port']);
console.log("************************************************************");
server.listen(conf['web']['port']);
var Routes = require('./routes/http-routes');
new Routes(app);
});
I setup a hello world route for now and no changes done to the angular sources, which means I would land at the Angular default starting page. But I cant land at the page but instead a white screen page. However, I can access the routes using Postman. I do ng build and then node app.js to run the application. What am I doing wrong?
You should use the Express way to handle routes
First
const router=express.Router();
Then let's suppose you have a file using only authentication routes
const authentication = require('./routes/authentication')(router);
To conclude, you only have to do :
app.use('/authentication', authentication);
This allows a better divison of your routes
You 'll use your routes this way
module.exports= (router)=>{
router.get('/',(req,res)=>{
res.json(message:'Hello World');
});
return router;
To set angular routes you need the router module, for more details read the documentation
You serve only index.html from your Angular App. But you need also serve assets, css and javascript. Easiest would be something like this (but you need to adjust directory names:
app.use('/js', express.static(path.resolve(__dirname, 'dist/js')));
app.use('/css', express.static(path.resolve(__dirname, 'dist/css')));
app.use('/assets', express.static(path.resolve(__dirname, 'dist/assets')));
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.
How to deploy angularjs with nodejs as backend requesting server, after building the angularjs package
My project structure:
app/
app/config
app/scripts
app/styles
app/views
bower_components/
dist/
node_modules/
test/
server.js
After building the angular package using grunt, i am using only the dist folder. But i want to use node for my request, to server. So how to setup the nodejs packages inside dist build folder. Which will be deployed to parse.com
Basically you need a simple webserver which is always returning index.html + the assets.
If I'm right in your root (i guess /dist at this point) you have to create an app.js file containing the following:
var express = require('express');
var bodyParser = require('body-parser')
var path = require('path')
var app = express();
app.use(bodyParser.urlencoded({extended:false}));
app.use(function (req, res, next) {
if (path.extname(req.path).length > 0) {
// normal static file request
next();
}
else {
// should force return `index.html` for angular.js
req.url = '/index.html';
next();
}
});
// static file serve
app.use(express.static(__dirname))
app.listen(3000)
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('/*',