In this tutorial, I will show you step by step to integrate Angular 8 project with Node.js Restful Services so that we only need to run both on same Server/Port. You will also know how to configure Angular SPA Routing to avoid 404 on refresh.
Related Posts:
– Angular 8 + Node.js Express + MySQL example
– Angular 8 + Node.js Express + PostgreSQL example
– Angular 8 + Node.js Express + MongoDB example
– Node.js Express + Angular 8: JWT Authentication & Authorization example
– Angular 8 upload file/image to Node.js Server example
Newer versions:
– Integrate Angular 11/10 with Node.js Restful Services
– Integrate Angular 15/14/13/12 with Node.js Restful Services
Contents
- Angular 8 & Node.js Express Application Overview
- Technology Stack
- Setup Angular Client
- Setup Node.js Express Server
- Integrate Angular with Node.js Restful Services
- Serve Angular App with Express
- Run Node Express server & Angular on the same Port
- Express & Angular: Refresh page error 404
- Conclusion
- Further Reading
- Source Code
Angular 8 & Node.js Express Application Overview
Assume that we have 2 separated projects: Angular 8 & Node.js Express like this-
For example, if we run them separately:
- Node.js Server exports Restful Services at Url:
http://localhost:8080/
- Angular Client runs at url:
http://localhost:8081/
Using Angular 8 to call Node.js Rest API:
Otherwise, when deploying Angular production-build with Node.js Express project, we only need to run Node Project for the fullstack (Angular + Node) system.
In this example, we access http://localhost:8080/
.
Technology Stack
- Node.js
- Express
- Angular 8
Setup Angular Client
You can use your own Angular Project, or just download the source code on Github, or follow these steps to create a new one.
Open cmd and use Angular CLI to create a new Angular Project as following command:
ng new Angular8Client
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
We also need to generate some Components and Services:
ng g s services/tutorial
ng g c components/add-tutorial
ng g c components/tutorial-details
ng g c components/tutorials-list
Now you can see that our project directory structure looks like this-
Because I want to keep this tutorial simple and brief, please continue to develop this App with instruction in the post:
Angular 8 CRUD Application example with Web API
Setup Node.js Express Server
You can use your own Node.js Project, or just download the source code on Github, or follow these steps to create a new one.
First, we create a folder:
$ mkdir angular-8-node-js-example
$ cd angular-8-node-js-example
Next, we initialize the Node.js App with a package.json file:
npm init
name: (angular-8-node-js-example)
version: (1.0.0)
description: Integrate Angular 8 with Node.js example
entry point: (index.js) server.js
test command:
git repository:
keywords: angular, angular 8, nodejs, express, sequelize, rest api, restful services
author: bezkoder
license: (ISC)
Is this ok? (yes) yes
The instruction can be found in one of the posts:
– Node.js Rest APIs example with Express, Sequelize & MySQL
– Node.js Rest APIs example with Express, Sequelize & PostgreSQL
– Node.js Rest APIs example with Express, Sequelize & MongoDb
Let’s continue to the most important part.
Integrate Angular with Node.js Restful Services
Build Angular 8 App
Currently Angular Client and Spring Boot server work independently on ports 8081
and 8080
.
The first thing we need to do is to build Angular App for production.
There are 2 steps:
– Set the output directory to static folder:
Open angular.json, add the "outputPath": "./static"
option to the build
target so that the production will be stored in static folder under project root directory.
{
...
"projects": {
"Angular8ClientCrud": {
...
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "./static",
"index": "src/index.html",
"main": "src/main.ts",
...
},
"configurations": {
...
}
},
...
}
}},
"defaultProject": "Angular8ClientCrud"
}
– Run command ng build --prod
.
Generating ES5 bundles for differential loading...
ES5 bundle generation complete.
chunk {2} polyfills-es2015.5b10b8fd823b6392f1fd.js (polyfills) 36.2 kB [initial] [rendered]
chunk {3} polyfills-es5.8e50a9832860f7cf804a.js (polyfills-es5) 126 kB [initial] [rendered]
chunk {0} runtime-es2015.c5fa8325f89fc516600b.js (runtime) 1.45 kB [entry] [rendered]
chunk {0} runtime-es5.c5fa8325f89fc516600b.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main-es2015.1fc85a54f08d1dacb8cd.js (main) 280 kB [initial] [rendered]
chunk {1} main-es5.1fc85a54f08d1dacb8cd.js (main) 345 kB [initial] [rendered]
chunk {4} styles.3ff695c00d717f2d2a11.css (styles) 0 bytes [initial] [rendered]
Date: 2020-05-30T15:34:14.655Z - Hash: 86d212a6faf72b219de3 - Time: 90679ms
Now you can see new static folder with content as following:
Integrate Angular 8 production with Node.js Project
In app folder of Node.js Express Project, let’s create views folder.
app
config
controllers
models
routes
views
index.js
package.json
server.js
Now we need to copy all files from Angular static folder to app/views folder above.
The final Node.js Project folder structure will be like this:
Serve Angular App with Express
We’re gonna serve static files such as HTML files, CSS files and JavaScript files in app/views folder using the express.static()
built-in middleware function.
const express = require("express");
const path = __dirname + '/app/views/';
const app = express();
app.use(express.static(path));
The final step is to deliver index.html file using res.sendFile()
. We will need to pass in a path to the file.
// const path = __dirname + '/app/views/';
app.get('/', function (req,res) {
res.sendFile(path + "index.html");
});
Now content in server.js file is like this-
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const path = __dirname + '/app/views/';
const app = express();
app.use(express.static(path));
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const db = require("./app/models");
db.sequelize.sync();
app.get('/', function (req,res) {
res.sendFile(path + "index.html");
});
require("./app/routes/turorial.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
Run Node Express server & Angular on the same Port
Run the Node.js Express server (including Angular 8 client) with commands:
node server.js
Open browser with url: http://localhost:8080/
.
Now you can see the result:
Express & Angular: Refresh page error 404
Oh yeah! Everything looks good.
But wait, let’s try to refresh the page.
What happened?
To handle this error, we’re gonna enable hash(#) in App Routing module.
– Open app-routing.module.ts
– Pass optional parameter useHash
as true
value.
@NgModule({
imports: [RouterModule.forRoot(routes, {useHash: true})],
exports: [RouterModule]
})
Our Url is hashed(#) after port number: http://localhost:8080/#/tutorials
Now you can refresh the page without worrying about 404.
Conclusion
Today we’ve learned how to integrate Angular 8 with Node.js Restful Services on same Server/Port. We also handle the case Refresh page error by adding hash(#) to the urls.
There are many Angular 8 + Node.js examples that you can apply this approach to integrate:
– Angular 8 + Node.js Express + MySQL example
– Angular 8 + Node.js Express + PostgreSQL example
– Angular 8 + Node.js Express + MongoDB example
– Node.js Express + Angular 8: JWT Authentication & Authorization example
– Angular 8 upload file/image to Node.js Server example
Further Reading
Source Code
You can find the complete source code for this tutorial at Github.
Thanks!