Run a script with ng server Angular 6 - node.js

I need to run a script every time I use the ng serve command, I'm preparing I server to receive POST from an API. My question is if when I run firebase deploy from the /dist folder, it will start this server so I get POST from an API in my application.
Below is the file I need to run via localhost with command ng serve within Firebase Hosting when running firebase deploy command.
In my angular.json file I tried as follows:
"assets": [
"src/favicon.ico",
"src/assets",
"src/server-api/server.js"
],
At the moment I'm only able to execute by setting a script through package.json.
"scripts": {
"app-main": "ng build && node ./server-api/server.js",
}
server.js:
// Get dependencies
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
// Get our API routes
const api = require('./routes/api');
const app = express();
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Point static path to dist
app.use(express.static(path.join(__dirname, 'dist')));
// Set our api routes
app.use('/api', api);
// Catch all other routes and return the index file
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
/**
* Get port from environment and store in Express.
*/
const port = process.env.PORT || '3000';
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port, () => console.log(`API running on localhost:${port}`));
api.js:
const express = require('express');
const router = express.Router();
const firebase = require("firebase");
// Required for side-effects
require("firebase/firestore");
firebase.initializeApp({
apiKey: "myapikey",
authDomain: "myapp-30d6b.firebaseapp.com",
projectId: "myapp-30d6b",
});
// Initialize Cloud Firestore through Firebase
var db = firebase.firestore();
router.post('/notifications', (req, res) => {
res.status(201).json({
notification: req.body
});
db.collection("notifications").add(req.body)
.then(function (docRef) {
console.log("Success: ", docRef.id);
})
.catch(function (error) {
console.error("Error", error);
});
});
module.exports = router;
package.json:
{
"name": "myapp",
"version": "1.0.0",
"scripts": {
"app-main": "ng build && node server.js",
"ng": "ng",
"start": "ng serve --open",
"start-hmr": "ng serve --configuration hmr -sm=false",
"start-hmr-sourcemaps": "ng serve --hmr -e=hmr",
"build": "node --max_old_space_size=6144 ./node_modules/#angular/cli/bin/ng build --dev",
"build-stats": "node --max_old_space_size=6144 ./node_modules/#angular/cli/bin/ng build --dev --stats-json",
"build-prod": "node --max_old_space_size=6144 ./node_modules/#angular/cli/bin/ng build --prod",
"build-prod-stats": "node --max_old_space_size=6144 ./node_modules/#angular/cli/bin/ng build --prod --stats-json",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"bundle-report": "webpack-bundle-analyzer dist/stats.json"
},
"private": true,
"dependencies": {
"#agm/core": "1.0.0-beta.2",
"#angular/animations": "6.0.0",
"#angular/cdk": "6.0.1",
"#angular/common": "6.0.0",
"#angular/compiler": "6.0.0",
"#angular/core": "6.0.0",
"#angular/flex-layout": "6.0.0-beta.15",
"#angular/forms": "6.0.0",
"#angular/http": "6.0.0",
"#angular/material": "6.0.1",
"#angular/material-moment-adapter": "6.0.1",
"#angular/platform-browser": "6.0.0",
"#angular/platform-browser-dynamic": "6.0.0",
"#angular/router": "6.0.0",
"#ngrx/effects": "6.0.0-beta.1",
"#ngrx/router-store": "6.0.0-beta.1",
"#ngrx/store": "6.0.0-beta.1",
"#ngrx/store-devtools": "6.0.0-beta.1",
"#ngx-translate/core": "10.0.1",
"#swimlane/ngx-charts": "8.0.0",
"#swimlane/ngx-datatable": "12.0.0",
"#swimlane/ngx-dnd": "4.0.0",
"#types/prismjs": "1.9.0",
"angular-calendar": "0.24.0",
"angular-in-memory-web-api": "0.6.0",
"angularfire2": "5.0.0-rc.9",
"body-parser": "1.18.3",
"chart.js": "2.7.2",
"classlist.js": "1.1.20150312",
"core-js": "2.5.6",
"creditcard.js": "2.1.3",
"d3": "5.2.0",
"express": "4.16.3",
"firebase": "5.0.3",
"firebase-admin": "5.12.1",
"font-awesome": "4.7.0",
"hammerjs": "2.0.8",
"lodash": "4.17.10",
"moment": "2.22.1",
"ng2-charts": "1.6.0",
"ng2-currency-mask": "5.3.1",
"ngrx-store-freeze": "0.2.2",
"ngx-color-picker": "6.0.0",
"ngx-cookie-service": "1.0.10",
"ngx-mask": "2.7.3",
"ngx-toastr": "8.6.0",
"perfect-scrollbar": "1.3.0",
"prismjs": "1.14.0",
"rxjs": "6.1.0",
"rxjs-compat": "6.1.0",
"typescript": "2.7.2",
"web-animations-js": "2.3.1",
"zone.js": "0.8.26"
},
"devDependencies": {
"#angular-devkit/build-angular": "0.6.0",
"#angular/cli": "6.0.3",
"#angular/compiler-cli": "6.0.0",
"#angular/language-service": "6.0.0",
"#angularclass/hmr": "2.1.3",
"#types/jasmine": "2.8.7",
"#types/jasminewd2": "2.0.3",
"#types/lodash": "4.14.108",
"#types/node": "8.9.5",
"codelyzer": "4.2.1",
"jasmine-core": "2.99.1",
"jasmine-spec-reporter": "4.2.1",
"karma": "1.7.1",
"karma-chrome-launcher": "2.2.0",
"karma-coverage-istanbul-reporter": "1.4.2",
"karma-jasmine": "1.1.2",
"karma-jasmine-html-reporter": "0.2.2",
"protractor": "5.3.1",
"ts-node": "5.0.1",
"tslint": "5.9.1",
"webpack-bundle-analyzer": "2.11.1"
}
}
The solution I'm looking for:
I need it to work when I run ng serve or else when my application is hosted on Firebase Hosting through the firebase deploy command.
That way I can receive POST in my Angular application.

you can use the pre/post hooks for npm explained here:
http://www.marcusoft.net/2015/08/pre-and-post-hooks-for-npm-scripting.html#hooks-pre-and-post
try adding these 2 scripts to your package.json and then run npm run server:dev
"preserver:dev": "node ./server-api/server.js",
"server:dev": "ng serve --configuration=dev",

Related

Getting a 404 error while trying to connect backend Api from the Heroku deployed Angular Api

I have successfully deployed my angular app onto Heroku. I have implemented the proxy.conf.json file to connect to the Backend API (which is also deployed in Heroku and its a Java JAX-RS REST API) and it is up and running.
The proxy.conf.json file contains:
{
"/webapi/*": {
"target": "https://backend-api.herokuapp.com",
"secure": false,
"logLevel": "debug",
"changeOrigin": true
} }
Also updated the start command in the package.json file as
"start": "ng serve --proxy-config proxy.config.json"
This is working perfectly fine in local using localhost:4200
But when I am deploying the project onto heroku, the backend call is not being held.
for your reference i am attaching the complete package.jsonfile
{
"name": "myapp-client",
"version": "0.0.0",
"scripts": {
"heroku-postbuild": "ng build --aot --prod",
"ng": "ng",
"start": "npm run build & concurrently --kill-others \"npm run serve-api\" \"npm run serve\"",
"serve": "ng serve --proxy-config proxy.config.json",
"build": "ng build",
"serve-api": "node server.js",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"engines": {
"node": "14.8.0",
"npm": "6.14.7"
},
"private": true,
"dependencies": {
"#angular-devkit/build-angular": "^0.1000.6",
"#angular/animations": "~10.0.9",
"#angular/cli": "^10.0.6",
"#angular/common": "~10.0.9",
"#angular/compiler": "~10.0.9",
"#angular/compiler-cli": "^10.0.9",
"#angular/core": "~10.0.9",
"#angular/forms": "~10.0.9",
"#angular/platform-browser": "~10.0.9",
"#angular/platform-browser-dynamic": "~10.0.9",
"#angular/router": "~10.0.9",
"awesome-typescript-loader": "^5.2.1",
"bootstrap": "^4.5.2",
"concurrently": "^5.3.0",
"cors": "^2.8.5",
"d3": "^3.5.17",
"express": "^4.17.1",
"file-saver": "^2.0.2",
"font-awesome": "^4.7.0",
"jquery": "^3.5.1",
"ng2-nvd3": "^2.0.0",
"nvd3": "^1.8.6",
"popper.js": "^1.16.1",
"rxjs": "~6.6.2",
"source-map-loader": "^1.0.1",
"tslib": "^1.10.0",
"typescript": "~3.9.7",
"zone.js": "~0.10.2"
},
"devDependencies": {
"#angular-devkit/build-angular": "^0.1000.6",
"#angular/router": "~10.0.9",
"#types/jasmine": "^3.5.12",
"#types/jasminewd2": "~2.0.3",
"#types/node": "^12.12.54",
"codelyzer": "^5.1.2",
"concurrently": "^5.3.0",
"install": "^0.13.0",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~5.0.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~3.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "^6.1.3"
},
"description": "This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.9.",
"main": "karma.conf.js",
"repository": {
"type": "git",
"url": "git+https://gitlab.com/myapp_tool/myapp-client.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://gitlab.com/myapp_tool/myapp-client/issues"
},
"homepage": "https://gitlab.com/myapp_tool/myapp-client#readme"
}
And the server.js file contains:
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
var cors = require('cors');
const app = express();
var corsOptions = {
origin: 'https://backend-api.herokuapp.com',
optionsSuccessStatus: 200
}
//app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname + '/dist/myapp-client')));
//app.use('/webapi',api);
app.get('/webapi', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for Java API!'})
});
app.get('*', (req,res) => {
res.sendFile(path.join(__dirname+'/dist/myapp-client/index.html'));});
//app.get('*', function (req,res) {
//res.sendFile('index.html', {root: '/dist/myapp-client'}));});
//const port = process.env.PORT || '8080';
//app.set('port',port);
//const server = http.createServer(app);
app.listen(process.env.PORT || 8080, function (){
console.log('CORS-enabled API is running on Port:${process.env.PORT || 8080}')
});
The deployed angular app works fine till its having static pages. but when it needs to access the backend-api it is unable to do so.
Like when I want to login and send the userid and password; the request should go like following:
https://myapp-client.herokuapp.com/login ==>> https://backend-api.herokuapp.com/webapi/login
But in the browser console i found that it is actually sending request to:
https://myapp-client.herokuapp.com/webapi/login
The angular app is unable to read the backend-api address; instead adds the rest of the path with it self(can't figure out why????).
I am unable to find any other method apart from proxy.conf.json and cors for dynamic backend api call.
Sorry guys for the long post. But i am unable to find any helpful material from anymore, hence I have explained all the things in more detail. Can anyone please help, I have a deadline hanging on me. Thanks in advance for any help.
Try adding path rewrite property in your proxy configuration like this -
{
context: '/webapi',
pathRewrite: { '^/webapi': '' },
target: "https://backend-api.herokuapp.com",
secure: false,
logLevel: "debug",
changeOrigin: true
}
Hope this might help!

Unable to host MEAN stack application on Heroku

I'm trying to deploy my application, but the problem is that in my root folder, I've two different folders one for back-end and one for front-end.
First of all I tried to push it as it is, just changed the database from local to cloud.
The push was successful, but I was not able to open the app. Got the following error:
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. You can do this from the Heroku CLI with the command
Next, merged both the folders, and made some necessary changes to the routes (followed different tutorials). Now I wasn't able to push even.
Tried a lot of ways, followed and saw different tutorials, read guides and blogs, yet unable to host my application.
My project is working fine in localhost.
Here is my package.json from front-end folder
{
"name": "office-space",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"postinstall": "ng build --aot -prod",
"start":"node server.js"
},
"private": true,
"dependencies": {
"#angular/cli": "~8.1.0",
"#angular/compiler-cli": "~8.1.0",
"#angular/animations": "~8.1.0",
"#angular/common": "~8.1.0",
"#angular/compiler": "~8.1.0",
"#angular/core": "~8.1.0",
"#angular/forms": "~8.1.0",
"#angular/platform-browser": "~8.1.0",
"#angular/platform-browser-dynamic": "~8.1.0",
"#angular/router": "~8.1.0",
"angular-font-awesome": "^3.1.2",
"bootstrap": "^4.3.1",
"font-awesome": "^4.7.0",
"jquery": "^3.4.1",
"material-design-icons": "^3.0.1",
"ngx-pagination": "^4.1.0",
"nonblockjs": "^1.0.8",
"pnotify": "^4.0.0",
"popper.js": "^1.15.0",
"rxjs": "~6.4.0",
"tslib": "^1.9.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"#angular-devkit/build-angular": "~0.801.0",
"#angular/language-service": "~8.1.0",
"#types/jasmine": "~3.3.8",
"#types/jasminewd2": "~2.0.3",
"#types/jquery": "^3.3.30",
"#types/node": "~8.9.4",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.4.3"
},
"engines": {
"node":"12.3.1",
"npm":"6.11.1"
}
}
and here is the package.json from my back-end folder
{
"name": "api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"mongoose": "^5.6.10"
}
}
and finally here is my server file
const express = require('express'),
path = require('path'),
bodyParser = require('body-parser'),
cors = require('cors'),
mongoose = require('mongoose'),
//DB = 'mongodb://localhost:27017/OfficeSpace'
DB = 'mongodb+srv://omersjd:omersjdp#officespace-szwno.mongodb.net/OfficeSpace?retryWrites=true&w=majority'
const employeeRoute = require('./routes/employee.route');
//mongoose.Promise = global.Promise;
mongoose.connect(DB, { useNewUrlParser: true }, (err, response) => {
if (err) {
console.log('Error connecting to Database: ', err)
}
else {
console.log('Connected to ' + DB);
}
});
const app = express();
app.use(express.static(__dirname + "/dist"))
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname + "/dist/OfficeSpace/index.html"))
})
app.use(bodyParser.json());
app.use(cors());
app.use('/', employeeRoute);
let port = process.env.PORT || 4000;
//console.log(employeeRoute);
const server = app.listen(port, function () {
console.log('Listening on port ' + port);
})
here is my directory structure:
├── api (backend folder)
└── frontend-app contents
have you checked the error logs ? you can do this by
heroku logs --tail
the error should be of mongodb connection check it and try to resolve...
hope this helps...

app with combined frontend and backend not deploying to Heroku

I have a angular frontend and nodejs backend app. The issue I am having is when I deploy to Heroku, the build and compile succeeds but I think only the backend is being run on heroku when I click open app. I looked at multiple tutorials and resources on how to deploy an angular and nodejs app on heroku and followed all the instructions but am unable to successfully get the full web app(both angular frontend and nodejs backend to Heroku.
the output I get when navigating to the app from the heroku url is:
{"message":"Invalid Token"}
my package.json is :
{
"name": "eserver",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"main": "server.js",
"heroku-postbuild": "ng build --prod",
"preinstall": "npm install -g #angular/cli #angular/compiler-cli
typescript",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"#angular/animations": "^7.2.11",
"#angular/cdk": "~7.3.3",
"#angular/common": "^7.2.11",
"#angular/compiler": "^7.2.11",
"#angular/core": "^7.2.11",
"#angular/flex-layout": "^7.0.0-beta.24",
"#angular/forms": "^7.2.11",
"#angular/http": "^7.2.11",
"#angular/material": "^7.3.3",
"#angular/platform-browser": "^7.2.11",
"#angular/platform-browser-dynamic": "^7.2.11",
"#angular/router": "^7.2.11",
"#fortawesome/fontawesome-free": "^5.6.3",
"#types/chart.js": "^2.7.42",
"#types/web-bluetooth": "0.0.4",
"angular-bootstrap-md": "^7.4.3",
"body-parser": "^1.18.3",
"bootstrap": "^4.3.1",
"chart.js": "^2.5.0",
"core-js": "^2.5.4",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"express": "^4.16.4",
"hammerjs": "^2.0.8",
"material-design-lite": "^1.3.0",
"ng-multiselect-dropdown": "^0.2.3",
"popper.js": "^1.15.0",
"pusher-js": "^4.4.0",
"rxjs": "^6.4.0",
"#angular-devkit/build-angular": "^0.6.8",
"rxjs-compat": "^6.3.3",
"#angular/compiler-cli": "^7.2.11",
"#angular/cli": "~7.3.7",
"tslib": "^1.9.0",
"uuid": "^3.3.2",
"zone.js": "^0.8.29",
"bcryptjs": "^2.4.3",
"express-jwt": "^5.3.1",
"jsonwebtoken": "^8.2.2",
"mongodb": "^3.0.10",
"mongoose": "^5.1.4",
"pusher": "^2.2.0",
"rootpath": "^0.1.2",
"typescript": "~3.2.4"
},
"devDependencies": {
"#angular/language-service": "^7.2.11",
"#types/jasmine": "~2.8.6",
"#types/jasminewd2": "~2.0.3",
"#types/node": "~8.9.4",
"angular-cli-ghpages": "^0.5.3",
"codelyzer": "~4.2.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~1.7.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.0",
"karma-jasmine": "~1.1.1",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "^5.4.1",
"ts-node": "~5.0.1",
"tslint": "~5.9.1"
}
}
my server.js is:
require('rootpath')();
const express = require('express');
const app = express();
const cors = require('cors');
const bodyParser = require('body-parser');
const jwt = require('./eserver-backend/_helpers/jwt');
const errorHandler = require('./eserver-backend/_helpers/error- handler');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(cors());
// use JWT auth to secure the api
app.use(jwt());
// api routes
app.use('/users', require('./eserver-
backend/users/users.controller'));
app.use('/categories', require('./eserver-
backend/categories/categories.controller'));
app.use('/items', require('./eserver-
backend/items/items.controller'));
app.use('/tableOrder', require('./eserver-
backend/tableOrder/tableOrder.controller'));
app.use('/orders', require('./eserver-
backend/order/order.controller'));
// global error handler
app.use(errorHandler);
// start server
const port = process.env.NODE_ENV === 'production' ? (process.env.PORT || 80) : 4000;
const server = app.listen(port, function () {
console.log('Server listening on port ' + port);
});
my procfile is:
web: node server.js
my file structure is:
file structure
Node.js app should serve the static files in dist folder which were built with ng build
Add the following code in your server.js file.
// Run the app by serving the static files
// in the dist directory
app.use(express.static(__dirname + '/dist'));
// For all GET requests, send back index.html
// so that PathLocationStrategy can be used
app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/dist/index.html'));
});
Adding this to the server.js fixed the issue
app.use(express.static(__dirname + '/dist/angular-registration-login-example'));
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname+'/dist/angular-registration-login-example/index.html'));
});

Heroku nodejs Procfile never picked up

It seems that my nodejs application is never deploying on Heroku. While my build successfully completes with the following message:
[154] ./server.ts 2.1 kB {0} [built]
[238] ./src 160 bytes {0} [built]
[244] (webpack)/buildin/module.js 517 bytes {0} [built]
[259] ./dist/server/main.bundle.js 76.1 kB {0} [built]
+ 301 hidden modules
Node server listening on http://localhost:5000
I'm only just seeing Heroku's Blank app:
Other symptoms:
My builds never end:
And no dynos are being instantiated:
This is despite the fact that I'm providing a Procfile, like so:
web: npm start
See my package.json:
{
"name": "vivonslagrasse-app",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "node dist/server.js",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"universal": "ng build --prod --aot && ng build --prod --app ssr --output-hashing=false && webpack --config webpack.server.config.js --progress --colors && node dist/server.js",
"postinstall": "npm run universal"
},
"private": true,
"dependencies": {
"#angular/animations": "^5.2.0",
"#angular/common": "^5.2.0",
"#angular/compiler": "^5.2.0",
"#angular/core": "^5.2.0",
"#angular/forms": "^5.2.0",
"#angular/http": "^5.2.0",
"#angular/platform-browser": "^5.2.0",
"#angular/platform-browser-dynamic": "^5.2.0",
"#angular/platform-server": "^5.2.9",
"#angular/router": "^5.2.0",
"#nguniversal/module-map-ngfactory-loader": "^5.0.0-beta.8",
"#ngx-translate/core": "^9.1.1",
"#ngx-translate/http-loader": "^2.0.1",
"#nicky-lenaers/ngx-scroll-to": "^0.6.0",
"ngx-cookie": "^2.0.1",
"core-js": "^2.4.1",
"foundation-sites": "^6.4.4-rc1",
"rxjs": "^5.5.6",
"ts-loader": "^3.5.0",
"xmlhttprequest": "^1.8.0",
"zone.js": "^0.8.19"
},
"devDependencies": {
"#angular/cli": "~1.7.0",
"#angular/compiler-cli": "^5.2.0",
"#angular/language-service": "^5.2.0",
"#types/jasmine": "~2.8.3",
"#types/jasminewd2": "~2.0.2",
"#types/jquery": "^3.3.1",
"#types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~4.1.0",
"tslint": "~5.9.1",
"typescript": "~2.5.3"
},
"engines": {
"node": "7.7.4",
"npm": "5.6.0"
}
}
Note that I need to run a node server since this is an angular universal app and the initial page's contents need to be server-generated.
EDIT: I'm adding my server.ts file (the generated server.js is too long to be reproduced here)
// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { renderModuleFactory } from '#angular/platform-server';
import { enableProdMode } from '#angular/core';
import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
(global as any).XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const PORT = process.env.PORT || 5000;
const DIST_FOLDER = join(process.cwd(), 'dist');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main.bundle');
const {provideModuleMap} = require('#nguniversal/module-map-ngfactory-loader');
app.engine('html', (_, options, callback) => {
renderModuleFactory(AppServerModuleNgFactory, {
// Our index.html
document: template,
url: options.req.url,
// DI so that we can get lazy-loading to work differently (since we need it to just instantly render it)
extraProviders: [
provideModuleMap(LAZY_MODULE_MAP)
]
}).then(html => {
callback(null, html);
});
});
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render(join(DIST_FOLDER, 'browser', 'index.html'), {req});
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
Needless to say, this setup works perfectly on my development machine...
Your help will be highly appreciated. I already spent 2,5 hours on this.
Use process.env.port in server.js to listen
const port = process.env.port || 5000;
app.listen(port);

Deploy Angular 4 / NodeJS to Heroku

I would deploy my Web app to Heroku.
this is the tree of my project :
├── client // Angular project is Here
├── db
├── express-admin
├── index.js
├── node_modules
├── package.json
├── package-lock.json
├── port
├── Procfile
├── README.md
├── routes
└── test.html
I have made these steps :
1) Build Angular 4 app by using ng build -prod --aot=false
2 ) Point Nodejs app to Angular index.html file in /dist folder.
Here's the index.js file:
// Get dependencies
const express = require('express');
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
var cool = require('cool-ascii-faces');
//var db = require('./db/connect.js');
// Get our API routes
//const api = require('./server/routes/api');
var appRoutes = require('./routes/index');
const app = express();
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
// Point static path to dist
app.use(express.static(path.join(__dirname, 'client/dist/')));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.use('/', appRoutes)
// Set our api routes
//app.use('/api', api);
// Catch all other routes and return the index file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'client/dist/index.html'));
});
app.get('/cool', function(request, response) {
response.send(cool());
});
/**
* Get port from environment and store in Express.
*/
const port = process.env.PORT || '4001';
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port, () => console.log(`API running on localhost:${port}`));
3) I Used the official Heroku Guide to deploy NodeJS app
When I open the link generated by Heroku , the index page get loaded but when I try to use login I get this error:
Mixed Content: The page at 'https://lit-island-95274.herokuapp.com/signup' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://localhost:4001/login'. This request has been blocked; the content must be served over HTTPS.
This is my Angular Package.json file :
{
"name": "projecttt",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"#angular/animations": "^4.1.2",
"#angular/common": "^4.1.2",
"#angular/compiler": "^4.1.2",
"#angular/core": "^4.1.2",
"#angular/flex-layout": "^2.0.0-beta.7",
"#angular/forms": "^4.1.2",
"#angular/http": "^4.1.2",
"#angular/material": "2.0.0-beta.4",
"#angular/platform-browser": "^4.1.2",
"#angular/platform-browser-dynamic": "^4.1.2",
"#angular/router": "^4.1.2",
"angular-2-local-storage": "^1.0.1",
"hammerjs": "^2.0.8",
"core-js": "^2.4.1",
"rxjs": "^5.4.1",
"systemjs": "^0.20.14",
"typings": "^2.1.1",
"zone.js": "^0.8.4"
},
"devDependencies": {
"#angular/cli": "^1.4.7",
"#angular/compiler-cli": "^4.4.0",
"#angular/language-service": "^4.0.0",
"#types/jasmine": "~2.5.53",
"#types/jasminewd2": "~2.0.2",
"#types/node": "^8.0.7",
"codelyzer": "~3.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"lite-server": "^2.2.2",
"lodash": "^4.16.4",
"protractor": "~5.1.2",
"rimraf": "^2.5.4",
"ts-node": "~3.0.4",
"tslint": "~5.3.2",
"typescript": "^2.3.4"
},
"repository": {},
"main": "karma-test-shim.js"
}
If I had well understood, Angular http routes didn't get deployed because Heroku is not building Angular app, but How to do it ?.
By default heroku does not install any dev dependency therefore move your
"#angular/cli": "^1.4.7",
"#angular/compiler-cli": "^4.4.0",
"typescript": "^2.3.4"
to dependency section and then you can deploy.
As those dependency was in devDependency so heroku could not find those library which causes deployment unsuccessfull.
Hope that helps you.
I have recently deploy Angular app on heroku. My package.json look something like this.
{
"name": "porfolio",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "node app.js",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"postinstall": "ng build --aot -prod"
},
"private": true,
"dependencies": {
"#angular/animations": "^5.2.0",
"#angular/cli": "1.6.8",
"#angular/common": "^5.2.0",
"#angular/compiler": "^5.2.0",
"#angular/compiler-cli": "^5.2.0",
"#angular/core": "^5.2.0",
"#angular/forms": "^5.2.0",
"#angular/http": "^5.2.0",
"#angular/platform-browser": "^5.2.0",
"#angular/platform-browser-dynamic": "^5.2.0",
"#angular/router": "^5.2.0",
"#ng-bootstrap/ng-bootstrap": "^2.0.0",
"bootstrap": "^3.3.7",
"core-js": "^2.4.1",
"express": "^4.16.3",
"font-awesome": "^4.7.0",
"jquery": "^3.3.1",
"ng-teximate": "^0.6.3",
"path": "^0.12.7",
"rxjs": "^5.5.6",
"typescript": "~2.5.3",
"zone.js": "^0.8.19"
},
"devDependencies": {
"#angular/language-service": "^5.2.0",
"#types/jasmine": "~2.8.3",
"#types/jasminewd2": "~2.0.2",
"#types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.8.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~2.0.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~4.1.0"
},
"engines": {
"node": "8.9.4",
"npm": "5.6.0"
}
}
Your start should be node fileName.js. And postinstall will build your application before deploy used by heroku. You also need to add engines which tells which version of engine you was running.
And as pointed out by #monsur you have to add some devDependencies to dependencies which is used by heroku.

Resources