Transition to a Static Website
[Dynamic Link — Static Link]
Posted: 2020-10-04
Last Edited: 2020-10-04
Recognising the flaws
This website used to be hosted with ASP.NET on my raspi 3B. That classes as
extreme overkill for what was (and still is) a 100% static website. Aside
from the fact that running Kestrel behind Nginx will be slow by itself, the
raspberry pi is not what one would call a powerful platform
. Granted, at
1 GHz on 4 cores it's relatively fast, and more than sufficient to use as a
daily driver for basic tasks, but when running C# it just wasn't fast enough
for what i would consider a decent browsing experience.
Part of the problem was that ASP.NET would precompile each page from its .cshtml.g into an internal representation the first time the page was accessed after a restart of Kestrel. This meant that i would have to sit through a 10-second compile every time i restarted my raspi and visited my website. That alone was atrocious.
In additon, the fact that i was running ASP.NET itself was part of the problem. ASP.NET is a very powerful framework, but i wasn't using it to its full potential. I was using it to render a static site. So all of the extra features were sitting idle and unused whilst Kestrel served the same static pages over and over. It was simply a waste of computing power, since i was using Nginx to proxy requests to Kestrel, which can already serve static files.
This all led me to seek a replacement for my hosting stack.
Searching for a replacement
The two things that i prioritised when searching for a replacement for ASP.NET were final size (directly correlated with page load speed) and ease of deployment (to make my life as easy as possible). Initially i had my sights set on using a static webpage generator to build my website. My reasoning was that these generators would allow me to add some dynamic elements should i want to, that they would produce compact final products, and would save me time. I picked next.js as my generator of choice.
Next.js produced a relatively small output at ~61KB all-in-all. The majority of that was the js framework that comes bundled with next.js, and a small fraction came from the actual content on my website (~15KB). Deployment was relatively easy, since next.js places your static site in the out/ folder by default. Its contents were simply copied via sftp to the webroot on my raspi, and done! I was initially happy with these results, but after re-reading motherfuckingwebsite i decided to return to the drawing board.
Finding the solution
I ended up just rolling my own 'static site generator'. It consists of a simple shell script, which calls a few npm tools (my html, css, and js minifiers), and a python script to actually convert my markdown posts into html to render. It uses misaka (a binding for Hoedown) for the markdown -> html, and also places the final product into out/ to make deployment as simple as possible. The source is available on my GitHub here. Whilst this is not as compact as it could be, such as if i did everything from within the shell script, for now i'm happy with it. It does what it is meant to do, and my website is again ~15KB.
Getting sidetracked
I also decided to compile Nginx from scratch, so i could fine-tune what modules were included in the final binary. This meant i had as little redundant code (read: bloat) as possible in the final product. It also allowed me to include the Brotli compression module, and the Headers-Mode module. These were important to help increase security and performance on my raspi. I built Nginx against libressl, just to ensure that i had a solid crypto library backing up my website. All in all it was probably a bit overkill, but i don't mind. To top it off, i also built Tor from source, to host a hidden version of my website. Tor was also built against libressl, as in this case i need the security. The sources for my Nginx and Tor builds can be found here (nginx) and here (tor). Feel free to send pull requests and improve the build scripts!