(2022/03/03 追記)Next.js 13 / App Router対応をやった
(2023/10/05 追記)Astroで書き直した
はじめに
ブログを自作した。決め手は以下の四つ。
- 適度な距離
- メンテナンス性
- 高速性と拡張性
- 無広告
1. 適度な距離
あらゆるものが最適化されて提供されるこの時代、遅配や誤配の確率はとても低い。大きなプラットフォームはユーザーのbuzzをすすんで後押しし、かれに向けて、かれのために、とパーソナライズに躍起だ。書き手と読み手の距離は透明に、コミュニケーションは確実に。だがそうではない形式もかつてはあった。ひょっとしたら誰かに拾われるかもしれない、あるいはGoogleのクローラにさえ拾われないかもしれない、そうした確率論的な雲のなかに自らの書いたものを打ち上げる。そして祈る。古き良き日々は理想郷ではなかったかもしれないが、あの誰かのものになる前の世界の、その歪な手触りを覚えておくための、個人サイトという距離感。
2. メンテナンス性
先人たちが示してきたとおり、この手の個人サイトは管理・移行が億劫になった時点でエタる。放置された「〇〇の部屋」、消えて還らない借りドメイン、むなしく刻む入室カウンターたちを眺めるたびに、せめて記事くらいは移行しやすい形式で扱いたいと思うようになった。そういうわけでMarkdown(コンテンツ) + tsx(テンプレート)。この組み合わせならそう簡単には廃れないだろうし、いつか別サービス・別フレームワークに移るときにもそれほど困らない。
3. 高速性と拡張性
Next.js。個人サイトには若干過剰の感もあるものの、ページ遷移の気持ちよさと画像の最適化が魅力的。あと少々複雑なことをしようとしてもフレームワークの守備範囲を出ないのは良い。
4. 広告や統計の排除
過剰な広告・統計に対して憎悪を抱いているため、このサイトには設置していない。唯一、ホスティング先であるVercelが行っているアナリティクスだけは確認している。こちらの記事も参照。
機能一覧と実装
以下はこのブログの機能と実装の展覧会
Markdownの処理
(2022/12/28 更新)
next-mdx-remoteで処理している。
getStaticProps
(/pages
の場合)ないしfetch
/ cache
(/app
の場合)を通じてコンテンツを取得し、JSXにコンパイルして返却する仕様になっている。また内部ではremark / rehype / MDX系のAPIが用いられており、これらの系列のプラグインが利用できる。
記事メタデータの取得
GitHub Flavored Markdown
絵文字
:v:
が ✌️ に。
数式
適当なところで KaTeX のスタイルシートを読み込む必要がある。
(k=1∑nakbk)2≤(k=1∑nak2)(k=1∑nbk2)
eiπ+1=0 ⬅️ インライン数式
ルビ
昨日午後、†聖剣†を振り回す全裸中年男性が出現し……
ページ内の見出しのリンク
➡️ はじめにに飛べるよ
Mermaid Diagram
(2023/05/07 更新)
rehype-mermaidjsを使った。通常のMermaidの使い方では、クライアント側でJSを実行せざるを得ないが、このプラグインを使うとビルド時にヘッドレスChromiumで2 あらかじめSVGが描画され、静的にドキュメントに埋め込まれる。
シンタックスハイライト
rehype-pretty-codeを利用した。このプラグインは内部でshikiを利用しており、スタイル適用がビルド時に行われる(= 追加CSS不要)、VSCodeのカラースキームが使える、などの利点がある。
リンクカード
こういう ⬇️ カード。
上の記事を参考に、unifiedのTransformerプラグインを自作して実装した。おおむね、
- 文書中に単独で貼られたリンクの
Node
を検出
- リンク先にアクセスしてメタデータ(
title
、description
、og image
)を取得
- これらの情報を
Node
の属性に付加し、独自要素(例:<linkcard>
)に置き換え
- 独自要素を、MDXの処理系(
next-mdx-remote
)側で自作コンポーネントに置換
する処理を行っている。4. は以下のような感じになっている。
画像処理
Markdown内の画像をnext/imageに置き換えるremarkプラグインを書いた。置換に加え、画像のサイズ取得・プレースホルダー生成(参考:公式ドキュメント)も行っている。
ダークモード
外部ライブラリを使用。
Open Graph画像の生成
(2022/05/07 更新)
別記事を参照。
サイトマップ生成
(2023/05/07 更新)
別記事を参照。
フィード対応
Feedというライブラリを使って形式を整え、上と同じ要領でビルド時に RSS、Atom、JSON Feed用のファイルを吐かせている。
感想
最高! はてなブログやQiita、Zennあたりと張り合える書き心地かもしれない。