Server side Rendering with Angular 4, Express, and NGINX proxy cache
Homepage demo/site: jamilslist.com
It’s taken me a lot of time to piece my way through everything, but I would like to share what I’ve learned about server side rending with Angular 2 and Express and how I ultimately reduced my page load time from 6 - 8 seconds on average, to averaging about 2.5 seconds. My webpage webpagetest.org score was an “F” for TTFB at around 3 seconds to start. Now I’m up to a "B" and TTFB is down to around 40 ms now.
When I first started my Netflix movie site I wrote it all in plain old PHP, HTML, jQuery, CSS. I threw together a quick design and it worked, and performed, great. I remember being excited about finally getting it off the ground and showing it to a friend at work who promptly told me, “That’s cool, It’d be perfect for Angular 2!”
I didn’t have much experience with Angular 2 but I had tried Angular 1 a little bit in the past and always found Javascript frameworks interesting. So a month later I gave it a shot.
I won’t lie... Angular 2 was, and is, hard for me to understand. As a self taught developer I always have found my greatest skill to be my persistence in learning as opposed to any natural talent of understanding. This stuff is HARD for me, but I always seem to find the solutions to every answer (after spending half my life on Stack Overflow).
So fast forward a month later and I was up and running with a brand new Angular 2 site and a sleek new design. Everything was great, but I forgot one HUGE thing. Client side rendering is the death of SEO. I knew my next step had to be server side rendering and I didn’t know where to start.
So I just hand rolled my own Express server from scratch and called it a day. Yeeeeaaa right. Absolutely ALL credit goes to this guy at coursetro.com. In fact, I can’t explain all the details of this post, because quite frankly, I don’t understand them all. But from this post I pieced the server together and was up and running with rendering on the server in one day!
So things were great, I had my app up, running on the server, and google could crawl everything.
But one thing I noticed was that my app was really slow. I was happy enough that I had figured out how to render everything on the server for awhile, but the slow speed really started to get to me.
Every once in awhile I’d get loading times of under 6 seconds, but more likely it was 7 - 8 on average. I figured that server rendering just caused a really slow initial boot up time and there was nothing I could do.
Well I lasted about one day before I decided that this just wouldn’t do. I had to speed up my site for my users.
NGINX Proxy Cache
I spent around a day searching for options like optimizing my express server setup (as if I understood how to do that) or cacheing images and css but 10 hours later I still wasn’t any closer.
Suddenly, it hit me. My setup is using an NGINX proxy to the Express server running my app. If I can do a proxy cache, I should be good to go.
Below is the code I implemented.
# Outside of the server block
proxy_cache_path /path/to/your/nginx/cache levels=1:2 keys_zone=my_zone:10m inactive=60m;
proxy_cache_key "$scheme$request_method$host$request_uri";
location / {
proxy_cache my_zone;
add_header X-Proxy-Cache $upstream_cache_status;
add_header Cache-Control public;
proxy_cache_key $host$uri$is_args$args;
proxy_cache_valid 200 1d;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy truehttp;
proxy_pass http://localhost:YourPORT;
proxy_redirect off;
}
First I created the NGINX cache directory with “mkdir -p /path/whereveryouwantit/“
Then I added the code above to my NGINX config for my site. You can see I set the cash to 200 expiring in 1 day.
Right now I’m averaging just under 3 seconds of load time.
So I know this isn't all that technical, and I'm sure there's a ton of people that have figured this out already, but for the people like me that find this stuff pretty challenging, I hope this helps you get your Angular 2 site up to speed with server side rendering and NGINX cacheing.
My next step is going to be to implement lazy loading and I’m hoping to break under 2 seconds. Wish me luck!