Digital Rain Memories 2.0公開のお知らせ

または、個人サイトに関する思想について

  • SvelteKit
  • Lifelog

投稿日:

もくじ

はじめに

2023年9月のサイト公開から現在にいたるまで本サイトではHugoによる静的サイト生成を採用していたのだが、この度サイトのフレームワークをSvelteKitにリプレースしてVer2.0にバージョンアップした。

そこで本稿ではサイトをゼロから再実装するに至った経緯と手法、そして個人サイトに関する筆者の個人的な思想について記す。

静的サイトは遅い?

HugoなどのSSGは一度サイトをビルドしてしまえばあとはHTMLとCSSだけのシンプルなWebページを配信するだけでよく、CDNと組み合わせることで爆速ページロードを実現できるのが特徴だが、これらのサイトには欠点がある。SPAに比べてページ遷移が遅いのだ。SPAがサーバーから受信したページごとの差分に基づいてDOMを更新することでページ遷移を実現する一方、SSGによって生成された静的サイトではページ遷移のたびにページ全体のHTMLファイルを読み込み、パースして、レンダリングする必要がある。そのためページ遷移時のオーバーヘッドが大きくなり、結果としてUXの低下を引き起こす。

――というのは半分嘘で、ハウツー記事を掲載する技術ブログやレビューサイトといったサイト訪問者が複数のページを見ずに離脱する可能性の高いWebサイトではやはり余計なデータを含まない静的ページの圧倒的な軽さが存分に発揮されることになる。

――というのも半分嘘で、最近のフルスタックWebフレームワークは先に生のHTMLファイルを送信したあと遅延読み込みしたJavaScriptでページをリアクティブにするハイドレーションと呼ばれるアプローチによって静的サイト並みの読み込み速度を達成しているし、加えてNext.jsやNuxt、SvelteKitなどのフレームワークにはSSGオプションも用意されており、任意のページをアプリのビルド時にプリレンダリングするよう指定できる。暴論ではあるが、もはや現在ではSSGを使うメリットは面倒なことをせずともMarkdownをHTMLに変換できることくらいしかないとも言える(とはいえそのメリットが大きいから本サイトではHugoを採用していたのだが)。

SvelteKit採用の経緯

まあ長々と静的サイトのUXについて書いたが、実をいうとHugoのスピードに特段不満があったわけではなかった。そもそもページが軽量だからページ遷移時の読み込みは十分に速いし、SPAとの違いも両者を並べて比較しない限り気づけるようなものでもない。しかし、html/templateというテンプレート言語を学ばなければならないことやサイトの構造をコントロールするのが難しいこと、そして何より技術スタックが他のサイトと差別化できていないことなどの問題は、サイト公開当初から悩みの種だった。

最終的にHugoからSvelteKitへの全面リプレースという重労働に挑むことを決意したきっかけは、筆者お気に入りの個人サイト「午睡機構」が手書きHTMLからSvelteKitに移行したという投稿だ。Ver 1.0公開時の投稿にもある通りSvelteKitとMarkdownレンダラを組み合わせることの複雑さを恐れてHugoを採用した筆者にとって、先行事例の発生はHugoからの移行を強く後押しした。(実は管理人にSvelteを薦めたのは他でもない筆者自身だったのだが)。

移行の流れ

SvelteKitでMarkdownベースのブログを作る方法については参考にした動画を観てもらうのが早いが、さすがにそれではあんまりなので技術スタックについて軽く説明する。

本サイトは主にMDsveXTailwind CSSで構成されている。MDsveXはSvelteでMarkdownを扱うためのプリプロセッサで、プリプロセッサとしてSvelteコンパイラに統合されるためMarkdownファイルの中にSvelteコンポーネントを直接追加することができる。例えば以下のようなコンポーネントを用意して記事に追加すると:

<script lang="ts">
	let name = ""
</script>

<div class="flex flex-col items-center pt-5 border-y-1 border-main-01">
	<input type="text" bind:value={name} class="px-2 font-sans rounded-sm" />
	<p class="font-sans text-sm">{name ? `こんにちは、${name}さん!` : "名前を入力してください"}</p>
</div>

このようにレンダリングされる。

名前を入力してください

本サイトで普段扱うトピックを鑑みるとこの機能の出番はそう多くなさそうだが、数学や物理学について書いているサイトにリアルタイムデモを設置するといった使い方をするとおもしろそうだ。

通常のSvelteアプリと同様の感覚でMarkdown文書にコンポーネントを追加できるため、Hugoのショートコードで実現していた独自機能も難なく移植できた。以下にルビ振りのために使っていたショートコードRuby.htmlと、それをSvelteで再実装したコンポーネントRuby.svelteの例を掲載する。

<!-- Ruby.html -->
<ruby>
    {{ .Inner | safeHTML }}
    <rp>(</rp>
    <rt>{{ .Get "rt" }}</rt>
    <rp>)</rp>
</ruby>

このショートコードをSvelteで再実装したものが以下のコンポーネントだ。どちらもrtという引数を受け取って<rt>要素に入れるという構造は共通している。

<!-- Ruby.svelte -->
<script lang="ts">
	export let rt: string
</script>

<ruby>
    <slot />
    <rp>(</rp>
    <rt>{rt}</rt>
    <rp>)</rp>
</ruby>

シンタックスハイライターにはshikiを使っている。shikiはVSCodeと同じトークナイザでソースコードをパースするためハイライトが正確なうえ、コードブロックに任意のVSCode用テーマを使えるという特徴がある。欠点があるとすればHugoのハイライターと違ってhtml/templateのサポートがないところくらいだろうか。

また、+layout.tsexport const prerender = trueという行を追加することによってすべてのページをサイトのビルド時にプリレンダリングするよう設定している。これで理論上はHugoと同等の速度でページを読み込めるはずだ。

おわりに

HugoからSvelteKitに全面移行した結果、当初の目論見どおりSSGによる高速なページ読み込みとCSRによる快適なナビゲーションを達成できた。ベンチマーク結果などは割愛する1が、全体的なUXは以前より向上しているはずだ。

そして何より、扱いやすいWebフレームワークでサイトを作れるようになったことによるDXの向上が大きかった。URLをif文に通してページごとにCSSファイルを出しわけるだけでも一苦労だった日々は終わり、いまではTailwind CSSのおかげで生のCSSを書く場面さえ激減した。萌え萌えアクセスカウンターが自前実装される日も近いだろう。

SNSやCMSの台頭によってコモディティ化が進んでしまったインターネットを照らす灯である個人サイトは多種多様なものであってほしいという願いがあるため、この記事が大手プラットフォームから個人サイトへ回帰したいと考えている人や、独創性のあるサイトを作りたいと考えている人へ勇気を与えられたら幸いだ。

著者プロフィール


  1. はじめはWeb Vitals拡張機能で比較検証した結果を掲載するつもりだったが、どちらのフレームワークもあまりにも速く0.1秒の誤差でさえ大きな違いを生んでしまうため諦めた