SEO (search engine optimization), ahh, that nightmare for every company, especially if your website is built using Angular. When you initially see your shiny new Angular-based website, everything looks great! It is fast, responsive, and everything loads in the blink of an eye, but… Then excited to run some benchmarks, you see the pagespeed report, and – here comes the moment of disappointment – everything is in the red.
This is a very common scenario for companies that have decided to use a SPA (Single Page Application) architecture for their websites, whereby most HTML and content are loaded from the server but rendered on the client in the browser. Search engines can't see or crawl it. But it's not the end of the world, nor was the use of a SPA architecture wrong or necessarily bad. It's a great architecture with some significant advantages, but unfortunately, SEO isn't one of them.
Thankfully Angular now has a solution for this and it's called Angular Universal -- a technology that renders Angular applications on the server; also known as Server-Side Rendering (SSR). Suffice it to say that SEO (generally) doesn't work well with data rendered only by the client and can be much more effectively optimized if the content is rendered by the server. So why not do both?
There are three primary ways that web pages/content can are rendered:
Client-Side Rendering (CSR):
This is the standard way how Angular works. Scripts & data are downloaded from the server, and after that, the page(s) (e.g., Html) is rendered in the browser on-the-fly. Since only data is retrieved, the screens and browser updates are very fast and smooth, offering a very nice user experience.
Server-Side Rendering (SSR):
With this approach, things are a little bit different. The page request is sent to the server, which then loads all data and initially renders the HTML content that is returned to the browser. Within the browser scripts, the HTML and further CSS/Scripts are then loaded to correctly display the page to the user. Generally, this process then repeats for each unique URL that may be opened in the browser or consumed by a search engine.
Historically this is how websites were rendered. But even with modern CSR applications, we can take advantage of this to augment the normal rendering and help close the gap in functionality for SEO.
Static Site Generation (SSG):
Also known as pre-rendering websites. This is the approach where dynamic page content is processed at build time, generating static HTML which is served from the server to the browser. But at this point, all content is static – unless it is rebuilt (which is usually a time-consuming process). So naturally, the SEO of static content can usually be optimized to be as good as it gets.
SEO issues with Client-Side Rendering
One of the key factors for a good SEO score is a good pagespeed score on slow(er) mobile devices. The problem with SPA's is that the first load of the application scripts takes some time to load, and then only after that can the content be rendered. Generally, during this initial loading time, the page is blank, or occasionally you may see some form of wait-animation denoting that things are loading. It's not uncommon for his initial loading process to take several seconds on a slow device, and it can result in a high user bounce rate.
The problem with Search Engines is that, while some may attempt to load and execute the application scripts to get the rendered content, there are varying levels of success at doing so. It's very common for the content that is indexed not to be what was expected because it's not able to render in the same way that a user would experience in a browser.
Another issue CSR has is often with social networks. Most sites use Open Graph meta tags (in the form of <meta property=" og:"/>) that are used to enhance the experience on some social networks. These tags are in the <head> of the website, and the values are populated during the rendering of the page. Therefore, the Open Graph meta tags need to be available and correctly populated when consumed by the social network link (meaning it needs to be rendered by the server).
Server-Side Rendering and SEO
SSR is not a magic wand, but it will solve many SEO issues. In case it's not explicitly clear yet, with SSR, the HTML is easily accessible by web crawlers because the full HTML is created on the server. So all search engines can consume exactly the content that you intend by rendering from the server.
With this in mind, the approach of using SSR in combination with Client-Side rendering can provide great SEO. In addition, there are other advantages that can be gained, such as improved Page load times (when implemented to do so), preloading of images or other resources, etc. All of which can lead to lower user bounce rates.
Downsides of SSR along with CSR
Even with CSR, the implementation of SSR can increase the server response times as traffic increases; since the server is a limited resource and will now be rendering content on initial page loads.
From a user's perspective, the result is that each initial page load is rendered twice: first by the server, and secondly on the client, after the scripts are loaded. This can cause page flickering, which can be visibly distracting to the user.
From an infrastructure perspective, the systems are now doing a lot more work than they would be if only performing as an API for the SPA application using CSR.
But the biggest impact is usually from a developer's standpoint. Implementing SSR within your application requires additional time to make your codebase SSR ready/capable. This is especially impactful if there are a lot of dependencies on browser features, like using the window object, local storage, session storage, etc. Functionality not available on the server must then be accounted for when rendering server-side.
Closing the feature gap between CSR and SSR
A common strategy to close the feature gap between client-side and server-side is for the front-end team to implement another layer in the application using mock-browser or domino for server-side DOM abstraction. Here is an example:
Then by using Angular's PLATFORM_ID token, we easily detect whether the code is running server-side or client-side, and execute accordingly:
Let's look at some actual performance scores…
SPA App using CSR only:
SPA App using both CSR & SSR:
Here we can see the pagespeed score improvement on mobile devices from 30 to 52. The First Contentful Paint metric is drastically improved. This is because on that first response from the server there is already full HTML necessary for the browser to render the page. And other performance metrics are similarly improved.
An important metric to notice is the Largest Contentful Paint (LCP), this measures how long it takes for largest content to be shown on screen. Ideally it should be below 2.5 seconds. Other important metrics are First Input Delay (FID) and Cumulative Layout Shift (CLS). Additional information about these metrics can be found on https://web.dev/vitals/.
In summary, Server-Side Rendering along with Angular (CSR) is not a perfect solution but as we saw it will improve SEO scores and it will give more stability in terms of web vitals to your application.
On our journey to improve SEO this is a great first step. But it doesn't necessarily end here, and in our next blog we will cover some other strategies that focus on truly maximizing SEO.