Rob Meijeren
Apr 07 ● 7 min read
This is the story of how I failed to improve the dreaded Angular development performance by not waiting on a production build.
Two weeks ago I was working on getting the angular service worker set up so we could use it for offline use on one of our projects. The development environment felt very slow. I figured I would make it quicker by not waiting on a production build of Angular but using the serve build.
This is the story about how I failed to achieve that (not because of my skills by the way 😉)
Jan van den Berg had let me know service workers only function on ssl connections so I started there to get my ng serve command serve over https, eventually, I came across a stackoverflow ( surprise surprise ) post which showed me that angular provides you with a simple way to provide an ssl certificate and ssl key to the ng serve command. But then the next challenge came. How was I supposed to get a certificate and key that I could provide to ng serve which it would accept and not give those pesky unsafe website error screens.
I first thought of getting a “Let’s Encrypt” certificate and key since those are generally accepted and figured that would also work for this. However when I saw that Let’s Encrypt gave the following advice on localhost
I knew I would have to give the self-generation of a certificate another shot. I had tried this in the past but always ran into issues with either OpenSSL or some other weird thing that would prevent me from using a self-signed certificate. But since I had no other option here I went for it.
The downside of self self-signed certificates is that they aren’t trusted by browsers, otherwise anyone could make a certificate and it would lose its meaning. As I knew I could make the certificate valid for my machine only by importing it I figured why not go down this path. Although Let’s encrypt gives an example of how to generate it I had to go looking a bit further because for some reason (I can’t remember the exact error I got) the certificate created with that wasn’t valid for Angular to start the serve command.
Eventually, I came across a post which explained to me how I needed to create a CA first, then from that create a domain certificate.
The benefit of using a root certificate to create my domain certificates is (as is explained in the post) that I only would need to trust the CA certificate and any sub certificates created by it would automatically be valid for our browser. So I went on my merry way.
Eventually, I got the certificate generated and adjusted the ‘angular.json’ so it could find the certificate and key when I would run the ng serve –ssl command. I trusted the root certificate on my machine and booted up as I believed I had everything in place to run localhost over SSL.
It turned out that I made one mistake. In my effort to do this as few times as possible I set the domain certificate for localhost to a validity of 10 years.
As I went to my localhost I got an error saying the website wasn’t secure.
This had me puzzled for a while, I reran everything thinking I did something wrong in the generation of the certificates and used a wrong domain or something of that sort, but that gave the same error (again made the domain certificate with a validity of 10 years). I started looking in the developer tools as the lock icon said the certificate was valid but it still threw an error screen.
Using the developer tools I found my error on the security page:
After which I went digging to find what the maximum validity of a ssl certificate is these days. Turns out the answer is only 1 year. So after replacing the domain certificate with one that only lasts a year I got everything working and could serve localhost over SSL.
Hooray! you might think the service worker will run now and we can develop faster. Yeah, not so fast…
Angular wouldn’t be Angular if they didn’t do things just a little bit differently.
When I finally managed to get the SSL working I could see the service worker up and running but when I went offline, API calls that should be cached were not working (as in not giving back the cached api response). After a lot of searching in which I focused on the service worker, I thought something was wrong with the registration since it did work the same way as before. But, no. After eliminating everything I could and changing how the service worker registered I could not get it to work. Eventually, Arne de Bree gave me the answer as to why it wouldn’t work for Angular.
This was literally on the first pages in regards to the service worker, I felt pretty dumb that I managed to overlook this somehow.
Arne also pointed out that the localhost domain doesn’t actually need SSL to use a service worker (which is also why the http-server call works.
Eventually, the time spent on this was not wasted, I learned a lot about self-signed SSL certificates, certificate validity, service workers, and that Angular sometimes just sucks 😉.
I kept thinking why ng serve wouldn’t work nicely with the service worker. The answer I came up with is that ng serve won’t generate hashes and append them to the file names of e.g. vendor.js, therefore it couldn’t determine if a new version is deployed and because of that the Angular team just went like screw it! it won’t work with ng serve.
I can sympathize with that solution.. but there are other ways to determine if there was an update e.g. the creation date of the file loaded. Also, even if you couldn’t detect if a new version of the application was deployed it should still have been possible to write and read the cache of the service worker, thus not having everything fail miserably.
As for the exact reason? I don’t think I’ll find out anytime soon, but, until they make it work I’ll just have to go the slow route and wait on my production builds of Angular and boot that up with http-server.
Are you interested in learning more about SpringTree? click here.
Sources: