Angular SSG (Static Site Generation) - The full guide from creation to deployment
Static site generation (SSG) with frontend frameworks like Next and Nuxt is all the rage lately so we Angular developers can't stay behind. It turns out, Angular supports SSG out of the box as it does with most things. No need for extra frameworks or libraries only Angular Universal and Angular Prerender. In this article, you will learn how to use Angular prerender for static site generation and how you can host it on Azure blob storage.
Angular SSG vs. SSR vs. SPA
Before we get into static site generation with Angular, let's first explain what static site generation (SSG) is, how it differs from server-side rendering or just rendering in the browser with a SPA and why you would want to use it.
Static site generation is when you render the website during the build process. The Angular compiler will build your website and pre-render the HTML pages during this process. The pre-rendered HTML pages including some JS and CSS files are your static website and can be hosted on something like Azure blob storage. Pre-rendering a static website only works for websites with static content; that is pages that are exactly the same for each person that loads and sees them.
With server-side rendering (SSR) a request for a page is made to a server (for example a nodeJS server) that will render the corresponding page and return it to the browser as an HTML page. A single-page application (SPA) will only ship JS code to the browser and the page will be rendered in the browser based on the JS code.
Okay, but why would I want to use a static website at all? First of all static websites have fast page loads and browsers can almost instantly show content to a user delivering a great user experience. In the case of the SPA, the JS code needs to be executed first and with SSR the server needs to respond and render the page.
With SSG because the pages are prerendered they are fully SEO-friendly and can be indexed by all crawlers, this will also be the case with SSR but a SPA can have some issues on the SEO front. Furthermore, you can host it cheaply (in some cases even free) and content can be cached using a CDN making for better availability and load times. For SSR you need to host a server and this can be expensive in comparison, especially for small websites.
Some good candidates for SSG are landing pages, informative websites, resume websites, and so on. A blog can be a good example as well, but SSG has a drawback for websites that frequently change. With static site generation, you need to do a new build or at least generate the changed page and upload them to your hosting. Also, each content change you make to an existing page requires a new build (or page generation) and an update of your hosting files. So think carefully about what type of website you're building and what suits your needs best. With Angular Universal, it's also fairly easy to mix and prerender some pages while server-side rendering others.
Building a static website with Angular
To build a static website with Angular you can use Angular Universal and the built-in pre-render engine for the static site generation. You can just take a new or existing Angular project and add Angular Universal with the following command:
This will add and change some files to enable server-side rendering and pre-rendering of your Angular application. You can still use and serve your application as a SPA with ng serve, with npm run dev:ssr you can run it server-side rendered (in develop mode), but we will be looking at pre-rendering your website.
After running the above-mentioned command some new scripts are added to your package.json:
We are interested in the "prerender script. This script will prerender your website. The angular compiler will try to find as many routes as it can, based on your routing modules. Because the compiler will try to find routes the building process takes a long time and even then it probably misses some pages, so we need to improve on this. We can help the Angular compiler a bit by giving it the files with the routes we want to prerender. To do this create a file in the root of your project (next to the package.json) named routes.txt. In this routes.txt file you can add all the routes you want to prerender like this:
Now you need to update the prerender script inside our package.json to:
ng run coding-blog:prerender --routes-file routes.txt
Now when you run the prerender script all pages you want will be prerendered and placed in the build output. When you run the script a dist folder is created and inside this dist folder you will find a server and browser folder:
The server folder is only needed when you are using SSR or a hybrid of SSR and SSG. In our case you are only interested in the browser folder inside your dist, this is your static website. Inside the browser folder, you will find a folder structure equal to the routes you generated and some additional JS, CSS, and HTML files in the root of the folder. Combined this is your static website including all the pages you prerendered.
Okay but now what?! Now you can start your static website using the following command:
npx serve ./dist/your-app-name/browser
This host your static website locally on your localhost. As a bonus, we will look into a way to deploy this to your Azure blob storage.
Hosting your static Angular app on Azure
In this example, you will be hosting your static website on Azure blob storage. This is a great and cheap way to host static websites and it allows for a front-door CDN, but we will not get into that in this example.
First login to your Azure portal and type blob in the search at the top of the page. This will show you some options to select from, you want to select the "Storage accounts" options:
Next, you want to create a new storage account. Click on "Create +", then select your Azure subscription, a resource group, and give your storage account a name. Click on review and then create to create your new storage account. After the storage account is created, you want to click on it and go to the option "static website" in the menu on the left. This will show a toggle to enable static website support, click on it and enter "index.html" under "index document name" and hit save.
After you click save you will see some URLs, with these URLs you can visit your static website in a moment. One more thing that happened is that Azure created a $web container for you under the "containers" menu of your storage account. On the left side of the menu, you will find a "containers" menu item. When you click on it you will see the $web container Azure created. This $web container is where we will host our static website.
If you click on the $web container you are able to upload the files from our static website manually. But we will be using VScode and the extension: Azure resources. First, install the extension in VScode and login to your Azure account. This will add an Azure icon on the left side of your code editor, if you click on the icon you will see a list of resources. Click on the storage accounts and you will see your storage account listed underneath it. Now right-click on the storage account and select: "Deploy to static website via Azure storage..".
Now select the browser folder from your dist and that's it, your static Angular website is hosted on Azure blob storage. A pop-up will be shown in VScode to browse your website after the files are uploaded, or you can just go to the URL found in your Azure portal.
Using Angular prerender to generate a static website is pretty easy to do. You just run a command to add Angular Universal and then it's just generating and hosting your static website. As with many things, Angular all functionally comes straight out of the box. Just make a good assessment if the benefits outweigh the extra work and build time for your case. Static websites can be a great option but it's not suited for every project.