So, you’ve built this really awesome Angular app, now what? Oh, you want to deploy it using Heroku. Easy peasey but there are a few gotcha’s to look out for. Running an Angular app locally we just run: ng serve -o But Heroku doesn’t work that way it needs to know how to serve up the app. We need to install a couple of packages and modify our project to make this work. The following steps should get the app up and running on Heroku just fine. First let’s make sure you are running the latest version of Angular CLI and the Angular Compiler CLI. Open a terminal session in the root folder of your project and run this: npm install @angular/cli@latest @angular/compiler-cli –save-dev So what did we just do? We installed (or updated) Angular CLI and the Angular CLI Compiler to the latest version the –save-dev added the necessary entries to the package.json which we now need to modify. Open the package.json with your favorite editor and scroll down to the devDependencies section. Move these two entries up into the Depencies section: “@angular/cli”: “^7.3.9”, “@angular/compiler-cli”: “^7.2.15”, Pay attention to the formatting and make sure you have commas where commas are needed etc. Notice the ^ symbol before the version numbers? That indicates that the version number shown is the lowest version that can be used but higher versions are allowed. Since this is an Angular app we also want to move the typescript entry up from the devDependecies to the Dependencies section. In my package.json it looks like this: “typescript”: “~3.2.2”, Now we need to tell Heroku how to build the app when it’s deployed. In the scripts section of the package.json add the following line: “postinstall”: “ng build –aot –prod” This tells Heroku to use the Ahead Of Time compiler and make the app production ready. This will create the /dist folder where all the javascripts and html are launched from. Ok now back in terminal type in: npm -v followed by node -v Make a note of the version numbers for both. We need to create an entry at the bottom of the package.json to tell Heroku what engines to use. Format the engine entry like this: “engines”: { “node”: “8.9.0”, “npm”: “6.10.2” } Paste this into the package.json right after the devDepencies section. Be sure to add a comma after the closing } for the devDepencies section. My package.json is pasted way below as an example. Since we can’t run ng serve on Heroku we need to a way to serve the app. We’ll install Express server to handle that for us. Back in terminal run: npm install express path –save This will install Express and create the entry in the package.json for us. Verify that the entry has been created in package.json it should like similar to mine: “express”: “^4.17.1”, Now go back to terminal and type in: touch server.js This creates an empty server javascript file. Open server.js with your favorite editor and paste the following into it: //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/your-app’)); app.get(‘/*’, function(req,res) { res.sendFile(path.join(__dirname+’/dist/your-app/index.html’)); }); // Start the app by listening on the default Heroku port app.listen(process.env.PORT || 8080); Replace your-app with the name of your app.
(you will use the name of the sub-folder located in /dist ) Now back in package.json modify (or add) the start entry located in the scripts section to this: “start”: “node server.js” Now save your changes and push them back Gitlab: git add .
git commit -m “updates to deploy to heroku”
git push Following your push check your pipelines and see if the deployment to Heroku was successful. If so go to Heroku and check out your awesome app! If not rewind, start from the top , and double check everything. My package.json: { “name”: “my-app”, “version”: “0.0.0”, “scripts”: { “ng”: “ng”, “start”: “node server.js”, “build”: “ng build”, “test”: “ng test”, “lint”: “ng lint”, “e2e”: “ng e2e”, “postinstall”: “ng build –aot –prod” }, “private”: true, “dependencies”: { “@angular/animations”: “^7.2.15”, “@angular/cli”: “^7.3.9”, “@angular/common”: “^7.2.15”, “@angular/compiler”: “^7.2.15”, “@angular/compiler-cli”: “^7.2.15”, “@angular/core”: “^7.2.15”, “@angular/forms”: “^7.2.15”, “@angular/platform-browser”: “^7.2.15”, “@angular/platform-browser-dynamic”: “^7.2.15”, “@angular/router”: “^7.2.15”, “bootstrap”: “^3.3.7”, “core-js”: “^2.6.10”, “express”: “^4.17.1”, “rxjs”: “~6.3.3”, “tslib”: “^1.10.0”, “typescript”: “~3.2.2”, “zone.js”: “~0.8.26” }, “devDependencies”: { “@angular-devkit/build-angular”: “^0.13.9”, “@angular/language-service”: “^7.2.15”, “@types/jasmine”: “~2.8.8”, “@types/jasminewd2”: “^2.0.8”, “@types/node”: “~8.9.4”, “codelyzer”: “~4.5.0”, “jasmine-core”: “~2.99.1”, “jasmine-spec-reporter”: “~4.2.1”, “karma”: “~4.0.0”, “karma-chrome-launcher”: “~2.2.0”, “karma-coverage-istanbul-reporter”: “^2.0.6”, “karma-jasmine”: “~1.1.2”, “karma-jasmine-html-reporter”: “^0.2.2”, “protractor”: “~5.4.0”, “ts-node”: “~7.0.0”, “tslint”: “~5.11.0” }, “engines”: { “node”: “8.9.0”, “npm”: “6.10.2” } } #CS@Worcester #CS448
From the blog Michael Duquette by Michael Duquette and used with permission of the author. All other rights reserved by the author.