Speeding Up the Site
To share my articles over IPFS, it made sense to embed the CSS and images directly into the HTML so that there would be a single file to share.
Embedding the CSS was the simplest part: I just placed the CSS directly into the site template using the <style></style> tag, and embedding the CSS alone already produced a nice speed gain.
I use HUGO as the framework to generate the site automatically. HUGO works by converting pages written in Markdown, but the same idea applies no matter how the site is built, even if it is written by hand, directly in HTML. With HUGO and a bit of programming, though, it was easy to automate my template and have the images converted to Base64 and inserted into the page automatically.
1{{- if strings.HasPrefix .Destination "http" -}}
2 <img
3 src="{{ .Destination | safeURL }}"
4 alt="{{ .Text }}"
5 {{ with .Title }}title="{{ . }}"{{ end }}
6 />
7{{- else -}}
8 {{ $file := index (split .Destination "#") 0 }}
9 {{ $class := index (split .Destination "#") 1 }}
10 {{ $class = $class | default "floatleft" }}
11 {{ $mime := "jpeg" }}
12 {{- if eq (path.Ext $file) ".webp" }}{{ $mime = "webp" }}{{ end -}}
13 {{- if eq (path.Ext $file) ".png" }}{{ $mime = "png" }}{{ end -}}
14 {{- if eq (path.Ext $file) ".gif" }}{{ $mime = "gif" }}{{ end -}}
15 {{- if eq (path.Ext $file) ".svg" }}{{ $mime = "svg+xml" }} {{ end -}}
16 <img
17 src="data:image/{{ $mime }};base64,{{ readFile $file | base64Encode }}"
18 alt="{{ .Text }}"
19 title="{{ .Title }}"
20 {{ with imageConfig ( printf "%s" $file ) }}
21 width={{ .Width }}
22 height="{{ .Height }}"
23 {{ end }}
24 />
25{{- end -}}
With the images in the HTML as well, the site ended up much faster. The reason is that everything happens over a single connection, and the increase in the HTML size does not have much impact since the traffic is compressed.
Since the result was so good, only one file was left to embed into the HTML to make each page require just a single HTTP request: the favicon. The good news is that modern browsers allow the favicon to be in SVG format, which makes it very simple to embed as text in the HTML and removes the need to keep several versions of the image for each size.
<link rel="icon"
sizes="any"
type="image/svg+xml"
href="data:image/svg+xml;utf8,<svg xmlns=...</svg>"
/>
The time savings will vary depending on the site’s content, the resources it needs to load, external connections, and so on. In my case it is simple, because I rarely use images and never use JavaScript, so the site already loaded fast by nature. The times between the start of the request and the page being fully rendered are running between 300 and 450 milliseconds.
If you try this idea on your own site, remember to collect the timings and compare them to know whether there was an improvement or not. After all, engineering without numbers is just opinion.
As a side effect, keeping all the resources of each article self-contained had other interesting benefits. Saving the page for off-line reading, archiving it on archive.org, and even using the page in integration scripts all became simpler, because I do not have to worry about following links — everything is in a single file with a predictable format.