Angular Universal is now called Angular SSR, and it is built into the framework. The year is 2024. Two things are changing: serverless, and CSR (Client Side Rendering). Sure, there are many valid use cases for both. However, in order to have good SEO, speed, and security, you need Server Side Rendering. In order to get rid of cold starts and location loading delays, you need Edge Computing. This is over simplification, but you get the point.
Angular needs to be at least on par with ALL other mainstream SSR frameworks and offer these things in deployment, easily. These other frameworks include SvelteKit, NextJS, Remix, Nuxt, Qwik (City), and Solid Start. The Signals addition is wonderful, but we need better deployment, or nothing else matters.
Google Edge
Google has an Edge Network, but they push serverless functions like Cloud Run, which is also what version 2 of Firebase Cloud Functions use. Firebase Functions need a Version 3, which is built on the Edge. However, first Firebase, specifically firebase-admin would need to work on the edge. Google, who makes Angular, might then be able to compete better for deployment options. Cold Starts are terrible and should die IMHO, unless you have have specific use cases for them.
1. Firebase Deployment (serverless)
So, let's start with the Google way, which you would think would be seamless. Don't get me wrong, it has come a LONG way. You used to have to bundle things up manually like in Fireship Angular 12 Course. You could do Cloud Run or Functions, but it was a pain. Now things are automatic. Here is the thing, they have been automatic since Angular 14-ish.
You can use firebase init hosting
or ng deploy
and follow the options, but you can't use both. It is odd to me that they don't work seamlessly together, as they do the same thing. You must have a Firebase project, and turn on the Blaze plan to use hosting.
Note 1
Thank you for trying our early preview of Angular support on Firebase Hosting.
During the preview, support is best-effort and breaking changes can be expected. Proceed with caution.
Why is this still in "early preview." I have been using this for at least 3 versions of Angular. Were the other versions early early alpha preview?
Note 2
Apparently you need to ignore the index.html
file when deploying if you have dynamic content. Maybe someone in the comments can tell me why this is default.
firebase.json
{
"hosting": {
"source": ".",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**",
"index.html"
],
"frameworksBackend": {
"region": "us-central1"
}
}
}
You also have to change pre-rendering to false
in angular.json
under projects.architect.options.prerender
. We have dynamic content for this app.
Note 3
And it seems to deploy on first try, but then I got a loop error. Turns out after posting a bug, and getting sent to GitHub, this is a known issue when deploying to Cloud Functions. The fix is to edit your server.ts
file, and don't use the process.env['PORT']
variable, as it apparently is already in use.
// const port = process.env['PORT'] || 4000;
const port = 4000;
Note 4
Every time I deployed, I got this error:
functions: Unhandled error cleaning up build images. This could result in a small monthly bill if not corrected. You can attempt to delete these images by redeploying or you can delete them manually at https://console.cloud.google.com/gcr/images/YOUR-PROJECT-ID/us/gcf
So, if you get this, click the link and delete the gcr image. I don't understand why there is an artifact, or one every time, but I don't want to waste space I could pay for.
All in all, deploying to Cloud Functions Gen 2 was a pain, and all that for serverless...
2. Netlify (Edge)
Netlify was remarkably easy to deploy and use. Set prerender: false
in angular.json
to make sure it uses the functions.
Create your Angular app, commit it to GitHub, and simply connect your app on Netlify. Done! Edge Deployment!
I suspect this process is entirely possible and easy due to Netlify using Deno. While Deno is terrible, it is also powerful. When you don't have to fool with configuring it, it can be nice!
3. Vercel (serverless)
I wrote a whole article just on deploying Angular Universal to Vercel. I updated it before I wrote this article to make sure it is working with Angular 17.2.
I have not seen a working Vercel Edge deployment, but considering Vercel uses Cloudflare under the hood, I imagine you could modify the Cloudflare code to get it working. However, Cloudflare has its own problems.
4. Cloudflare (Edge)
Cloudflare only offers Edge deployment, and is the backbone of all the great sites. There is a Cloudflare Angular Guide with bad information. Unfortunately, there is not a simple add package like these:
Amazon S3: ng add @jefiozie/ngx-aws-deploy
Firebase: ng add @angular/fire
Netlify: ng add @netlify-builder/deploy
GitHub Pages: ng add angular-cli-ghpages
There needs to be. We need ng add @cloudflare/angular
or something similar.
In any case, you have to create a new repository:
npm create cloudflare@latest my-angular-app -- --framework=angular
Then you connect your GitHub account in Cloudflare. However, the settings on the Guide are wrong. You need to use these:
Configuration Option | Value |
---|---|
Production branch | main |
Build command * | npm run pages:build |
Build directory | dist/cloudflare |
I also had to set prerender to false in angular.json
under projects.architect.options.prerender
. Otherwise my index page would get prerendered. Again, not sure why this is default.
Adding it to your repository
If you have an existing project, you should be able to add the tools
folder as well as updating your server.ts
file. Just create a new cloudflare angular project and copy them over. Check your package.json
in case there are required dependencies. I have not tested this, but no reason it shouldn't work.
Problem - Critical CSS Inlining
One of the issues with the Cloudflare deployment, as it works, but only without critical css inlining. I believe Vite supports this, and Angular SSR is able to do this on Node servers (and apparently Deno on Netlify, probably with npm imports). Notice in the Cloudflare repo there is a jump where the CSS loads later from the stylesheet. I am frankly ignorant on the subject, but you can blatantly see a CSS loading difference.
5. Analog
Analog allows you to deploy anywhere, literally. It uses Nitro toolkit which has options for anything while working with Vite.
There is a small learning curve, but I got deployment working immediately.
What now?
Well, scream though I have, the Angular team desperately needs to Remove NodeJS Dependencies, as it has already fallen behind from all frameworks concerning deployment. I'm still waiting for the response on this... 🦗 🦗 🦗 🦗
Does Vercel Hate Angular?
I thought about writing a whole article on this, but I figured I would sum it up here. When I first wrote my Vercel Deployment article in 2021, which BTW the original vercel.json
took weeks to figure out without any clear direction, I emailed Vercel:
12/28/21
Unfortunately, there are no plans to add this since this is using a Serverless Function to start your server on Vercel, instead of a Node.js server, making this not ideal.
I then received a email explaining why Nuxt and SvelteKit could work fine, but not Angular. Their reasonings had a incredible misunderstanding of how Angular works. Angular is just JavaScript, just like every other Framework. So, I made it work using their own vercel.json
file and some small tweaks. I then asked them to add it to the Framework Presets. Here was my response:
These adapters, for example, were built by the community:
https://github.com/sveltejs/kit/tree/master/packages/adapter-vercel
https://github.com/nuxt/vercel-builder
If somebody builds a working one for Angular Universal, we will gladly add it to our Framework Presets → https://vercel.com/docs/concepts/deployments/build-step#framework-preset.
It had taken weeks without direction to figure out a simple vercel.json
file, so building a preset was out of my wheelhouse.
Since the Angular Team has stepped up their game in the last 2 years, I saw this post by Alan Agius from Angular Team (who gave me the crickets, but also who is a huge reason Angular is doing great now!):
We actually did reach out to Vercel, to work with them to support SSR. Unfortunately in the near term they do not have a priority to add support for Angular SSR/SSG.
Netlify and Cloudflare worked with Vercel to get the Angular adapters working, but Vercel doesn't seem to want to help Google!? Wow. The answer is for someone to take my code (modified now thanks to several contributors) and create a Framework Preset. Of course, I suspect, if the Node Dependencies go away, it will be extremely easy to get it to work on Vercel Edge (once they figure out the css issues).
In 2025
I will write a new article in 2025. Hopefully these problems will be solved:
- Critical CSS Inlining will work on Cloudflare
- Vercel Framework Preset will exist (with Edge option)
- Angular SSR will have .env variables built in
- Angular SSR will simplify preloading data
- Angular SSR will simplify rest endpoints
- ZoneJS will be fully optional (important for faster deployments)
Summary
Use Netlify if you want Edge deployment, otherwise AnalogJS is freaking amazing and solves all the problems above. Sponsor AnalogJS the project if you can give a few bucks!
Demos
Repos
Angular with Firebase Deployment
For a modern Angular App with Firebase, see my latest post:
https://code.build/p/angular-todo-app-with-firebase-fmLJ37
Currently Building a Free Firebase Course on Code.Build.
J
Top comments (5)
Thank you for sharing!
But how about Azure Static Web Apps?
I set prerender as false, but it is not possible to see anything from HTML in the source of the site, and when I refresh it displays an error 404. Same with any other of the pages.
Could you please explain how to fix this?
I'm not familiar with Azure, so I'm not sure. I would say go with AnalogJS in most cases.
Yesterday I hosted my Angular app on vercel, just as nextjs on vercel. And it worked just fine, I didn't need to do anything, it just worked out of the box. And I was using SSR
It is probably prerendered which is not the same thing. Make sure
projects.build.options.prerender
is set tofalse
. Otherwise, check out my post for that. dev.to/jdgamble555/how-to-deploy-a...Thanks for sharing! I ended up using the new Firebase App Hosting. Netlify deployment would fail with a weird error every time that I tried :/