Heroku nodejs Procfile never picked up - node.js

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);

Related

Trying to deploy Angular 8 app to Heroku - build successful but heroku saying 'Not Found'

I am trying to deploy my angular app to heroku, the builds are successful but when i go to my link, it is telling me 'Not Found'. I am really confused as to what is going on because I have visited various websites which go through the steps and I am sure that I am following the steps properly.
I have a procfile which has
web: node server.js
My package.json looks like this -
{
"name": "ng-barry-project",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "node server.js",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"heroku-postbuild": "ng build --aot --prod"
},
"private": true,
"dependencies": {
"#angular/animations": "~8.2.0",
"#angular/cli": "^8.3.17",
"#angular/common": "~8.2.0",
"#angular/compiler": "~8.2.0",
"#angular/compiler-cli": "^8.2.13",
"#angular/core": "~8.2.0",
"#angular/forms": "~8.2.0",
"#angular/platform-browser": "~8.2.0",
"#angular/platform-browser-dynamic": "~8.2.0",
"#angular/router": "~8.2.0",
"#fortawesome/angular-fontawesome": "^0.5.0",
"#fortawesome/fontawesome-svg-core": "^1.2.25",
"#fortawesome/free-solid-svg-icons": "^5.11.2",
"express": "^4.17.1",
"path": "^0.12.7",
"rxjs": "~6.4.0",
"tslib": "^1.10.0",
"typescript": "~3.5.3",
"zone.js": "~0.9.1"
},
"devDependencies": {
"#angular-devkit/build-angular": "~0.802.2",
"#angular/cli": "^8.3.17",
"#angular/compiler-cli": "^8.2.13",
"#angular/language-service": "~8.2.0",
"#types/jasmine": "~3.3.8",
"#types/jasminewd2": "~2.0.3",
"#types/node": "~8.9.4",
"codelyzer": "^5.0.0",
"enhanced-resolve": "^3.3.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.5.3"
},
"engines": {
"node": "12.9.1",
"npm": "6.10.2"
}
}
This is my server.js file
//Install express server
const express = require('express');
const path = require('path');
const app = express();
// Serve only the static files form the dist directory
app.use(express.static('./dist/pi-project'));
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname,'/dist/pi-project/index.html'));
});
// Start the app by listening on the default Heroku port
app.listen(process.env.PORT || 8080);
Please try like this .click here
Everything seems correct, just cross check the following points if it may help
You might get error running the postinstall command. This works instead:
heroku-postbuild": "ng build --prod
Node and npm engine should be same version you have on your machine. So, run node -v and npm -v to get the correct version and include it in your package.json
This worked for me for angular 6 and angular 7 deployment on heroku.
Try this- https://www.youtube.com/watch?v=hE1i_LhL_Nc
Updated Answer
You need a couple of Edits to your server.js file
Change this:
app.use(express.static('./dist/pi-project'));
To This:
app.use(express.static(path.join(__dirname,'./dist/pi-project')));
And Change this:
app.get('/*', function(req,res) {
To this
app.get('/', function(req,res) {
so that not all requests are serviced by this function
Original Answer
In your server.js you have the following:
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname,'/dist/pi-project/index.html'));
});
Because of the asterisk after the /, that's saying to return the index.html file for every request that comes in. So what will happen is that you'll first make a request to localhost:8080 and that will return the index.html (so far so good). Then the browser will read the <script> tags from the index.html and for each one it will make another request. So let's say the next request will be to localhost:8080/main.js. When express sees that it will AGAIN return index.html which obviously isn't what you want.
To fix that problem you can change your server.js to this:
//Install express server
const express = require('express');
const path = require('path');
const app = express();
// Serve only the static files form the dist directory
app.use(express.static('./dist/pi-project'));
app.get('/*', function(req,res) {
if(req.url === '/') {
res.sendFile(path.join(__dirname,'/dist/pi-project/index.html'));
}
else {
res.sendFile(path.join(__dirname, '/dist/pi-project' + req.url))
}
});
// Start the app by listening on the default Heroku port
app.listen(process.env.PORT || 8080);

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'));
});

Run a script with ng server Angular 6

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",

"HMR is not enabled for webpack-dev-server " error in heroku

I've deployed my angular app over Heroku. The build is successful but when I visit my app's URL
In the browser console. An error has occurred i.e., HMR is not enabled for webpack-dev-server! Are you using the --hmr flag for ng serve?. Why is it so?
My main.ts
import { enableProdMode } from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment.hmr';
import {hmrBootstrap} from './hmr';
if (environment.production) {
enableProdMode();
}
const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
if (environment.hmr) {
if (module[ 'hot' ]) {
hmrBootstrap(module, bootstrap);
} else {
console.error('HMR is not enabled for webpack-dev-server!');
console.log('Are you using the --hmr flag for ng serve?');
}
} else {
bootstrap();
}
My package.json file
{
"name": "demo-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"start": "node server.js",
"hmr": "ng serve --hmr -e=hmr",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test",
"pree2e": "webdriver-manager update",
"e2e": "protractor",
"postinstall": "ng build --aot -prod"
},
"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/router": "^5.2.0",
"#ng-select/ng-select": "^1.3.0",
"bootstrap": "^4.1.0",
"core-js": "^2.4.1",
"enhanced-resolve": "^4.0.0",
"express": "^4.16.3",
"moment": "^2.22.1",
"ngx-bootstrap": "^2.0.4",
"ngx-google-places-autocomplete": "^2.0.1",
"path": "^0.12.7",
"rxjs": "^5.5.6",
"typescript": "~2.5.3",
"web-animations-js": "^2.3.1",
"zone.js": "^0.8.19"
},
"devDependencies": {
"#angular/cli": "^1.7.4",
"#angular/compiler-cli": "^5.2.10",
"#angular/language-service": "^5.2.0",
"#angularclass/hmr": "^2.1.3",
"#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",
"tslint": "~5.9.1",
"typescript": "~2.5.3"
},
"engines": {
"node": "8.4.0",
"npm": "5.3.0"
}
}
and my server.js path is demo_project > server.js
server.js
//Install express server
const express = require('express');
const path = require('path');
const app = express();
// Serve only the static files form the dist directory
app.use(express.static(__dirname + '/dist'));
app.get('/*', function(req,res) {
res.sendFile(path.join(__dirname+'/dist/index.html'));
});
// Start the app by listening on the default Heroku port
app.listen(process.env.PORT || 8080);
I don't know if this is a perfect solution for the question or just a workaround, but it works. All I have to is to change my main.ts file as:
import { enableProdMode } from '#angular/core';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment.hmr';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
A better solution would be to
`const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);
if (environment.hmr === true) {
if (module['hot']) {
hmrBootstrap(module, bootstrap);
} else {
bootstrap().catch((err) => console.log(err));
}
} else {
bootstrap().catch((err) => console.log(err));
}
`
This would enable hmr based on environment configuration.

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