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.
Related
I'm trying to setup a basic mean stack by following this guide, but the client doesn't seem to render the app instead the body contains,
<body>
<app-root></app-root>
</body>
The file structure is exactly the same as a blank angular cli project except the addition of two extra files.
PLUS: npm install --save ejs cors express body-parser
routes/index.js
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
res.render('index.html');
});
module.exports = router;
server.js
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var cors = require('cors')
var index = require('./routes/index');
// app
var app = express();
// cors
app.use(cors());
// views
app.set('views', path.join(__dirname, 'src'));
// engine
app.set('view enginer', 'ejs');
app.engine('html', require('ejs').renderFile);
// angular dist
app.use(express.static(__dirname + '/dist'));
// body bodyParser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
// route
app.use('/', index);
// Initialize the app.
var server = app.listen(process.env.PORT || 3000, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
I run an ng build and node server.js but get a blank white page in the browser.
Perhaps there is a breaking change that I'm not aware of since that guide was using angular2 (I'm using angular 6).
Since your index.html isn't directly inside the dist folder (rather, it is inside a sub-folder for some reason), try changing app.use(express.static(__dirname + '/dist')); to app.use(express.static(__dirname + '/dist/<your project name here>'));
I just deployed my express.js server on openshiftapps and for some reason, one of the routes not working and I get :
Internal Server Error
Same route is fine in local.this route is my root route which only should render my index.ejs file. the other routes working just fine. I share the codes here, I hope you guys can help to see where did I do wrong.
So this is my server.js code :
var express= require('express');
var path = require('path');
var bodyParser = require('body-parser');
var index = require('./routes/index');
var accountname = require('./routes/accountname');
var app = express();
//View Engine (We Use ejs)
app.set('views', path.join(__dirname,'views'));
app.set('view engine', 'ejs');
// app.use(express.static(path.join(__dirname,'edaccounting')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use('/', index);
app.use('/api/v1/', accountname);
app.listen(8080, function(){
console.log('Server is Started on port 8080');
})
And this is my index.js :
var express= require('express');
var router = express.Router();
router.get('/',function(req,res,next){
res.render('INDEX');
})
module.exports = router;
so for this route : app.use('/', index); I get Internal server error on the real server but it's working in my local and render the .ejs file. Other route is fine in real server. I used openshiftapps and I build my node.js app there with no errors!
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;
I'm learning MEAN stack with 'Getting MEAN with...' book, and problem is older Express version in books than i use.
The first step is to tell our application that we’re adding more routes to look out for,
and when it should use them. We already have a line in app.js to require the server
application routes, which we can simply duplicate and set the path to the API routes
as follows:
var routes = require('./app_server/routes/index');
var routesApi = require('./app_api/routes/index');
Next we need to tell the application when to use the routes. We currently have the following line in app.js telling the application to check the server application routes for
all incoming requests:
app.use('/', routes);
Notice the '/' as the first parameter. This enables us to specify a subset of URL s for
which the routes will apply. For example, we’ll define all of our API routes starting
with /api/ . By adding the line shown in the following code snippet we can tell the application to use the API routes only when the route starts with /api :
app.use('/', routes);
app.use('/api', routesApi);
And there's listing of my app.js file:
var express = require('express')
, others = require('./app_server/routes/others')
, locations = require('./app_server/routes/locations')
, routesApi = require('/app_api/routes/index')
, ;
require('./app_server/models/db')
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/app_server/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
// LOCATION PAGES
app.get('/', locations.homeList);
app.get('/location', locations.locInfo);
app.get('/location/review/new', locations.addReview);
// OTHER PAGES
app.get('/about', others.about);
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
Can someone explain me how to do the same in my Express version ?
In Express 4, this is done using Router Middleware. More info is available on Express Routing here.
A Router is simply a mini express app that you can define middleware and routes on that should all be packaged together, ie /api should all use apiRouter. Here is what apiRouter could look like
apiRouter.js
var express = require('express')
var router = express.Router(); // Create our Router Middleware
// GET / route
router.get('/', function(req, res) {
return res.status(200).send('GET /api received!');
});
// export our router middleware
module.exports = router;
Your main Express app would stay the same, so you would add your router using a require() to import the actual file, and then inject the router with use()
Express Server File
var express = require('express');
var app = express();
var apiRouter = require('../apiRouter');
var port = process.env.PORT || 3000;
app.use('/', apiRouter);
app.listen(port, function() {
console.log('listening on ' + port);
});
When running express, the generated app.js is the following: (at the date of this post)
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 routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use(function(req, res, next) {
...
});
if (app.get('env') === 'development') {
...
}
app.use(function(err, req, res, next) {
...
});
module.exports = app;
For simplicity I removed comments.
My question is really simple:
I've seen a lot nodeJS examples in websites, blogs, and docs, where they use one of the followings:
require('http').createServer(app).listen(3000);
or
app.listen(3000);
If I execute my generated express app (npm start), it runs. I can navigate to localhost:3000 with a browser and it is being served. So... how relevant is to use listen(port)?
Im asking this because I like to have full control of things.
Also, some examples of modules use listen, eg. module Sequelize
Article: "Usage with Express.JS",
link: http://sequelizejs.com/articles/express,
app.js
------
db
.sequelize
.sync({ force: true })
.complete(function(err) {
if (err) {
throw err[0]
} else {
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'))
})
}
})
This makes me think that I should sync before starting listening.
If I dont use listen, and let it listen automagically (as the generated code does), will I get troubles because of syncing and listening at the same time?
If you look at the package.json file you'll probably find its running /bin/www or some such startup script. That will have the "missing" listen statement.