Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
A couple months ago, I was traveling outside of the U.S. and wanted to show a friend a link on my personal (static) site. I tried navigating to my website, but it took much longer than I anticipated. Thereâs absolutely nothing dynamic about itâââit has animations and some responsive design, but the content always stays the same. In Italy, at 8mb/s, it was a different picture entirely. I was pretty appalled at the results, ~6s to DOMContentLoaded, and 8.2s for a full page load. There were 50 requests for a static site, with 2.9mb of total data transferred. I was accustomed to my 1Gb/s, low latency internet in Los Angeles connecting to my server in San Francisco.
This was my first foray into optimizations. Up to this point, any time I wanted to add a library or resource, I would just throw it in and point to it with src=ââŠâ. I had paid zero attention to any form of performance, from caching to inlining to lazy loading.
I started looking around for people with similar experiences. Unfortunately, a lot of the literature on static optimizations gets dated fairly quicklyââârecommendations from 2010 or 2011 discussed libraries or made assumptions that simply werenât true anymore, or just repeated the same maxims over and over.
However, I did find two great sources of informationâââHigh Performance Browser Networking and Dan Luuâs similar experience with optimizing static sites. While I didnât go as far as Dan in stripping formatting and content, I did manage to get my page load to be roughly 10x faster, to about a fifth of a second for DOMContentLoaded and only 355ms for full page load.
The Process
The first step of the process was to profile the site. I wanted to figure out what was taking the longest, and how to best parallelize everything. I ran various tools to profile my site and test it from various locations around the world, including:
- https://tools.pingdom.com/
- www.webpagetest.org/
- https://tools.keycdn.com/speed
- https://developers.google.com/web/tools/lighthouse/
- https://developers.google.com/speed/pagespeed/insights/
- https://webspeedtest.cloudinary.com/
Some of these offered suggestions on improvements, but thereâs only so much you can do when your static site has 50 requests for everything from a spacer gif left as a remnant from the 90s to assets that arenât used (I was loading 6 fonts and only using 1)
Timeline for my siteâââI tested this on the Web Archive as I didnât screenshot the original one, but it looks similar enough to what I saw a few months ago.
I wanted to improve everything that I had control overâââfrom the contents and speed of the javascript to the actual web server (Nginx) and DNS settings.
Optimizations
Minify and Coalesce Resources
The first I noticed was that I was making a dozen requests each for CSS and JS (without any form of HTTP keepalive), and to various sites, some of which were https. This added multiple round trips to various CDNs or servers, and some JS files were requesting others, which caused the blocking cascade seen above.
I used webpack to coalesce all my resources into a single js file. Any time I make a change to my content, it automatically minifies and turns all my dependencies into a single file.
I played around with different optionsâââcurrently, this single bundle.js file is in the <head> of my site, and is blocking. Itâs final size is 829kb, and that includes every single non-image asset (fonts, css, all libraries and dependencies, and js). The vast majority of this is are the font-awesome fonts, which make up 724 of the 829kb.
I went through the font awesome fonts and css and stripped all but the three icons I was usingâââfa-github, fa-envelope, and fa-code. I used a service called fontello to only pull the icons I needed. New size? 94kb.
The way the site is currently built, it wonât look correct if we only have stylesheets, so I accepted the blocking nature of a single bundle.js. Load times are ~118ms, which is more than an order of magnitude better than above.
This also had a few added benefitsâââI was no longer pointing to 3rd party resources or CDNs, so the user would not need to 1) perform a DNS query to that resource, 2) Perform the https handshake, and 3) actually wait for the full download from that resource.
While CDNs and distributed caching might make sense for large scale, distributed sites, it does not make sense for my small static site. The additional hundred milliseconds or so are a worthwhile tradeoff.
Compress Resources
I was loading an 8mb sized headshot and then displaying it at 10% width/height. This wasnât just a lack of optimizationâââthis was almost negligent usage of users bandwidth.
I compressed all my images using https://webspeedtest.cloudinary.com/âââit also suggested I switch to webp, but I wanted to remain as compatible with as many browsers as possible, so I stuck to jpg.
Improve Web ServerâââHTTP2, TLS, and More
The first thing I did was transition to httpsâââwhen I started, I was running Nginx bare on port 80, just serving files from /var/www/html
I started by setting up https and redirecting all http requests to https. I got my TLS certificate from Letâs Encrypt (an absolutely amazing organization that just started signing wildcard certificates as well!)
Justy by adding the http2 directive, Nginx was able to take advantage of all the modern, baked in advantages of the newest HTTP features. Note that if you want to take advantage of HTTP2 (previously SPDY), you must use HTTPS. Read more about it here.
Utilize Caching & Compression Directives
What more could be accomplished through just Nginx? The first things that jump out are caching and compression directives.
I was sending raw, uncompressed HTML. With just a single gzip on; line, I was able to go from 16000 bytes to 8000 bytes, a decrease of 50%.
Additionally, my site changes fairly infrequently, so I wanted the resources to be cached for as long as possible. This would make it so that, on subsequent visits, users would not need to redownload all assets (especially bundle.js).
My updated server config looks like this. Note that I wonât touch on all the changes I made, such as TCP settings changes, gzip directives, and file cache. If youâd like to know more about these, read this article on tuning Nginx.
And the corresponding server block
Lazy Loading
Lastly there was a small change to my actual site that would improve things by a non-negligible amount. There are 5 images that arenât seen until you press on their corresponding tabs, but that were loaded at the same time as everything else (due to their being in a <img src=ââŠâ> tag.
I wrote a short script to modify the attribute with every element with the lazyload class.
So once the document had completed loading, it would modify the <img> tags so that they went from <img data-src=ââŠâ> to <img src=ââŠâ>, and load it in the background.
Conclusion
This improved my page load times from more than 8 seconds to ~350ms on first page load, and an insane ~200ms on subsequent ones. I really recommend reading through all of High Performance Browser Networkingâââitâs a fairly quick read, and provides an incredibly well written overview of the modern internet, and optimizing at every layer of the modern internet model.
Did I miss anything? See anything that violates best practices or that could improve my performance even more? Feel free to reach outâââJonLuca De Caro!
10x Performance Increases: Optimizing a Static Site was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.