blog.polynom.me/static-site-generator/index.html
2024-01-05 22:03:16 +00:00

204 lines
14 KiB
HTML

<!doctype html>
<html lang="en-gb">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="https://blog.polynom.me/css/index.css" rel="stylesheet" integrity="sha384-EJX4ZZbYMJeuoLRp93IbM/RYSzZmxw42TK7sgSRBEMChbBFK4NYUQEfsz3nBJQm8" />
<link rel="alternate" type="application/rss+xml" title="blog.polynom.me Atom feed" href="https://blog.polynom.me/atom.xml">
<meta property="og:description" content="" />
<meta property="og:title" content="Jekyll Is Cool, But..." />
<title>Jekyll Is Cool, But...</title>
</head>
<body>
<div class="flex flex-col p-2 md:p-8 items-start md:w-4/5 mx-auto">
<!-- Header -->
<div class="flex flex-row self-center">
<img class="w-12 h-12 md:w-24 md:h-24 rounded-lg" src="https://blog.polynom.me/img/avatar.jpg" integrity="sha384-uiNteVXosQ2+o/izp41L1G9VwuwYDYCOPxzFWks058DMUhW7KfQXcipM7WqgSgEZ" alt="Profile picture"/>
<div class="ml-4 self-center">
<a class="self-center text-2xl font-bold" href="/">PapaTutuWawa's Blog</a>
<ul class="list-none">
<li class="inline mr-8"><a href="/">Posts</a></li>
<li class="inline mr-8"><a href="https://blog.polynom.me/atom.xml">RSS</a></li>
<li class="inline mr-8"><a href="https://polynom.me">About</a></li>
</ul>
</div>
</div>
<!-- Container for posts -->
<div class="mx-auto mt-4 w-full md:max-w-prose">
<h1 class="text-indigo-400 text-3xl">Jekyll Is Cool, But...</h1>
<span class="text-md mt-2">Posted on 2020-09-29</span>
<!-- Actual article -->
<article class="prose lg:prose-lg text-white mt-4">
<p>I love static site generators. They are really cool pieces of software.
Give them some configuration files, maybe a bit of text and you receive
a blog or a homepage. Neat!</p>
<span id="continue-reading"></span>
<p>For a long time, I have been using <a href="https://github.com/jekyll/jekyll"><em>Jekyll</em></a>
as my static site generator of choice. Mostly, because it is one of the
most famous ones out there and thus there are tons of plugins, documentation
and templates to get started. It was nice, until I wished it would do
a bit more...</p>
<p>During some time off, I wanted to do an overhaul of my infrastructure. Make
things cleaner, document more things and finally do those tasks that I have
been pushing aside for quite some time. One of those things is to make all
my webpages, which today only include <a href="https://git.polynom.me/PapaTutuWawa/blog.polynom.me">this blog</a>
and my <a href="https://git.polynom.me/polynom.me/xmpp-invite-web">XMPP invite page</a>,
share common assets. This got started after I wrote the invitation page
and thought that it looked pretty good.</p>
<p>So off I went to create a subdomain for my own &quot;CDN&quot;, generate a TLS
certificate and... I got stuck. I wanted to have <em>Jekyll</em> generate two
seperate versions of my pages for me depending on what I wanted to do:
One with local assets for local previewing and testing and one with my
&quot;CDN&quot; attached. As such I would have liked to have three files: <code>_config.dev.yml</code>,
<code>_config.deploy.yml</code> and <code>_config.common.yml</code>, where <code>_config.common.yml</code>
contained data shared between both the deployed and the locally developed
version and the other two just contain a variable that either points to a local
folder or my &quot;CDN&quot;. However, I have not found a way to do this. Looking back, I perhaps
would have been able to just specify the common config first and then specify another
config file to acomplish this, but now I am in love with another piece of software.</p>
<p>Additionally, I would have liked to integrate the entire webpage building process
more with my favourite build system, <em>GNU Make</em>. But <em>Jekyll</em> feels like it attempts
to do everything by itself. And this may be true: <em>Jekyll</em> tries to do as much as
possible to cater to as many people as possible. As such, <em>Jekyll</em> is pretty powerful, until
you want to change things.</p>
<h2 id="introducing-makesite">Introducing makesite</h2>
<p>While casually browsing the Internet, I came across a small
<a href="https://github.com/sunainapai/makesite"><em>Github</em> repository</a> for a
static page generator. But this one was different. The entire repository was just
a Python script and some files to demonstrate how it works. The script itself was just
232 lines of code. The Readme stated that it did one thing and that the author was not
going to just add features. If someone wanted a new feature, he or she was free to just
add it by themself. Why am I telling you all this? Because this is the - in my opinion -
best static site generator I have ever used.</p>
<h3 id="simplicity">Simplicity</h3>
<p><em>makesite</em> is very simple. In its upstream version, it just generates user defined pages,
renders a blog from Markdown to HTML and generates a RSS feed. It does templating, but without
using heavy and fancy frameworks like <em>Jinja2</em>. The &quot;<em>Getting Started</em>&quot; section of <em>makesite</em> is
shorter than the ones of other static site generators, like <em>Jekyll</em> and <em>Hugo</em>.</p>
<p>This may seem like a bad thing. If it does not do thing X, then I cannot use it. But that is where
<em>makesite</em>'s beauty comes in. You can just add it. The code is very short, well documented and
extensible. It follows the <a href="https://suckless.org/philosophy/">&quot;<em>suckless philosophy</em>&quot;</a>. In my case,
I added support for loading different variables based on the file <em>makesite</em> is currently compiling,
copying and merging different asset folders - and ignoring certain files - and specifying variables
on the command line. Would I upstream those changes? Probably not as they are pretty much unique to
my own needs and my own usecase. And that is why <em>makesite</em> is so nice: Because it is not <em>a</em> static
site generator, it is <strong>your</strong> static site generator.</p>
<h3 id="speed">Speed</h3>
<p><em>makesite</em> is fast... Really fast. In the time my Makefile has compiled my page and tar-balled it,
ready for deployment, <em>Jekyll</em> is still building it. And that makes sense, <em>Jekyll</em> is pretty powerful
and does a lot. But for me, I do not need all this power. This blog is not so difficult to generate,
my invite page is not difficult to generate, so why would I need all this power?</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span># Jekyll version
</span><span>&gt; time make build
</span><span># [...]
</span><span>make build 1.45s user 0.32s system 96% cpu 1.835 total
</span><span>
</span><span># makesite version
</span><span>&gt; time make build
</span><span># [...]
</span><span>make build 0.35s user 0.06s system 100% cpu 0.406 total
</span></code></pre>
<h3 id="buildsystem-integration">Buildsystem Integration</h3>
<p>In case of <em>Jekyll</em>, <em>Jekyll</em> pretty much <em>is</em> your buildsystem. This is not so great, if you already
have a favourite buildsystem that you would prefer to use, since it does not integrate well. <em>makesite</em>, on
the other hand, does just the bare minimum and thus gives the buildsystem much more to work with. In my case,
<em>makesite</em> just builds my blog or my other pages. If I want to preview them, then my Makefile just starts a
local webserver with <code>python -m http.server 8080</code>. If I want to deploy, then my Makefile tar-balls the resulting
directory.</p>
<pre data-lang="makefile" style="background-color:#2b303b;color:#c0c5ce;" class="language-makefile "><code class="language-makefile" data-lang="makefile"><span style="color:#65737e;"># [...]
</span><span>
</span><span style="color:#8fa1b3;">serve</span><span>: </span><span style="color:#b48ead;">${</span><span style="color:#bf616a;">OPTIMIZED_IMAGES</span><span style="color:#b48ead;">}
</span><span> </span><span style="color:#bf616a;">python</span><span> ../shared-assets/makesite.py \
</span><span style="color:#bf616a;"> -p</span><span> params.json \
</span><span style="color:#bf616a;"> -v</span><span> page_assets=/assets \
</span><span style="color:#bf616a;"> -v</span><span> build_time=&quot;</span><span style="color:#b48ead;">${</span><span style="color:#bf616a;">BUILD_DATE</span><span style="color:#b48ead;">}</span><span>&quot; \
</span><span style="color:#bf616a;"> --assets</span><span> ../shared-assets/assets \
</span><span style="color:#bf616a;"> --assets</span><span> ./assets \
</span><span style="color:#bf616a;"> --copy-assets </span><span>\
</span><span style="color:#bf616a;"> --ignore</span><span> ../shared-assets/assets/img \
</span><span style="color:#bf616a;"> --ignore</span><span> assets/img/raw \
</span><span style="color:#bf616a;"> --include</span><span> robots.txt \
</span><span style="color:#bf616a;"> --blog </span><span>\
</span><span style="color:#bf616a;"> --rss
</span><span> </span><span style="color:#96b5b4;">cd</span><span> _site/ &amp;&amp; </span><span style="color:#bf616a;">python -m</span><span> http.server 8080
</span><span>
</span><span style="color:#8fa1b3;">build</span><span>: </span><span style="color:#b48ead;">${</span><span style="color:#bf616a;">OPTIMIZED_IMAGES</span><span style="color:#b48ead;">}
</span><span> </span><span style="color:#bf616a;">python</span><span> ../shared-assets/makesite.py \
</span><span style="color:#bf616a;"> -p</span><span> params.json \
</span><span style="color:#bf616a;"> -v</span><span> page_assets=https://cdn.polynom.me \
</span><span style="color:#bf616a;"> -v</span><span> build_time=&quot;</span><span style="color:#b48ead;">${</span><span style="color:#bf616a;">BUILD_DATE</span><span style="color:#b48ead;">}</span><span>&quot; \
</span><span style="color:#bf616a;"> --assets</span><span> ./assets \
</span><span style="color:#bf616a;"> --copy-assets </span><span>\
</span><span style="color:#bf616a;"> --ignore</span><span> assets/img/raw \
</span><span style="color:#bf616a;"> --include</span><span> robots.txt \
</span><span style="color:#bf616a;"> --blog </span><span>\
</span><span style="color:#bf616a;"> --rss
</span><span> </span><span style="color:#bf616a;">tar -czf</span><span> blog.tar.gz _site
</span></code></pre>
<p>This is an excerpt from the Makefile of this blog. It may seem verbose when <em>Jekyll</em> does all this
for you, but it gives me quite a lot of power. For example:</p>
<ul>
<li><code>-v page_assets=...</code> (only in my version) gives me the ability to either use local assets or my &quot;CDN&quot; for deploying;</li>
<li><code>--copy-assets --assets ./assets</code> (only in my version) allows me to copy my static assets over, so that everything is ready for deployment. If I want to use all assets, including the shared ones, then I just add another <code>--assets ../shared-assets/assets</code> and change the <code>page_assets</code> variable;</li>
<li>conditionally decide if I want a blog and/or an RSS feed with <code>--blog</code> and <code>--rss</code></li>
<li><code>-v</code> allows me to pass variables directly from the commandline so that I can inject build-time data, like e.g. the build date</li>
</ul>
<p>If I wanted to, I could now also add a minifier on the build target or page signing with <a href="https://github.com/tasn/webext-signed-pages">Signed Pages</a>.
It would be more difficult with <em>Jekyll</em>, while it is just adding a command to my Makefile.</p>
<p>Another great thing here is the usage of <code>${OPTIMIZED_IMAGES}</code>: In my blog I sometimes use images. Those images have to be loaded and, especially if
they are large, take some time until you can fully see them. I could implement something using JavaScript and make the browser load the images
lazily, but this comes with three drawbacks:</p>
<ol>
<li>It requires JavaScript for loading an image, which is a task that the browser is already good at;</li>
<li>Implementing it with JavaScript may lead to content moving around as the images are loaded in, which results in a terrible user experience;</li>
<li>Some people may block JavaScript for security and privacy, which would break the site if I were to, for example, write a post that is filled with images for explanations.</li>
</ol>
<p>The target <code>${OPTIMIZED_IMAGES}</code> in my Makefile automatically converts my raw images into progressive JPEGs, if new images are added. However, this
rebuild does not happen every time. It only happens when images are changed or added. Progressive JPEGs are a kind of JPEG where the data can be
continously loaded in from the server, first showing the user a low quality version which progressively gets higher quality. With <em>Jekyll</em> I probably
would have had to install a plugin that I can only use with <em>Jekyll</em>, while now I can use <em>imagemagick</em>, which I have already installed for other
use cases.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Is <em>makesite</em> easy? It depends. If you want to generate a website with blog
that fits exactly the way upstream wrote the script, yes. If you want to do
something different, it becomes more difficult as you then have to patch
<em>makesite</em> yourself.</p>
<p>Per default, <em>makesite</em> is more limited than other static site generators out
there, but that is, in my opinion, where <em>makesite</em>'s versatility and
customizability comes from. From now on, I will only use <em>makesite</em> for my
static pages.</p>
</article>
<!-- Common post footer -->
<div class="mt-6">
<span class="prose lg:prose-lg text-md text-white">
If you have any questions or comments, then feel free to send me an email (Preferably with GPG encryption)
to papatutuwawa [at] polynom.me or reach out to me on the Fediverse at <a href="https://social.polynom.me&#x2F;papatutuwawa">@papatutuwawa@social.polynom.me</a>.
</span>
</div>
</div>
</div>
</body>
</html>