top of page
Blog Page(1902x420).jpg

Keep your business ahead with

Insights That Drive Innovation

How To Develop and Build Angular App With NodeJS

In this post, we will see the details and implementation with NodeJS. We will go through step by step with an example.


  • Introduction

  • Prerequisites

  • Example Project

  • Just Enough NodeJS For This Project

  • Development Phase

  • How To Build Project For Production

  • How To Package Project For Production

  • Deploying On AWS Elastic Beanstalk

  • Deploying On AWS ECS

  • Summary

  • Conclusion





Introduction

Angular is a javascript framework for building web apps and it doesn’t load itself in the browser. We need some kind of mechanism that loads the index.html (single page) of Angular with all the dependencies(CSS and js files) in the browser. In this case, we are using node as the web server which loads Angular assets and accepts any API calls from the Angular app.



If you look at the above diagram all the web requests without the /api will go to Angular routing. All the paths that contain /api will be handled by the Node server.


In this post, we are going to develop an Angular app with NodeJS and see how to build for production.


Prerequisites

There are some prerequisites for this article. You need to have nodejs installed on your laptop and how http works. If you want to practice and run this on your laptop you need to have these on your laptop.


  • NodeJS

  • Angular CLI

  • Typescript

  • VSCode


Example Project

This is a simple project which demonstrates developing and running Angular applications with NodeJS. We have a simple app in which we can add users, count, and display them at the side, and retrieve them whenever you want.


As you add users we are making an API call to the nodejs server to store them and get the same data from the server when we retrieve them. You can see network calls in the following video.


Here is a Github link to this project. You can clone it and run it on your machine.


// clone the project

// install and start the project

npm install

npm start


Just Enough NodeJS For This Project

If you are new to NodeJS don’t worry this short description is enough to get you started with this project. If you are already aware of NodeJS, you can skip this section.


NodeJS is an asynchronous event-driven javascript runtime environment for server-side applications. The current version of the node js is 12 and you can install it from this link here. You can click on any LTS link and the NodeJS package is downloaded and you can install it on your laptop.


You can check the version of the Node with this command node -v. You can run javascript on the node REPL by typing the command node on the CLI.



The installation of a node is completed and you know how to run javascript. You can even run javascript files. For example, Let’s put the above commands in the sample.js file and run it with this command node sample.js.


var x = 10;

var y = 20;

var z = x + y;

console.log(z);



Development Phase

Usually, the way you develop and the way you build and run in production are completely different. That's Why, I would like to define two phases: The development phase and the Production phase.


In the development phase, we run the NodeJS server and the Angular app on completely different ports. It’s easier and faster to develop that way. If you look at the following diagram the Angular app is running on port 4200 with the help of a webpack dev server and the NodeJS server is running on port 3080.



Project Structure

Let’s understand the project structure for this project. We will have two package.json: one for Angular and another for node js API. It’s always best practice to have completely different node_modules for each one. In this way, you won’t get merging issues or any other problems regarding web and server node modules collision.



If you look at the above project structure, all the Angular app resides under the my-app folder and nodejs API resides under the root folder. You can have a separate folder for nodejs API as well.


NodeJS API


We use the express and nodemon on the server-side. Express is the Fast, unopinionated, minimalist web framework for NodeJS and nodemon is the library which makes your API reloads automatically whenever there is a change in the files. Let’s install these two dependencies. nodemon is only used for development so install this as a dev dependency.


npm install express --save

npm install nodemon --save-dev


Here is the package.json of node js.

{

"name": "angular-nodejs-example",

"version": "1.0.0",

"description": "node server",

"main": "index.js",

"scripts": {

"start": "node index.js",

"dev": "nodemon ./server.js localhost 3080",

"test": "echo \"Error: no test specified\" && exit 1"

},

"repository": {

"type": "git",

},

"author": "Justin",

"license": "ISC",

"bugs": {

},

"dependencies": {

"express": "^4.17.1"

},

"devDependencies": {

"nodemon": "^2.0.2"

}

}


Now we need to create a file name (server.ts) where we create a server and render Api endpoint here.


import express from "express";

import * as http from "http";

// import * as bodyParser from "body-parser";

import {AppHttpResponses} from "./_models/app.http.responses";

import path from "path";

import compression = require("compression");

require("dotenv").config();


// Here is an example route where you can import the Api’s routesConfig file.

Import { HomeRoutes } from “./Home/Home.routes.config.js”;

const responseMsgs = AppHttpResponses.HttpStatusObj;

const app: express.Application = express();

const server: http.Server = http.createServer(app);

const port: any = process.env.PORT || "8000";

const routes: any = [];


app.use(

function (req, res, next) {

res.header(

"Access-Control-Allow-Headers",

"Origin, X-Requested-With, Content-Type, Accept, signature, iv, authorization"

);

next();

},

compression({}),

express.json({limit: "5mb"}),

helmet()

);


app.use("/", express.static(path.join(__dirname, "../public")));


// Here Router for different part of application

routes.push(new HomeRoutes (app))

app.use("/robots.txt", function (req, res, next) {

res.type("text/plain");

res.sendFile(__dirname + "./public/robots.txt");

});


app.get("*", function (req, res, next) {

res.sendFile(path.resolve("./public/index.html"), function (err) {

if (err) {

return res

.status(200)

.send({success:true, msg: ‘successful’});

}

});

});


app.disable("x-powered-by");


server.listen(port, () => {

console.log(`Server running at port ${port}`);

});

});


Angular-app


Now we create an angular-app using this command

Step:1

ng new your new project

Step:2


npm install


Step:3


Now we have a angular.json file in this file we need to change the OutPath You have to add a path where you build the angular


  "build": {

"builder": "@angular-devkit/build-angular:browser",

"options": {

"outputPath": "../node-app/public",

"index": "src/index.html",

"main": "src/main.ts",

"polyfills": "src/polyfills.ts",

"tsConfig": "tsconfig.app.json",

"aot": true,

"assets": [

"src/favicon.ico",

"src/assets",

"src/sitemap.xml",

"src/robots.txt"

],

},

}

Step:4


Now run this command in your terminal ng build


  • Now it runs and creates a public folder with an index.html file in our node-app folder.



Step:5


In Node-app some changes in package.Json file given below


Here we edit the main and script json, change path of start , add Keywords too .


{

"name": "Industry name",

"version": "1.0.0",

"description": "REST API ExpressJS NodeJS",

"main": "dist/server.js",

"scripts": {

"tsc": "tsc",

"start": "node ./dist/server.js",

"test": "echo \"Error: no test specified\" && exit 1",

"create-env": "printenv > .env"

},

"keywords": [

"REST",

"API",

"ExpressJS",

"NodeJS"

],

}


Angular App

Now the nodejs API is running on port 3080. Now it’s time to look at the Angular app. The entire Angular app is under the folder my-app. You can create with this command ng new my-app. I am not going to put all the files here you can look at the entire files in the above Github link or here.


Let’s see some important files here. Here is the service file which calls node API.


import { Injectable } from '@angular/core';

import { HttpClient } from '@angular/common/http';


@Injectable({

providedIn: 'root'

})

export class AppService {


constructor(private http: HttpClient) { }


rootURL = '/api';


getUsers() {

return this.http.get(this.rootURL + '/users');

}


addUser(user: any) {

return this.http.post(this.rootURL + '/user', {user});

}


}


Here is the app component which subscribes to these calls and gets the data from the API.



import { Component, OnDestroy } from '@angular/core';

import { FormGroup, FormControl, Validators } from '@angular/forms';

import { AppService } from './app.service';

import { takeUntil } from 'rxjs/operators';

import { Subject } from 'rxjs';


@Component({

selector: 'app-root',

templateUrl: './app.component.html',

styleUrls: ['./app.component.css']

})

export class AppComponent implements OnDestroy {


constructor(private appService: AppService) {}


title = 'angular-nodejs-example';


userForm = new FormGroup({

firstName: new FormControl('', Validators.nullValidator && Validators.required),

lastName: new FormControl('', Validators.nullValidator && Validators.required),

email: new FormControl('', Validators.nullValidator && Validators.required)

});


users: any[] = [];

userCount = 0;


destroy$: Subject<boolean> = new Subject<boolean>();


onSubmit() {

this.appService.addUser(this.userForm.value).pipe(takeUntil(this.destroy$)).subscribe(data => {

console.log('message::::', data);

this.userCount = this.userCount + 1;

console.log(this.userCount);

this.userForm.reset();

});

}


getAllUsers() {

this.appService.getUsers().pipe(takeUntil(this.destroy$)).subscribe((users: any[]) => {

this.users = users;

});

}


ngOnDestroy() {

this.destroy$.next(true);

this.destroy$.unsubscribe();

}

}


Interaction between Angular and Node API

In the development phase, the Angular app is running on port 4200 with the help of a webpack dev server and nodejs API running on port 3080.


There should be some interaction between these two. We can proxy all the API calls to nodejs API. Angular provides an inbuilt proxying method. First, we need to define the following proxy.conf.json under my-app folder.


{

"/api": {

"secure": false

}

}


If you look at the file, all the paths that start with /api will be redirected to http://localhost:3080 where the nodejs API running. Then, you need to define in angular.json under the serve part with the proxyConfig key. Here is the complete angular.json file.



Once this is configured, you can run the Angular app on port 4200 and NodeJS API on 3080 still make them work together.


// nodejs API (Terminal 1)

npm run dev

// Angular app (Terminal 2)

npm start


How To Build Project For Production

The Angular app runs on the port 4200 with the help of a webpack dev server. This is not the case for running in production. We have to build the Angular project and load those static assets with the node server. Let’s see those step by step here.


First, we need to build the Angular project with this command npm run build and all the built assets will be put under the dist folder.



Second, we need to make some changes on the server-side. Here is the modified server.js file.


  • We have to use express.static at line number 9 to let express know there is a dist folder and assets of the Angular build.

  • Load index.html for the default route / at line number 22


const express = require('express');

const app = express(),

bodyParser = require("body-parser");

port = 3080;


const users = [];


app.use(bodyParser.json());

app.use(express.static(process.cwd()+"/my-app/dist/angular-nodejs-example/"));


app.get('/api/users', (req, res) => {

res.json(users);

});


app.post('/api/user', (req, res) => {

const user = req.body.user;

users.push(user);

res.json("user added");

});


app.get('/', (req,res) => {

res.sendFile(process.cwd()+"/my-app/dist/angular-nodejs-example/index.html")

});


app.listen(port, () => {

console.log(`Server listening on the port::${port}`);

});


Once you are done with the above changes, you can actually run the whole app with the nodejs server running on port 3080 like below as nodejs acts as a web server as well.



Summary

  • There are so many ways we can build Angular apps and ship them for production.

  • One way is to build Angular with NodeJS.

  • In the development phase, we can run Angular and Nodejs on separate ports.

  • The interaction between these two happens with proxying all the calls to API.

  • In the production phase, you can build the Angular app and put all the assets in the dist folder and load it with the node server.

  • Nodejs act as a web server as well in the above case. You need to let express know where all the Angular assets are.

  • We can package the application in a number of ways.

  • You can deploy the packaged zip folder in any node environment.


Conclusion

This is one way of building and shipping Angular apps. This is really useful when you want to do server-side rendering or you need to do some processing. NodeJS is non-blocking IO and it is very good for normal websites as well. In future posts, I will discuss more on deploying strategies for this kind of architecture.

Looking to build and deploy powerful web applications with cutting-edge technologies like Angular and NodeJS? At Cloud Science Labs, we specialize in creating scalable, robust, and efficient web solutions tailored to your business needs. Whether you're developing for production, deploying on AWS, or need expert advice on server-side rendering, our team is here to help you succeed.

Comments


bottom of page