digitalspeed logo

How to Host a Server Side Rendered (SSR) Angular Application on AWS Lightsail

Angular SSR hosting on Lightsail

In this tutorial, we will explore how you can implement server-side rendering (SSR) with Angular Universal and host your application on AWS. I will not go into much detail in this post rather I will outline the general process you can use and link relevant docs that contain the details of that specific process.

I will not link the GitHub repo for my project because it is a private repo. I simply wanted to share my experience, the architecture I followed and alternative architecture you can as well try. One reason why I am sharing this is because I noticed that most posts and docs about his process were outdated, so I had lots of learning and research to do. I will show only a few pictures.

The architecture of the solution I used, our main interest here is the Lightsail server

Prerequisite

This tutorial assumes you have developed an Angular single-page application (SPA) for which you want to implement SSR. If you don’t already have an Angular application, refer to Angular Tour of Heroes to first build your application or you can use any simple Angular application.

Short intro and distinction of SSR and CSR

Angular applications can be rendered in two primary ways: Server-Side Rendering (SSR) and Client-Side Rendering (CSR).

SSR: With Angular SSR, the server pre-renders the application and sends the fully rendered HTML to the client. This approach significantly improves the initial load time and is beneficial for SEO as search engines can easily index the content. SSR is ideal for applications where performance and SEO are critical, such as e-commerce sites and blogs.

CSR: Angular CSR, on the other hand, renders the application directly in the browser using JavaScript. While this allows for dynamic content updates and a more interactive user experience, it can lead to slower initial load times and less effective SEO compared to SSR. CSR is suitable for applications that rely heavily on user interactions and where SEO is not a primary concern.

Server Side Rendering will render your application in advance and generate static structural pages that get bootstrapped on the client. There are a number of reasons for implementing server-side rendering for your Angular application.

  1. Search Engine Optimization (SEO)
  2. Improved performance on low-powered devices and low internet connectivity
  3. Quicker initial loading of the first application page
  4. Implementing Google AdSense

Implementing Angular SSR

The previous version of Angular requires you to install Angular SSR as Angular Universal through this command

ng add @nguniversal/express-engine

But more recent version V17 of Angular, you use

npm install @angular/ssr

You will notice that the following files were created

  1. src/main.server.ts: exports the AppServerModule, which is the entry point for the Angular Universal application.
  2. src/app/app.server.module.ts: wraps the Angular application along with the ServerModule into a single AppServerModule, which is the entry point for the Angular Universal application.
  3. src/tsconfig.server.json: this file tells the Angular compiler where to find the AppServerModule entry point.
  4. webpack.server.config.js: this specifies the server-side webpack configuration for bundling the Express server (server.ts and import files) into JavaScript code. This is used in conjunction with the updates to package.json to include the “compile: server” script.
  5. server.ts: this is the Express server. It is called ngExpressEngine, which is a wrapper around renderModuleFactory. This is the core functionality that makes Angular Universal work, as it takes the index.html file and generates static HTML pages based on the Angular routes specified for the application.

The following files will also have been modified.

  1. package.json: updated to include new dependencies and new scripts such as the “compile: server” script already mentioned, and the scripts for building and running the Angular Universal application, “build:ssr” and “server:ssr”.
  2. angular.json: the build output path is updated from dist/{application_name} to dist/browser and a new architect script is added for “server”.
  3. src/main.ts: updated so that the browser version of the application won’t start bootstrapping until the server-side rendered pages have been loaded.
  4. src/app/app.module.ts: update to replace BrowserModule with the method BrowserModule.withServerTransition({ appId: ‘serverApp’ }), which tells the browser version of the application that the server version will transition to the client version.

Build your SSR

Run the following command to build and serve your file

npm run build:ssr
npm run serve:ssr

You most definitely have errors when you run the commands above because some of the JS code/functions you used are not suitable for the server side only for the client side.

Remove or modify codes of the form

setInterval(do-smth(), 15000)
window.scrollTo({ top: 0, behavior: 'smooth' });

Generally, avoid any function call that uses resources only available to the client without testing first if it is being run on a client or server. More like this

if (type of window !== "undefined") {
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

The server-side rendered application will then be running on http://localhost:4000. This is the default port that the Angular SSR application will run, however, it can be changed by updating the PORT const value in server.ts.

You will notice that your webpage loads faster now and inspecting the page from the dev tool you will notice that it is mainly HTML that corresponds to the content of your application, instead of script tags which will execute JavaScript in the browser.

You can locate the build of your Angular SSR file in the dist folder of the main entry of your application folder. Your SSR build is in the server rather than the browser which will contain your application script file.

On your server folder, you should see server.mjs which if run (node ./path/server.mjs) would start your SSR application and serve on the specified port which was what you did when you ran npm server:ssr previously.

There are lots of ways you can deploy your angular application on AWS. You can deploy on any of the compute options on AWS EC2, Lambda, ECS, LightSail, ElasticBeanStalk, App Runner, etc.

Another option to host your SSR web application on AWS is to use NestJS and deploy on Amplify, as Amplify hosting does support SSR currently. Check out this link for more details  https://docs.aws.amazon.com/amplify/latest/userguide/server-side-rendering-amplify.html

We will use LightSail because it offers a tailored Node.js environment, is cost-effective, and includes a 3-month free tier for new users.

If you want to try out using Lambda for this process then check out this post https://medium.com/swlh/serverless-angular-universal-with-aws-lambda-99162975eed0

Deploy your SSR Application to LightSail

Create a LightSail instance on AWS, ensure you select NodeJS as the instance environment, and access your LightSail server securely using the SSH instance keypair you created.

Install Nginx and Git on your LightSail server

Clone your application to your LightSail server using the GitHub URL, be intentional about the folder you clone it to.

Assess the folder of your server.mjs script, and start your node application remotely using the command node server.mjs

Locate your server running on port 4000 which was the port we set for your application to run on, http://Server-IP-Address:4000

You should see your website running but on HTTP protocol because you’re yet to set up TLS encryption so your server can run HTTPS. This is where the Nginx server comes in, Nginx server will also be used as a reverse proxy to direct requests coming in from port 80 to port 4000 so you won’t have to append 4000 on your server IP again.

Optimizing your SSR Application

So you should install Nginx on your server if it’s not already installed. Configure to redirect the traffic from port 80 to 4000.

Configure HTTPS on your LightSail server using this AWS doc on configuring HTTPS Nginx Lightsail Server

It will require you to set an SSL certificate from Let’s Encrypt and to have a domain name so ensure have those set up.

Configure Nginx on your server to redirect traffic from HTTP to HTTPS, and to redirect traffic from port 80 to port 4000 which is where your application is currently running.

You should now be able to access your application through HTTPS and the default HTTP port of port 80 rather than port 4000.

If you configured a domain name for your website, you should now be able to set up your website on Google Search Console. Prior to using SSR, Google Search wouldn’t be able to access your website because it requires JavaScript to load which Google Search bot does not run.

The website is now accessible to Google

Now you should create a CICD pipeline to enable continuous integration and continuous deployment of your application through GitHub Actions or any other CICD pipeline you are familiar with.

Set up GitHub actions on your GitHub repo, and create your main.yml file where you will test your application before deploying it to your LightSail server.

To do this, you will add your LightSail server keypair file and server IP to your GitHub secrets which will grant GitHub access to deploy your application to your LightSail server in the path you specify in your action main.yml file.

Test your CICD pipeline by pushing changes to your application to GitHub and confirming the changes are automatically deployed to your LightSail server.

Ensure smart troubleshooting and debugging if you encounter errors, in my case, the common errors are ensuring proper naming of the secrets and variables in GitHub actions. Check properly as this step is quite error-prone.

Conclusion

I have shown you the work through to implement the Angular SSR solution on AWS although I did not include specific codes or detailed steps to carry out the processes, the blog posts I recommend would be very useful and also you can get specific steps from ChatGPT. Now you know what is possible because I have done this before.

Please share this article at the top of the page under the share this button. Thanks

Recent Post

Send Us A Message

Related Post

Join our newsletter to stay updated

digitalspeed-logo

At DIGITALSPEED, you can get updates, reviews and learn about new digital tools and features on existing tools. check us on social media.

Get In Touch

Lagos, Nigeria

DIGITALSPEED © All Rights Reserved.

2024

Scroll to Top

Seach for Articles