はじめに
このブログでは、できるだけ軽く、速く、読みやすい技術ブログを目指している。
基本方針はシンプルだ。記事本文は静的なHTMLとして出し、初回表示に不要なJavaScriptを絡めない。装飾や機能を増やすときも、それが本当に読む体験に必要かを考えるようにしている。
その方針の中で、今回 Shiki を使ってシンタックスハイライトを導入した。
なぜシンタックスハイライトを入れたのか
最初は、シンタックスハイライトを入れるべきか少し迷っていた。
このブログは「爆速」を意識しているため、便利そうだからという理由だけでライブラリを追加したくなかった。コードブロックも、短いものであればプレーンテキストのままでも読める。
ただ、技術ブログを書いていく以上、コードや設定ファイルは避けられない。Astro、TypeScript、CSS、Cloudflare Workers、GitHub Actions などの記事では、複数行のコードや設定例を載せることになる。
そのときに、すべて単色のコードブロックだと視線の移動が増える。キーワード、文字列、コメント、プロパティの境界が分かりにくくなり、本文よりもコードを読む負担が大きくなる。
技術ブログにおいて、コードは本文の補足ではなく、理解を支える重要な情報である。であれば、必要最低限のシンタックスハイライトは読みやすさのために入れる価値があると判断した。
なぜ Shiki を選んだのか
シンタックスハイライトの候補としては、Prism.js や highlight.js のような選択肢もある。軽量さだけを見れば、それらを選ぶ考え方もある。
それでも今回は Shiki を選んだ。
理由は、ビルド時にハイライト済みのHTMLを生成する方針と相性が良かったからだ。
このブログでは、記事本文をクライアント側で組み立てない。Markdownをビルド時にHTMLへ変換し、ブラウザにはできるだけ完成済みのHTMLを渡す。Shiki はこの考え方に合っている。
ブラウザ上でコードを解析して色を付けるのではなく、事前にハイライトしたHTMLを配信できる。つまり、読者が記事を開いたあとに、シンタックスハイライトのためだけに余計なJavaScriptを実行しなくてよい。
「コードを読みやすくしたいが、初回表示の負荷は増やしたくない」という今回の要件には、Shiki がちょうどよかった。
実際のコード例
Shiki では、たとえば次のようにコードを HTML に変換できる。
import { codeToHtml } from "shiki";
const html = await codeToHtml(`const message = "Hello, Shiki";`, {
lang: "ts",
theme: "github-dark",
});
console.log(html);
この処理はビルド時やサーバー側で実行できるため、記事を読むユーザーのブラウザでハイライト用の JavaScript を動かす必要がない。
このブログでは、こうした仕組みを使って、コードブロックを読みやすくしつつ、記事ページ自体は静的で軽いまま保つ方針にしている。
個人的には GitHub Actions の YAML がかなり相性いい。
理由は、単色だと読みづらいけど、ハイライトされると効果がわかりやすいから。
たとえば、設定ファイル系のコードもハイライトがあるだけでかなり読みやすくなる。
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
自作しなかった理由
最初は、必要最低限のシンタックスハイライトを自作することも考えた。
たとえば、TypeScriptやJSONだけを対象にして、正規表現でキーワードや文字列に色を付けるくらいなら作れそうに見える。
しかし、実際にはすぐに限界が来る。
JavaScript、TypeScript、CSS、HTML、JSON、YAML、Shell などを扱い始めると、言語ごとの構文差を無視できなくなる。コメント、文字列、テンプレートリテラル、ネスト、エスケープ、属性、設定ファイル特有の書き方など、考えることが多い。
中途半端な自作ハイライトは、軽く見えても保守コストが高い。表示が少し崩れるたびに直す必要があり、記事を書く時間よりもハイライトの調整に時間を使ってしまう可能性がある。
このブログで大事にしたいのは、仕組みを作り込むことではなく、学習や開発の記録を読みやすく残すことだ。その目的から考えると、構文解析は Shiki に任せる方が自然だった。
依存関係を増やすことへの考え方
このブログでは、依存関係を増やしすぎないことを意識している。
ライブラリを1つ追加すると、サイズだけでなく、アップデート対応、設定、互換性、セキュリティ確認も増える。特にクライアント側に入る依存は慎重に見たい。
ただし、依存関係をゼロにすることが目的ではない。必要な機能まで無理に自作して、品質や保守性を落とすのは本末転倒である。
今回の Shiki は、導入する理由が明確だった。
- 技術記事のコードを読みやすくする
- ブラウザ側でハイライト処理を走らせない
- VS Code に近い自然な見た目にできる
- 自作よりも構文解析の精度と保守性が高い
- Astro の静的サイト構成と相性が良い
この条件を満たしているなら、依存関係を1つ増やす価値はある。
導入時に意識したこと
Shiki を入れるからといって、何でも盛るつもりはない。
このブログでは、あくまで静的で軽い記事ページを保ちたい。そのため、シンタックスハイライトも次の方針で扱う。
- 記事表示後にハイライト用JavaScriptを動かさない
- 必要な言語を中心に使う
- テーマや装飾を増やしすぎない
- コードブロックの見た目は読みやすさを優先する
- ページ全体の表示速度を犠牲にしない
大事なのは、Shiki を入れること自体ではない。コードを読みやすくしながら、ブログ全体の軽さを壊さないことである。
おわりに
爆速な技術ブログを作るうえで、機能を足す判断は意外と難しい。
軽さだけを見れば、何も入れないのが一番だ。しかし、技術記事として読みづらくなってしまうなら、それは良いブログとは言えない。
今回 Shiki を導入したのは、見た目を豪華にするためではない。コードを自然に読めるようにしつつ、クライアント側の負荷を増やさないためである。
速く、軽く、読みやすく。
このバランスを崩さない範囲で、必要なものだけを慎重に選んでいきたい。