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

Page content

この日記の続編。残課題とか、その辺について。

残課題対応

  • SSL証明書のエラー云々と言っていた件は、SSL証明書が原因ではなかった。移行のミスで、画像の参照先URLのスキームがhttpsではなくhttpになっていて、httpsのページからhttpで画像を見に行ってることが原因だった。要するにただのアホ。スマホのChromeからだと証明書の部分に警告が出ていたのでてっきり証明書の問題だと勘違いしてしまっていた。注目すべきは 「このサイトで目にする画像は、悪意あるユーザーによって差し替えられたものである可能性があります。」 という部分だった。(ちょっとわかりづらくない??この表示)
    20240126-0001-iphone-chrome-warning.PNG
    というわけで再度、全501記事の画像参照先URLをhttpsに移行しなおし。501記事一括Commit。重かったぜ。イエア。
  • カテゴリやタグに件数集計したい件は、config.tomlの設定変更だけで終わった。[Params.widgets]内のcategories_counterおよびtags_counterをそれぞれtrueにするだけで表示される。完了。。
  • 年月ごとの集計をしたかった件。どうもArchiveというTaxonomyを別に用意して、それを使うやり方が一般的なようだ。こちらとかで紹介されている。ただ、移行時点ではここを意識してなかったので、archive: は付いていなかった。というわけで、しょうがないので移行後に再度全部つけた。(簡単なNode.jsのツールを組んで実行。2秒くらいで終わったw)幸いdate:に記事の日時は出力されてるので、それを使ってarchive:の値を生成して再出力した。ここまでが第一段階。
  • 年月ごとの集計をしたかった件の続編。archiveの値をもとに記事数集計してサイドバーに出すwidgetをつくる。基本的にはMainrodに備わっているcategoriesとかのpartialのコードをパクって新たにwidget用のhtmlファイルを作成した。ハマったのが以下の辺り。
    • T "categories_title"というコードがなんだかよくわからなかった。config.tomlに見当たらなくて、どこで設定するんだろうと思ってたら、i18nディレクトリ配下にあった。へー。後で調べてみたら確かにTというのはTranslateのAliasだった。なるほど。
    • Hugoのテンプレートの書き方がわからん。例えば、文字列の長さとるのにも一苦労だった。もっといいやり方がありそうだが、$name | strings.Count ""とか書いてとりあえず乗り切った。どうもstring.lengthみたいないい感じのメソッドはなく、このstrings.Countも、指定された文字が文字列内にいくつあるかを検索するメソッドらしくて、空文字を渡すことで文字数をカウントするという、なんとも切ないやり方だ。絶対なんか間違ってる。。気がする。その他、ifによる条件分岐、rangeによるループなど、書き方が独特で分からないことが多い。archives:にはYYYYとYYYYMMで2種類の情報を付与してるので、2014年以降のarchivesをリストで出すと結構な長さになり、あんまり見栄えが良くない。はてなブログのときみたいに、初期表示はYYYYだけにして、クリックしたら配下の年月YYYYMMが開閉する、という作りがいいんだが、このHugoテンプレートの使い方がよくわからない絡みで、うまい具合に実装できなかった。というわけでとりあえず今はwidgetに出力するのはYYYYだけにしている。(上に書いた文字列長のチェックを使ってYYYYMMを省いている)ここはもう少しなんとかしたい部分なので、継続的に対応していくつもり。
    • これの関連で、現在は2014~2024までが昇順で並んでいる形だが、これを降順2024~2014に変更したい。はてなブログがそうだったし、記事も降順で出てくるので、そっちの方が感覚に合っている。が、archivesをソートする方法がわからない。。Alphabetical.Reverseとかすればいいんじゃないかと思ってたんだが、これ書いたら何故かarchivesが全く見えなくなってしまった。なんでやねん。まあ多分なんか使い方が間違ってるんだろう。ここも継続して確認していく。
  • Pagefindで独自の検索機能を付けたいという件。ほぼほぼこちらの記事に書いてある内容に沿って実施。結論、「比較的」簡単にできた。いくつか対応のポイントはあって、以下の辺り。
    • Mainroadには一応Google検索用のWidgetが備わっているので、枠だけそれをパクって中身だけPagefindのGetting StartedのUIに書き換えた別widgetを用意して、config.tomlのsearchのwidgetをそっちに変更した。ちなみに以下のような感じ。ほぼGetting Startedの内容のまま。大外のdivタグだけMainroad。
      <div class="widget-search widget">
        <link href="/pagefind/pagefind-ui.css" rel="stylesheet">
        <script src="/pagefind/pagefind-ui.js"></script>
        <div id="search"></div>
        <script>
            window.addEventListener('DOMContentLoaded', (event) => {
                new PagefindUI({ element: "#search", showSubResults: true });
            });
        </script>
      </div>
      
    • この方のブログに沿ってpagefind_extendedを利用。ただしnpx pagefind_extended@latestは動作しない。しょうがないのでリリースページから最新版のprecompile版をダウンロードしてきて解凍。hugoのあとこの方と同じく./pagefind_extended --site public --glob="{posts}/**/*.html" --output-path="static/pagefind"を実行。約10秒ほどで完了した。
    • 解凍後のpagefind_extendedは200MBを超えており、無邪気にgit pushするとGithubに怒られる。はい、怒られたやつです。。なのでリポジトリにはのせられない。かといって.tar.gzあげるのもなんかちょっといただけない。というわけで、Cloudflare Pagesのビルドで頑張ってもらう事にした。Cloudflare Pagesのビルド環境はUbuntuベースのコンテナらしいんだが、wgetとかその辺ちゃんと入ってるのか心配だったか、とりあえずやってみたら動いた。ので、OKとする。以下のようなビルド用のshellを用意し、
      #!/bin/sh
      
      # build hugo
      echo "run hugo"
      hugo
      
      # download pagefind_exteded
      echo "download pagefind_extended from:${PAGEFIND_EXTENDED_URL}"
      wget ${PAGEFIND_EXTENDED_URL}
      gzip -d *.gz
      tar -xf *.tar
      
      # run pagefind_extended
      echo "run pagefind_extended"
      ./pagefind_extended --site public --glob="{posts}/**/*.html" --output-path="static/pagefind"
      
      exit 0
      
    ビルドの環境変数PAGEFIND_EXTENDED_URLという名前で最新のリリースURLを指定して、Build Configurationでビルドのコマンドをsh custom-build.shのようにすればいい。普通に全部動いた。ただ、ビルド環境の詳細が不明なため(あまり調べられてもいないが…)、ある日突然wgetとか消えましたみたいなこともあるかもしれないので、ここは注意が必要な気もしている。少なくとも2024年1月26日現在は動くことを確認済。
    • とりあえず字ブログ内検索は実装できたんだが、Mainroadの名残で、検索結果がサイドバーの大きさでしか表示されないのが、若干いけてない気もしている。ここはそのうち直すかもしれない。
  • 新規記事が出たときにTwitterに投稿したい要件。の手始めとしてまずRSSを確認。MainroadのデフォルトだとrssLimitが存在しないせいか、作成された/index.xmlが見た感じ全部の記事がぶわーっと連なって出てきており、これが原因なのかブラウザで表示したりSlackのRSSフィードで読み込ませるとエラー起こした。とりあえずrssLimit=20くらいにして生成したところエラー消えたので、一旦これで様子見る。なんらか記事を投稿しないとRSSの更新も確認できないが、とりあえずIFTTTのRSS Trigger Appletを仕掛けた。行き先はWebhookでLambda(+関数URL)。一旦これで動作確認してから細かいことを考える。Lambdaに向けてぶっ放つのは、Twitter投稿に必要なOAuth TokenがDynamoDBにあるから。AWSに乗せるのが一番わかりやすい。ついでに各地へのping通知もヤッちまうつもりだが、それは大した話じゃないので追々考える。とりあえずどういうデータが回ってくるのか一通りみてからだ。そもそもIFTTTが動かない気もしなくもないのでその辺も踏まえて検証が先決だ。

残課題とは別に実施した対応

  • Twitter上でOGP画像が表示されていないことに気づいたので、修正。Mainroadは/layout/_default/baseof.html{{ template "_internal/opengraph.html" . }}とかのHugoでOGPを使うためのコードは既に記述されてるので、config.tomlopengraph = trueとか設定してれば基本的にはそれでOK。画像が出ない件はまた別で、どうもconfig.tomlimages = ["/img/xxx.png"]を記述すればいいらしい。こちらのブログの記事が参考になった。画像は/static/配下からの相対パス。
  • Custom CSSの読み込みエラーが出ていたので、旧ブログ用に使ってたスタイルシート群を独立させて、Custom CSSとして配置してエラーを解消させた。ただ、よく考えたらconfig.tomlのその行コメントアウトするだけでも良かったな。。まあ別にいいけど。
  • もはやあんまり意味があるようにも思ってないんだが、一応はてなブログ時代に登録していたブログコミュニティへのリンクも追加した。超簡素なwidget用意してケツにくっつけた。だけ。スタイルの当たり方があまりにもアレなのでここはちょっと見直すかもしれない。ただ自分の中で優先度は低い。

他にやりたいこと

  • いわゆるステージング環境的なやつがほしい。↑で書いたRSSの更新確認もそうだが、本番以外に何かもう一つ環境があると、やはり色々やりやすい気がする。Preview Deploymentsというのをうまく使えばできそうな気もするんだよな。この場合だけ実行コマンドを hugo server -Dに設定すればよくて、かつそこにカスタムドメイン割り当ててCloudflareで我が家以外のアクセス拒否ればいいわけで、なんかできそうではある。まぁローカルでhugo server -Dするのもそんなに遅くはないのでそんなに優先度は高くないんだが、時間があったらやってみたい。
  • Deploy Hookを使うと、「毎日0時に更新」とかいう機能も作れそうだな。と思った。これを構築すれば、未来日時の日記を裏で書いておいて(draft: falseにしておく必要はある)、git pushさえしておけば、日を超えた瞬間の予約投稿みたいなことができなくはない。IFTTTでも軽いCronみたいなことはできたはずだから、スケジュールジョブ的にDeploy HookのエンドポイントにWebhookでリクエスト投げるのは、できなくはなさそう。まぁでも外側の仕組みを増やすと管理が面倒くさくなりそうだしな~どうしようかな~という気持ち。ここはエンジニア的好奇心によるところが強い。そのうちやる、かも。

それ以外に気付いたこと・やったこと

  • hugo コマンドだけを単発で放つとビルドだけを実行してサーバーを起動しない、ということができる。pagefindを実行するときに知った。へー。ただ、(知らないだけかもしれないけど)逆に「(ビルド済の資産使って)サーバー だけ 起動する」ってのが出来ない気がする。hugo serverってビルドも一緒にやってるよね??そうなると、ビルド「だけ」を行う目的って何?という気はしなくもない。pagefindみたいに、ビルド後の生成物をサーバー起動するまでの間に拝借する必要があるやつは、まぁわからんでもないが、Hugo本体的には必要とする場面あるのかなあ。という疑問はある。まあそんなに興味もないんだが。他のプラットフォームに移行するとき用とか??
  • Github ActionsのEnvironment Variableに「Secrets」のほかに「Variables」というのがあるのに気付いた。これ昔はSectretsだけじゃなかったっけ??知らずに最初Variablesの方触っちゃったけど、VariablesのほうはSecretsとは違って値が丸見えになるので、Secretsに比べてわかりやすい一方、セキュリティ的には若干抵抗も感じる。AWSのアクセスキーとかは載せる気にはなれないなあ。。昔作った、Github ActionsでLambdaにデプロイするワークフローは、Secretsを使ってるので、今回(RSS更新を受けて起動するLambda関数のリポジトリ)にも、Secretsを使う形で実装したので、Variablesを使う機会はなかったし、そういう意味では今後も使う場面がなさそうだが。どういう使い分けする想定で用意されてるのか少し気にはなる。もっと単純なビルドやCIの設定用かなあ?
  • はてなブログProを解約した。といっても1年契約だったので6月までプランは継続するんだが。また、その関連で、はてなブログのping送信で使っていたIFTTTのアプレットを全部Archiveした。気付いたときにやっておかないとこういうのは絶対忘れるものだ。。あとはてなブログで「移行したのでもう更新しません」という最後の記事の投稿。この数日で、もうほぼ完全にはてなブログからは手を引いた。さらばはてなブログ。