ブログ生成環境をHugoからNext.jsに移行

published: ,
last modified: .

lang: ja

category: dev

tags: nextjs webdev

このブログを生成しているSSG (Static Site Generator) をHugoからNext.jsに移行しました.

Next.jsの選定理由

  • 技術的興味
    • 性能的にはHugoでもそれほど困ってはいなかったのだが,SPAのお試しやReactの練習がしたかった
  • 構造の簡明さ・柔軟性
    • HugoはGo言語のテンプレート機能を使って手続き型的に処理を組むため,個人的にはあまり複雑なことをしやすいとは言えなかった
      • その一方でHugoはテーマが充実しており,自分でデザインなどを組み立てない場合はかなり良い選択肢なのではないかと思います
    • Next.jsは(Reactの知識があれば)どの部分が何をしているか分かりやすく,制御の自由度も高い

Next.jsで実装したもの

  • タグ,カテゴリ,言語による分類
  • 記事一覧表示でのページ分け
  • 記事の先頭N文字を取得して表示
    • または記事.mdファイルのメタデータに要約があればそれを表示
  • 数式表示 (KaTeX\KaTeX)
  • ソースコードハイライト (highlight.js)
  • ダークモード/ライトモードの切り替え
  • ページ遷移エフェクト

Next.jsで実装した箇所のソースコードについてはいずれGitHubに公開する予定です.以下ではこれらの実装について軽くですが説明します(ソースコード公開時にもう少し詳しく記述する予定です).

タグ,カテゴリ,言語による分類

ここではタグを例として説明します.チュートリアルにもある各記事を表すページposts/[id].tsxのようにタグごとのページtags/[tag].tsxを作ります.getStaticPathsが各タグのパスを返すようにすれば良いです.全ての記事データからタグを抽出・列挙する補助関数を定義して利用すれば実現可能です.

ページ分け

現在何記事目まで表示しているかは「状態」であるため,useStateを使います.次または前のページを選びたい場合はsetState(状態±ページ毎の記事数)[1]として状態を変化させ,現在の状態(すなわち表示する記事の番号)で描画されるべき記事を描画すれば良いです.

記事の先頭N文字

記事のメタデータを取得する際に本文も取得し,markdown-to-textを使って不要なmarkdown部分を除去し,先頭N文字を取得しています.手動で要約したものがある場合はメタデータに記載されているため,この処理をスキップします.

数式表示,ソースコードハイライト

数式表示は以前はMathJaxを使っていましたが,重かったのでKaTeX\KaTeXに変えました.チュートリアルではmarkdown解釈ライブラリとしてremarkを使っていますが,remarkのKaTeX\KaTeXプラグインがうまく動作しなかったため,markdownをmarkdown-itでパースするように変更しています.markdown-itプラグインを使うことでこれら二つは実現できました.

ダークモード/ライトモード

これも状態なのでuseStateを使って切り替えます.初訪問ではデバイス側の指定を読み取って設定し,次回以降は設定値をlocalStorageに格納することで選択を記憶します.html要素のカスタムデータ属性に値を格納してCSS側でその値によってスタイルを切り替える[2]ことで,デザインを切り替えることができます.

ページ遷移エフェクト

Next.jsと相性の良いライブラリがいくつか存在するようですが,今回はそれらを使用せずCSSでアニメーションさせました.Router.events.onでページ切り替えイベントを登録できるため,アニメーションさせる要素のクラス名などをこのタイミングで切り替えることで,ページが切り替わる際にアニメーションを再生させることが可能です.


  1. 実際は負になる場合や最大記事数を超える場合を避けるためmaxminなどで調整します. ↩︎

  2. 実際はカスタムプロパティ(いわゆる変数)のみを切り替えることが可能なため,存外簡単に色変えできます. ↩︎