続々々・ブログをはてなブログからHugo+Cloudflare Pages(+R2)に移行しました

Page content

ブログの移行話の続き。もう「移行」というかほとんど「(移行後の)改造」っぽい話になってるけど。。

OGPを記事ごとに変更

別にデフォでOGPさえ指定できてれば記事ごとにわざわざ変更する必要もないのだが技術的好奇心によりやってみたかった。ので、やった。Mainroadのテーマには/layouts/_default/baseof.htmlってのがあり、これにTwitterを含めたOGPの指定がある。これを/themes/配下からルート配下の/layouts/配下にコピーして、以下のように改修:

		{{- if .Params.ogp_image }}
			<meta property="og:title" content="{{ .Params.title }}" />
			<meta property="og:description" content="{{ .Params.description }}" />
			<meta property="og:image" content="{{ .Params.ogp_image }}" />
		{{- else }}
			{{ template "_internal/opengraph.html" . }}
		{{- end }}

各記事(Front Matter)にogp_imageというパラメータを用意して、その定義があるときには、その画像をOGP画像に使ってmetaタグを生成する。ogp_imageがなければデフォルトの{{ template "_internal/opengraph.html" . }}を使う。という、言ってみればまあそんだけ。twitter:imageのほうも似たように改修した。簡単だった。

ちなみに、ogp_imageに指定する画像に関しては、FacebookやTwitterが推奨するOGP画像のアスペクト比を気にしない。してもいいけど、運用上あんまりする気がない。これはライブいってきたの各記事において、必ずと言っていいほど撮るライブハウス前の写真をその記事のOGPにしたかったという目的のほうが強くて、その写真はOGPなんか気にせず撮ってるし、あとでOGPのサイズに合うように加工するのも面倒くさいので、基本そのままでいく。結果的にOGPからすると若干見栄えが悪くなる(変なところでtrimmingされて見える形になる)が、あんまり気にしない。見る人が見れば「あっあのライブだ」ってわかればいいのだ。はてなブログ時代もそんな感じだったし。

逆にそれ以外、つまりIT系やそれ以外の日常雑記系の記事に関してはogp_imageを指定する気はなく、{{ template "_internal/opengraph.html" . }}でデフォルトのOGP画像を使用してもらう。ここに関してはさすがになんかちょっとサイズ合わせておくかと思い、10分くらいで適当に作った。これ↓
ogp

「HugoでOGPを記事ごとに生成する」みたいなキーワードでググルると、結構な割合でtcardgenっていうライブラリを使ったOGP画像の生成方法が紹介されてるんだけど、見てる感じだとその度毎回画像を作らないといけないっぽいのが個人的にあんまり性に合わず、ちょっと腰が重い。ただ技術的な好奇心はあるのでそのうち手を出すかもしれない。というか個人で趣味でやってる開発や運用に関してはほとんどそれがモチベーションだ。こういうところ見ると、やっぱり自分は「ITエンジニア」なんだなあ~と、感心したり苦笑したりする。

見出しにアンカーリンクを設定

よくあるやつ。h2タグとかその辺の見出しにホバーすると鎖っぽいマークが出てきてリンクになるというアレ。別になくても困らないんだが自ブログ内の記事リンク作るときにあると便利だし技術的好奇心によりやってみたかった。

ググると出てくる事例は、contentをレンダリングするときに正規表現でh2等の見出しをリンク付きのものに変換するというやつだ。参考になったのはこちらの記事。ただしこちらの記事ではできなかったことや、個人的にやりたかった内容がこちらの記事の案内と少し違うというのもあって、ちょいちょい変えた。以下が個別の対応内容。

  1. こちらの記事ではショートコード(/layouts/shortcodes/headline-anchor.html)を作成すると書いてあるが、それだとコンテンツ側で呼び出すときのコード{{ partial "headline-anchor.html" .Content }}がエラーになってしまった。/layouts/partial/headline-anchor.htmlに移動したら動いた。partialの間違いなんじゃないかなあ?それともhugoのバージョン差異でこういうこと起きうるのか??(よくわからん)
  2. 正規表現を<h[2-9] id=\"([^\"]+)\">)(.+)(</h[2-9]+>)に変えた。ポイントはh2で囲まれた部分の中身の文字列だけを分離した(...(.+)...)ところ。ここだけ取り出して扱いたかったので。余談だが、HugoがreplaceRE関数のページから「ここで正規表現のテストできるよ」ってページ、とても有用。こんなのあったのか。。知らなかった。これは今後も活用必至だ。
  3. あと細かい話だがreplaceRE関数の正規表現の指定をダブルクォーテーション(")からシングルバッククォーテーション(`)に変えた。つまり{{ . | replaceRE "<h[2-9] id=\"([^\"]+)\">)(.+)(</h[2-9]+>)" ... }}じゃなくて{{ . | replaceRE ``<h[2-9] id=\"([^\"]+)\">)(.+)(</h[2-9]+>)`` ... }}に変えた。というかこうしないとエラーでビルドできなかったので。これもHugoのバージョン違いの問題かな??
  4. この方の記事ではh2タグとかの「左側」にリンク画像を表示する例のようだが、個人的には「右側」に表示したかったので(HerokuのDevcenterとかのようにしたかった、こんなかんじ)、ちょっと実装を変えた。また、画像は普通にimgタグを使い、h2タグの中身全体をdisplay: inline-blockにすることで横並びにした。

最終的な/layouts/partial/headline-anchor.htmlは以下

{{ . | replaceRE `(<h[2-9] id=\"([^\"]+)\">)(.+)(</h[2-9]+>)` `${1}<a href="#${2}">${3}<img src="/img/mark_chain_kusari_20x20.png" class="anchor-link" ></a>${4}` | safeHTML }}

CSSは以下

h2 a,
h3 a,
h4 a {
    color: black;
    text-decoration: none;
}
h2:hover a img.anchor-link,
h3:hover a img.anchor-link,
h4:hover a img.anchor-link {
    display: inline-block;
    top: 0;
    left: 100%;
    margin-left: 10px;
}
img.anchor-link {
    display: none;
}

ちなみにホバー時に出る画像はいらすと屋の鎖の画像を拝借している。フリー素材でいいやつが見つからなかったので。。みんなどの辺から入手してるんだろこういうの??(まぁ見つからなかったら描けばいいかって感じではあるが)

SNS shareボタンを追加

個々の記事の下部に「SNSでシェアするボタン」を追加した。やはりほとんどは 技術的好奇心による。 なくてもそんなに困らないしな、こんな個人の弱小ブログ。。改修内容はほとんど以下記事の通り。

上記からの変更点としては、/layouts/partial/share.htmlのレンダリングの条件。上記記事だと{{ if ne .Params.share false}}と各記事のパラメータを参照するようになっていたが、すべての記事にshareパラメータつけるのが面倒くさかったので、config.tomlsnsShare = trueというパラメータを追加させてもらい、{{ if .Site.Params.snsShare }}というふうに条件を変えた。これによりいちいち全部の記事にshareパラメータつけなくてもよくなった。そんだけ。

余談だが、これの修正の検証の最中、/static/css/custom.cssに追加したCSSが反映されなくて困った。hugo server --ignoreCacheとか試したんだが解決せず。Chromeのlocalhostのキャッシュ全部消したら見えるようになった。今まで意識してレスポンスヘッダなんか見てなかったが、、どうもHugoは自分の持ち物はクライアントキャッシュするように動作するっぽいな。まぁそりゃそうか。というかんじです。

Cloudflare pagesを毎日自動ビルド&昔のビルドを自動削除

Cloudflare pagesを毎日自動ビルドするような仕組みを作っておけば、未来日時の記事の予約投稿っぽいことができていいな~っていうのは前の記事でも書いた通りだが、別にそこまで必要性を感じてなかったのでいまいち乗り気がしなかった。一方、ふと昔のビルドの履歴を見ると、全部残っていることが少し気になった。どうもこれ自動的に削除とかしてくれないらしい。なんだよそうなん??しかもこれ(カスタムドメインがないだけで)コミットハッシュ付きの一意なランダムURLは全部に設定されてるので、見ようと思えば見えてしまう。Vercelのdeploymentsと同じだ。これは嫌ですね。。。というわけでそいつらの掃除をする仕組みを作っておいたほうがいい、ということになった。つまり「毎日自動ビルド」はどちらかというと「おまけ」で、「昔のビルドを自動削除」のほうを対応するためにやっておこう、という感じである。あと技術的好奇心による。こういう一見面倒くさいやつも「なんだよしかたね~なぁ~(笑)」とか言って手を出しちゃうオタクなのだ。

これも相変わらずLambdaで実現した。トリガーはEventBridgeで毎日AM8時(JST)起動。時間に特に意味はない。ただ以前はてなブログで予約投稿使ってたときは決まって朝8時に指定していたので、それに倣った形だ。はてなブログでなんで朝8時にしてたか?っていうと、これにも実は別に意味はない。なんとなくだ。昔出社してたときに出勤途中に更新確認できるからいいかもな~くらいなノリだった気がするが覚えてないし、現時点で予約投稿も厳密には機能的に存在しないので、実際のところ何時でもよかった。仕様決定の経緯があいまいで最早誰も知らない、脳死の設計判断、「現行踏襲」ってやつだ。

あと、毎日ビルドするほどのことか??という気もしたが、Cloudflare Pagesのビルド回数の制限は月500回らしいし、30回程度のビルド回数が追加されるくらい大したことあるまい、と思った(むしろ500回もできんの?って感じだ)。こういうスケジュールタスクには、Cloudflare的にはCloudflare Workersを勧めてるようだが、個人的にはLambdaのほうがやりやすかったのでLambdaとさせていただいた。ブログの更新情報を自動ツイートする機能もLambdaで動いてるし。。

処理は簡素で、CloudflareのAPIをfetchでコールする。どういうAPIをコールするか?はこのページの記載に倣う。要するにhttps://api.cloudflare.com/client/v4/accounts/{account_id}/pages/projects/{project_name}/deploymentsに対してメソッドをGETに指定すればビルドの履歴の取得、POSTに指定すれば(ブランチの最新のコミットとってきて)新しくビルドの生成、DELETEに指定すれば過去のビルド履歴(deployments)の削除、という感じになる。ほぼこのページの実装にそのまま倣った。ちなみに削除だけ実行してるとそのうち現行本番が消えてなくなってしまうので、Githubリポジトリに変更があろうがなかろうが、新規のデプロイを必ず1回作成するように処理を実装した。つまりPOST->GET+DELETEの構成。なお、APIトークンはテンプレート使わず作成し、パーミッションは「Cloudflare pagaes - Edit」を選択した。詳細なパーミッションの指定はよくわかってないがこれで動いたのでOKだろう。多分。
20240219-blog-update-after-migration-3-001.png

記事更新のツイート投稿時にハッシュタグも付与

前回作った記事更新時のTwitter自動投稿機能を改造。記事のTAG情報も一緒に取り出して、それをTwitterのハッシュタグにする形で本文に載せて投稿するようにした。

これの目的はどちらかというとやはり主にはライブいってきた記録のためで、アーティスト名をハッシュタグとして付与したかったからだ。ライブいってきた記録では、タイトルに必ずライブの主催バンド(対バンだったら2バンド)を書いてるので、こんなことしなくても本文には必ず載ってくるのだが、なんとなくハッシュタグを使ってみたかった。技術的好奇心である。なお、“9mm Parabellum Bullet"や"Nothing’s Carved In Stone"など、そのまま設定するとハッシュタグとして機能しない文字列が来ることも想定して、文字列の加工処理を組み込んだ。軽くテストはしたので問題ないはずだが実際のデータでどうなるかはちょっとドキドキ。まあお楽しみということで。

言及元の人に移行したことを伝える

まあ、文字通り。はてなブログ時代に言及いただいた人の元記事のほうに、移行した旨と移行先のURLをコメントでお伝えした。反応があればいいが、反応がなければ仕方ないけどそういうものだろうと思うことにする。結構昔の記事にもあるからな。これに限っては技術的好奇心は一切ない。ただのネットコミュニケーションの一環というか。最終的に言及元は以下の通りとなった。参考にしていただきありがとうございます。
20240211-0001-blog-update-after-migrations-3.png

おわりに

大体これで興味のある開発作業は終わったかな、と思う。Review Deploymentに少し興味あるけどまあローカルで動かせれば別にそこまで必須でもないし。そんなわけで、ブログ移行関連の一連のシリーズ記事はこれにて一旦終了とする。気になったらまた随時手を出していき、必要に応じてブログ記事とする。かも。