I'm building a web app using Angular2, to create the project I'm using Angular2 CLI webpack. Angular2 app uses other external packages also (Eg: Firebase). In addition to that, I need to create a REST API running on node.js
How can I serve both of Angular2 app and REST API using node.js server
Use ng build to build your app into build directory.
Create nodejs app to server the build directory as static content, then create route for api.
Following is an example of nodejs app using express that will serve the Angular2 app:
/*
Put content of angular2 build into 'public' folder.
*/
const html = __dirname + '/public';
const port = 4000;
const apiUrl = '/api';
// Express
const bodyParser = require('body-parser');
const compression = require('compression');
const express = require('express');
var app = express();
app
.use(compression())
.use(bodyParser.json())
// Static content
.use(express.static(html))
// Default route
.use(function(req, res) {
res.sendFile(html + 'index.html');
})
// Start server
.listen(port, function () {
console.log('Port: ' + port);
console.log('Html: ' + html);
});
// continue with api code below ...
None of the answers worked properly for me. And if it worked, the Angular routing did not work on reload.
So this is how I solved it. Angular routing works even on full page reload.
function getRoot(request, response) {
response.sendFile(path.resolve('./public/angular/index.html'));
}
function getUndefined(request, response) {
response.sendFile(path.resolve('./public/angular/index.html'));
}
// Note the dot at the beginning of the path
app.use(express.static('./public/angular'));
app.get('/', getRoot);
app.get('/*', getUndefined);
NO angular base-href rewrite is required! Just use ng build or ng build --prod.
Here is full back end code which is working
const express = require('express');
var app = express();
var port = 9999;
function getRoot(request, response) {
response.sendFile(path.resolve('./public/angular/index.html'));
}
function getUndefined(request, response) {
response.sendFile(path.resolve('./public/angular/index.html'));
}
app.use(express.static('./public/angular'));
app.get('/', getRoot);
app.get('/*', getUndefined);
// Start server
app.listen(port, function () {
console.log('server running at port: ' + port);
});
Based on #NTN-JAVA answer, here's a solution to serve an Angular app from NodeJS server.
Here's the summary from beginning:
npm install -g #angular/cli
ng new PROJECT_NAME
cd PROJECT_NAME
npm install nodemon express cookie-parser body-parser morgan method-override --save
5.Create app.js:
var express = require('express');
var app = express();
var morgan = require('morgan');
var bodyParser = require('body-parser');
var port = process.env.PORT || 3000;
var methodOverride = require('method-override'); // simulate DELETE and PUT (express4)
var router = express.Router();
console.log('——————————- Run on port '+ port);
/****************************** Router ***************************/
router.get('*', function(req, res){
res.sendFile('index.html', { root: __dirname + '/' });
});
/****************************** /Router ***************************/
//app.use(morgan('dev')); // log every request to the console
app.use(express.static(__dirname + '/')); // Static (public) folder
app.use(bodyParser.urlencoded({extended:true}));// get information from html forms
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
app.use(methodOverride());
app.use('/', router); // app.use('/parent', router); call all from localhost:port/parent/*
app.listen(port);
Edit package.json file:
{
...
"scripts": {
"start": "ng build; cp app.js dist/app.js; node dist/app.js",
}
...
}
Run npm start
This answer also offers a solution for calling direct URLs from browser and resolving them correctly in your app.
Follow the Express node server with Angular 2 CLI document to serve your application through Node.js server. The application is being served Through Node.js and a REST full API. You can design this REST as your requirements.
E.g.
Serve application with http://localhost:5000/app
app.get('/app/*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'))
});
or
Serve data from REST calls with http://localhost:5000/rest/contacts
app.get('/rest/user', function(req, res) {
res.send({
"id": 2,
"name": "Jhon",
})
});
Step 1: In order to get static content, run this command in your angular app directory -
ng build --prod
Step 2: The first step will create a dist folder in your current directory, move all files in the dist folder to public folder of your node app -
Step 3: Create a node server. App.js -
var path = require('path');
var express = require('express');
var cookieParser = require('cookie-parser');
var cookieParser = require('cookie-parser');
const allowedExt = [
'.js',
'.ico',
'.css',
'.png',
'.jpg',
'.woff2',
'.woff',
'.ttf',
'.svg',
];
var app = express();
app.use(cookieParser());
function getAngularApp(request, response) {
response.sendFile(path.resolve('./public/index.html'));
}
function defaultHandler(request, response) {
if (allowedExt.filter(ext => req.url.indexOf(ext) > 0).length > 0) {
response.sendFile(path.resolve(`public/${req.url}`));
} else {
response.sendFile(path.resolve('./public/index.html'));
}
}
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', getAngularApp);
app.get('/*', defaultHandler);
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
Related
I have a node & express app that is currently hosted on a shared hosting. I would like to run and manage the app using Phusion Passenger. My hosting account supports nodejs applications managed by Passenger which i have never used before.
The server code generated when setting up the Node app is the basic server setup as below.
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
var message = 'It works!\n',
version = 'NodeJS ' + process.versions.node + '\n',
response = [message, version].join('\n');
res.end(response);
});
server.listen();
I would like to replace this with the code below that has elements of express that i am using to serve my API routes.
//import modules
var express = require('express'),
bodyParser = require('body-parser'),
morgan = require('morgan'),
cors = require('cors');
path = require('path');
var app = express();
var port = process.env.PORT || 3000;
//import database connection from dbconnect.js file
var mysql = require('./dbconnect/dbconnect');
//Parse as urlencoded and json.
app.use(bodyParser.urlencoded({extended:false}));
app.use(bodyParser.json());
//adding middleware - cors
app.use(cors());
//Http logger
app.use(morgan('dev'));
//Uncomment for production
//app.use(express.static(__dirname + '/public'));
// Point static path to public
app.use(express.static(path.join(__dirname, 'public')));
//import routes from /routes/routes.js
var user = require('./routes/Users');
route = require('./routes/route');
router = require('./router/router');
//adding routes
app.use('/api', user, route, router);
// Catch all other routes and return the index file
app.get('/*', (req, res) => { res.sendFile(path.join(__dirname, '/public/index.html'));
});
app.use(function (req,res,next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "x-access-token, Origin, Content-Type, Accept");
next();
});
app.listen(port, function() {console.log('Server started at http://localhost:'+port+'/');});
but i get the error:
I am currently running my server script on the shared server using Forever, which is working fine but that hasn't been efficient, so i would like to switch to using Passenger.
Are you able to set your NODE_ENV=development and then look at your page again? It will likely output a lot more information, why it throws the Error.
With the error information, we can have a better look at what might be wrong.
Thanks,
Marc
I suspect it has to do with your routes and it not finding the files.
Here is my node server.js it is in the project root with its own npm config. All Angular files are in /client hence after ng build the dist will be at client/dist
const express = require('express');
const colors = require('colors');
const bodyParser = require('body-parser');
const path = require('path');
const cors = require('cors');
const PORT = process.env.port||'3200';
// init "app"
const app = express();
app.use(cors({origin: `http://localhost:4200`}));
// angular entry point
app.use(express.static(path.join(__dirname, 'client/dist')));
//parse incoming data before routes
app.use(bodyParser.json())
// api routes
app.use('/api',require('./api/api'));
// error middleware
app.use(function(err, req, res, next){
console.log(`${err}`.red.bold)
res.status(422).send({error: err.message });
});
// listen
app.listen(PORT, function(){
console.log(`app running on ${PORT}...`.magenta);
});
When I go to the server http://localhost:3200/ I see my angular app. and when I go to http://localhost:3200/api/someExpressRoute I get my api functions. great
Now I need to figure out how to serve angular routes. for example http://localhost:3200/about is part of my angular single page app. But when I go to that url the server doesnt know what to do.
How do I configure this server to handle http://localhost:3200/* as an angular route that is served from index?
Here's how I serve my angular application via nodejs:
var express = require('express'),
path = require('path'),
fs = require('fs');
var compression = require('compression');
var app = express();
var staticRoot = __dirname + '/';
var env = process.env.NODE_ENV || 'development';
app.set('port', (process.env.PORT || 5000));
app.use(compression());
/* other middleware */
/* place any backend routes you have here */
app.use(function(req, res, next) {
//if the request is not html then move along
var accept = req.accepts('html', 'json', 'xml');
if (accept !== 'html') {
return next();
}
// if the request has a '.' assume that it's for a file, move along
var ext = path.extname(req.path);
if (ext !== '') {
return next();
}
fs.createReadStream(staticRoot + 'index.html').pipe(res);
});
app.use(express.static(staticRoot));
app.listen(app.get('port'), function() {
console.log('app running on port', app.get('port'));
});
When serving the application, ensure all of your frontend dist files are in the same folder as this file (which I call index.js)
The following is my ./server.js my angular dist is at ./client/dist when I node server.js in the terminal my angular app and nodejs backend works as expected. Now how do I deploy on aws beanstalk (im open to changing beanstalk)?
Most tutorials want me to start the job from scratch but i really need the server to work as shown below like it does on localhost.
const express = require('express');
const colors = require('colors');
const bodyParser = require('body-parser');
const compression = require('compression');
const path = require('path');
const fs = require('fs');
const cors = require('cors');
// init "app"
const app = express();
var staticRoot = __dirname + '/client/dist/';
app.set('port', (process.env.PORT || 5000));
app.use(cors({origin: `http://localhost:4200`}));
//parse incoming data before routes
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
// api routes
app.use('/api',require('./api/api'));
app.use(function(req, res, next) {
//if the request is not html then move along
var accept = req.accepts('html', 'json', 'xml');
if (accept !== 'html') {
return next();
}
// if the request has a '.' assume that it's for a file, move along
var ext = path.extname(req.path);
if (ext !== '') {
return next();
}
fs.createReadStream(staticRoot + 'index.html').pipe(res);
});
app.use(express.static(staticRoot));
app.listen(app.get('port'), function() {
console.log('app running on port', app.get('port'));
});
I created a modern MEAN Stack guide with full tutorials and source code. For your question in particular, I created a step-by-step guide on how to deploy a MEAN stack app to AWS Elastic Beanstalk (https://www.meankit.io/guides/deploy-with-aws)
There's also reference links as well if you need further information.
I using the port 4200 in my angular, and port 3000 for my nodejs, when i am running angular the nodejs does not work. Connection refused problem occurred.
What i do? Plz answer my question
That's not how it supposed to work.
Running Angular on 4200 port is the CLI's ability for live reload & All, it doesn't create the distribution folder or the dist.
This is how it should work
you create the dist folder [Html,CSS,JS]
You write an express code in Node JS to serve the dist directory or index.html
You copy the dist to the public accessible folder in node JS
When you hit localhost:3000 then & Only then Node JS as well as Angular will run.
Example :
create 1 folder server
In it write app.js with this code.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
app.use(logger('dev
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(__dirname));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname,'index.html
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (app.get('env== 'development')
{
app.listen(3000, function () {
console.log('Example listening on port 3000!');
});
}
else{
app.listen(8080, function () {
console.log('Example listening on port 8080!');
});
}
module.exports = app;
This snippet assumes that u have installed cookie-parser body-parser morgan.
So basically any request redirects to index.html which is the starting point of the Angular 2 App.
Now when u do
node app.js
your angular app will be served through Node JS & Express
I have done the standard MEAN stack JS application from scratch using Angular-CLI and node/npm. I did ng init and filled out some front end stuff which works fine when I use ng serve, then I created the back end using the code posted below and typing node server in shell. It loads my index.html page which is in src/index and then I try to do a join on src which contains src/app which has my Angular2 code but I get the dreaded Loading... from within my element. I have watched multiple tutorials and they all did exactly this or similar cookie cutter server code, I cannot figure it out.
server.js:
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var event = require('./routes/events');
var port = 3000;
var app = express();
app.set('views',path.join (__dirname, 'src'));
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);
app.use(express.static(path.join(__dirname, 'src')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/', index);
app.use('/', event);
app.listen(port, function() {
console.log("server listening on port" + port);
});
index.js:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
// res.render('../src/index.html');
res.render('index.html');
});
module.exports = router;
in Angular CLI app, run ng build or ng build --prod then node/express serve static directory dist not src.