Angular Server Side Rendering with Lambda@Edge and CloudFront
One of my goals when working on FaxDroid was to ensure the best possible user experience. An important factor in user experience is the time it takes to load web pages. There are various studies around page speed and how it effects visitors (https://web.dev/why-spe-matters).
In order to increase the speed of page loads I took advantage of several different tools:
Background
Speed Metrics
One of the main metrics used in evaluating page speed is First Contentful Paint (FCP). This indicates the time it takes for the first piece of content to render on the users browser. This metric is important because if the FCP takes too long, users will tend to leave the website (and hence will result in loss of conversions). A fast FCP will provide some visuals for users to be engaged with while the rest of the page loads.
Another really important metrics is Largest Contentful Paint (LCP). This indicates the time it takes for the largest piece of content to load. Users have a higher wait tolerance for LCP compared with FCP, however there is still a limit to the amount of time users will wait. If your website is too slow users will still bounce.
Angular SSR
Angular SSR allows a NodeJS server to return a simple version of the webpage (without the HTML and CSS). This allows a simple version of the webpage to render for the user while the actual Angular application is downloading and loading behind the scenes. This version of the page does does not function and is non interactable. Without SSR the entire Angular application will need to load before anything becomes visible to the user. This is time consuming for two reasons:
- The bundle size for the full Angular application is normally much larger than the SSR version
- On slower devices the actual load time of the application is considerable (even after the JS bundle is downloaded)
Lambda@Edge
For Angular SSR to work a NodeJS server is required. Lambda@Edge allows the Angular SSR to be rendered at edge locations closest to the user, keeping the latency for the initial render low.
CloudFront
CloudFront is the CDN provided by AWS. CloudFront has a global distribution of edge servers (https://aws.amazon.com/cloudfront/features/) which can be used for providing static content (or dynamic content using Lambda@Edge). This helps provide content from locations closest to consumers and hence reducing latency (https://www.cloudping.co/grid). With CloudFront static resources (the Angular bundles, images, …) can be loaded from caches closest to the user, greatly reducing the speed for loading the full page.
Solution
The solution I used for optimizing page load times can be seen in the figure below. The domain FaxDroid.com resolves to a CloudFront distribution. Anytime a request is made for FaxDroid the DNS resolves to the closest edge location for CloudFront. If the content is found in the CloudFront cache it is returned, if not Lambda@Edge is used to decide how to handle the request.
There are three different types of requests that reach the CloudFront server. In the sections below I’ve explained each
Page Load Request
When users enter FaxDroid’s URL in their browser an HTTP GET request is sent to CloudFront. These requests are never cached and CloudFront redirects all such request to the Lambda@Edge. Lambda@Edge performs server side rendering and provides the initial render of the page:
Static Resource Request
Once the initial render of the page is downloaded, the request for static resources will begin. Unlike page loads, static resources are cached. Static resources could be one of the following things:
- Static files such as images, icons, thumbnails
- Static files that are generated per deployments such as the js resource bundles
Both resources have a caching policy enabled. This greatly speeds up the site load as users will receive content required to load the full page from an edge CloudFront server closest to them.
API Requests
Once the webpage is loaded and the angular app loads, it will start to make REST calls to the server. CloudFront never caches API requests. These requests are routed to the FaxDroid server located in us-east-2. Even though the actual FaxDroid server is not globally distributed, there is still a benefit of routing the traffic through CloudFront. By leveraging CloudFront traffic passes through AWS’s backbone infrastructure reducing the latency of API requests.
Description
Leveraging Angular Server Side Rendering using Lambda@Edge and CloudFront to reduce page load latency.
Skills:
- Angular IO
- Angular SSR
- Lambda@Edge
- CloudFront