Deploying Angular
Deploying Angular can be tricky for a lot of us. We; Frontend Developers kinda throw this shit over Backend Developers and we say, it’s not our shit 💩 and this leads us to not know the whole process and how does things work.
But, that’s entirely wrong, we should know the whole process, from the first scratch of our application, to going through the UX/UI design, to writing the CSS and styles, to handle APIs, till testing and finally going LIVE on production servers. 🚀
First things First
How can we deploy our Angular project?
In a previous post, We spoke about Angular Universal Vs. a normal Angular application.
To run a normal Angular application, we can just double click the index.html page generated after running `ng build` located in the dist folder
- Actually, we should run it using a server cause we may face some javascript errors not able to run js files, but yea,,, it’s as simple as hosting the index.html file
To run an Angular Universal App, we discussed that we have two folders generated:
- Browser
- Server
We will use the main.js file in the server directory to host our Browser folder, and we will run it like so:
- node dist/server/main.js
And it should open a port (say 4000) and navigating to localhost:4000 will show our App.
Ways to Host
Ok, so how can we host our App? we have a lot of ways to deploying Angular:
- Building a normal Angular app and use github pages for it, navigating to our index.html file
- Using firebase for deployment
- Using a private server to host our app with a web server like NGINX and LAMP
What will we be using?
We will go the hard way ðŸ¤ðŸ˜‚, We will use the NGINX one.
Why? cause it teaches us a lot of things along the way, we will speak about them in the coming posts, but we will go the fast way now.
Server
Ok, so how do we start?
We will start by creating our server, there’re a lot of server providers like:
We will be using DigitalOcean and you will get 200$, but any will work. You can use Linode as it has a 100$ gift as a start, Or, use DigitalOcean with this link: DigitalOcean
How do we do that?
We will start by creating our Droplet/Server in Digital Ocean.
Let’s make it like so:
- Germany
- Ubuntu
- Basic: Regular SSD
- 4$/Month
- Password –> And type in your root password
- And now, Click, Create Droplet !
Now, we will wait till this is done.
Once it’s done, click it, and you shall find the IP at the top of the droplet
The droplet is billed by time, so you won’t be charged the whole 4$ at once, but it will keep increasing from 0$ to 4$ during the month period.
SSH
Ok, now what?
We will need to SSH to our server/droplet to start using it.
Open a new terminal and ssh to your droplet using the IP in your droplet info and your password, like so:
$ ssh root@134.209.230.153
CONGRATULATIONS !! Your are IN your first server !, or not first IDK 😂😂😂
Ok, now what? we should Install some stuff:
Node
There’re a lot of way to install Node on Ubuntu, the easiest way is to use apt install
Follow this:
- $ sudo apt update
- $ sudo apt install nodejs
- It will ask for confirmation, type in yes or y
- Make sure it’s successful by typing
node -v
- Output: v18.7.0 (by the date of this article)
- $ sudo apt install npm
- Make sure it’s successful by typing npm -v
- Output: 8.18.0 (by the date of this article)
- Make sure it’s successful by typing npm -v
Ok, now we have Node and NPM installed.
Let’s create our Angular app, refer to Angular Universal Applications for the whole process of converting a normal Angular app to a Universal Angular app.
- mkdir /home/dev
- cd /home/dev
On your local machine/laptop/PC create your Angular Universal App, and move it to your Droplet/Server using SCP, or any other preferred method.
For the whole terminal process, check the below terminal output:
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
Install the latest PowerShell for new features and improvements! https://aka.ms/PSWindows
PS C:\Users\Joseph> cd .\Desktop\
PS C:\Users\Joseph\Desktop> ng new my-angular
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
CREATE my-angular/angular.json (2720 bytes)
CREATE my-angular/package.json (1041 bytes)
CREATE my-angular/README.md (1063 bytes)
CREATE my-angular/tsconfig.json (901 bytes)
CREATE my-angular/.editorconfig (274 bytes)
CREATE my-angular/.gitignore (548 bytes)
CREATE my-angular/tsconfig.app.json (263 bytes)
CREATE my-angular/tsconfig.spec.json (273 bytes)
CREATE my-angular/.vscode/extensions.json (130 bytes)
CREATE my-angular/.vscode/launch.json (474 bytes)
CREATE my-angular/.vscode/tasks.json (938 bytes)
CREATE my-angular/src/favicon.ico (948 bytes)
CREATE my-angular/src/index.html (295 bytes)
CREATE my-angular/src/main.ts (214 bytes)
CREATE my-angular/src/styles.css (80 bytes)
CREATE my-angular/src/assets/.gitkeep (0 bytes)
CREATE my-angular/src/app/app-routing.module.ts (245 bytes)
CREATE my-angular/src/app/app.module.ts (393 bytes)
CREATE my-angular/src/app/app.component.html (23115 bytes)
CREATE my-angular/src/app/app.component.spec.ts (1085 bytes)
CREATE my-angular/src/app/app.component.ts (214 bytes)
CREATE my-angular/src/app/app.component.css (0 bytes)
✔ Packages installed successfully.
warning: in the working copy of '.editorconfig', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.gitignore', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.vscode/extensions.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.vscode/launch.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of '.vscode/tasks.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'angular.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'package-lock.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'package.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app-routing.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.spec.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.component.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/app/app.module.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/index.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/main.ts', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'src/styles.css', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.app.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'tsconfig.spec.json', LF will be replaced by CRLF the next time Git touches it
Successfully initialized git.
PS C:\Users\Joseph\Desktop> cd .\my-angular\
PS C:\Users\Joseph\Desktop\my-angular> ng add @nguniversal/express-engine
ℹ Using package manager: npm
✔ Found compatible package version: @nguniversal/express-engine@15.2.1.
✔ Package information loaded.
The package @nguniversal/express-engine@15.2.1 will be installed and executed.
Would you like to proceed? Yes
✔ Packages successfully installed.
DeprecationWarning: 'createStringLiteral' has been deprecated since v4.0.0. Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead.
DeprecationWarning: 'createPropertyAssignment' has been deprecated since v4.0.0. Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead.
DeprecationWarning: 'createObjectLiteralExpression' has been deprecated since v4.0.0. Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead.
DeprecationWarning: 'createCallExpression' has been deprecated since v4.0.0. Use the appropriate method on 'ts.factory' or the 'factory' supplied by your transformation context instead.
CREATE src/main.server.ts (60 bytes)
CREATE src/app/app.server.module.ts (318 bytes)
CREATE tsconfig.server.json (272 bytes)
CREATE server.ts (2027 bytes)
UPDATE package.json (1466 bytes)
UPDATE angular.json (4473 bytes)
UPDATE src/app/app.module.ts (438 bytes)
UPDATE src/app/app-routing.module.ts (293 bytes)
✔ Packages installed successfully.
PS C:\Users\Joseph\Desktop\my-angular> npm run build:ssr
> my-angular@0.0.0 build:ssr
> ng build && ng run my-angular:server
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Raw Size | Estimated Transfer Size
main.bf1fcc11957ecb1e.js | main | 201.07 kB | 54.57 kB
polyfills.267f3febe9be7bef.js | polyfills | 33.09 kB | 10.68 kB
runtime.031a281078bcbe9e.js | runtime | 898 bytes | 517 bytes
styles.ef46db3751d8e999.css | styles | 0 bytes | -
| Initial Total | 235.04 kB | 65.76 kB
Build at: 2023-05-21T11:05:40.075Z - Hash: 648415e578c7a5ff - Time: 19298ms
✔ Server application bundle generation complete.
Initial Chunk Files | Names | Raw Size
main.js | main | 3.53 MB |
| Initial Total | 3.53 MB
Build at: 2023-05-21T11:06:03.267Z - Hash: f8eced095ba8a0b1 - Time: 20660ms
PS C:\Users\Joseph\Desktop\my-angular> scp -r .\dist\ root@134.209.230.153:/home/dev
root@134.209.230.153's password:
3rdpartylicenses.txt 100% 13KB 100.6KB/s 00:00
favicon.ico 100% 948 9.9KB/s 00:00
index.html 100% 545 4.9KB/s 00:00
main.bf1fcc11957ecb1e.js 100% 201KB 365.8KB/s 00:00
polyfills.267f3febe9be7bef.js 100% 33KB 209.7KB/s 00:00
runtime.031a281078bcbe9e.js 100% 898 9.3KB/s 00:00
styles.ef46db3751d8e999.css 100% 0 0.0KB/s 00:00
3rdpartylicenses.txt 100% 102KB 150.8KB/s 00:00
main.js 100% 3619KB 849.6KB/s 00:04
PS C:\Users\Joseph\Desktop\my-angular>
Now, we used SCP to copy our dist folder to our server, if you `cd /home/dev/` and use ‘ls’ you will find your files there.
Simple Deployment
If we use node on our main.js file now, we will be able to deploy our Angular app right away ! but that’s not what we want to use, we want to configure nginx to proxy to it.
But simple, just use `node /home/dev/dist/my-angular/server/main.js` and you will find this:
Node Express server listening on http://localhost:4000
Navigating to your http://<ip>:4000 will show it
NGINX
Now, we need to install NGINX
Like anything else, there’re a lot of way to install NGINX, but we will use apt as well
- sudo apt update
- sudo apt install nginx
Navigate to http://<ip> and you shall find the NGINX welcome landing page
If we go to /etc/nginx we will find two directories:
- sites-available
- sites-enabled
They are basically a mirror to each other, we will create a file for our angular app under sites-available and link it to sites-enabled
If you go to /etc/nginx/sites-available and /etc/nginx/sites-enabled, and you find a file called `default` copy it to somewhere safe and remove it from both directories
Deploying Angular
Now, create a file under /etc/nginx/sites-available, and call it my-angular.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
proxy_pass http://localhost:4000;
proxy_set_header Host $host;
}
}
Now, create a link for that file to the sites-enabled directory
$ sudo ln -s /etc/nginx/sites-available/my-angular.conf /etc/nginx/sites-enabled/
Now, we reload nginx
$ sudo systemctl reload nginx
If we navigate to http://<our-ip>
We will find that the landing page has changed and now it’s giving an error message saying that this site cannot be reached.
Why?
Because we stopped our node server earlier, how to resume it? just run node main.js again from under /home/dev, like so:
root@ubuntu-s-1vcpu-512mb-10gb-fra1-01:/home/dev# node dist/my-angular/server/main.js
Node Express server listening on http://localhost:4000
If we navigate to http://<our-ip> again, it shall work
Now, we are here … FINALLY !!
We will speak in detail about NGINX, Node servers, and firewalls in detail in the coming posts.
But for now, maybe that was beneficial I hope?
But, If not, here’s a potato acting as a server