WordPressがつらい

今までブログ用に利用していたWordPressですが、CMSの制約と自由度の高さ、 脆弱性に対応するためのバージョンアップへ追従するのがつらくなってきました。

ということで、静的にWebサイトを生成するHugoにWebサイトを移行してみました。

移行にあたってハマったポイントとか

テーマ選びが重要っぽい

Hugoは生成エンジンとテーマを自身で選択し、その上でコンテンツを作成し生成するという形になります。 これはWordPressも同じですが、テーマによって利用できる機能に差異があったり、コンテンツの作り方が変わってきたり(shortcodesという独自構文で記載するもの)という注意点があります。

今回使ったテーマ

今回このサイトではrobustというテーマをベースに利用させて頂いていますが、 自身が使いやすいようにテーマを大幅にカスタマイズしています。

作成当初はメインリポジトリ内にgitmodules機能でリポジトリをインポートし、layouts/ディレクトリ内で改変したい内容を記載していましたが、 カスタマイズ箇所が増加するとどちらの記載内容が優先されるのかが分かりにくくなったり、 CSSが肥大化する(custom.cssに記載した内容と元々のテーマが利用しているCSSの内容が重複)といった問題点が発生したため、 今回はテーマをフォークし、そのフォークしたテーマをgitmodulesにてインポートすることにしました。

フォークしたリポジトリはgithub.com/Nya-buro/hugo_theme_robustにありますので、ご参考になればどうぞ。

WordPressからの移行

WordPress→Hugoの移行のため、WordPress上にある既存のコンテンツをMarkdown形式に変換する必要があります。

まずはWordPressの管理画面のツールエクスポートより、すべてのコンテンツをxml形式でエクスポートします。

WordPressからエクスポート

WordPressからエクスポート

エクスポートしたxmlファイルを適当な場所に格納し、Node.jsが動く環境で下記を実行

npx wordpress-export-to-markdown

実行後いろいろ聞かれるので、雰囲気で入力

  • Path to WordPress export file?
  • Path to output folder?
  • Create year folders?
  • Create month folders?
  • Create a folder for each post?
  • Prefix post folders/files with date?
  • Save images attached to posts?
  • Save images scraped from post body content?
  • Include custom post types and pages?

適当に回答し、画像はサーバからダウンロードして適当に格納し、Markdown形式の画像形式だったので、テーマが内蔵している画像挿入形式に正規表現を使ったり色々こねくり回しました

画像を圧縮したりEXIF情報を抹消したりする

スマートフォンで撮影したデータには日付時刻や位置情報などのタグが入っていたりして、そのままWebサイトにアップロードするのは危険です。 CMSではそのあたりもいい感じに対応してくれたりしますが、静的サイトジェネレータではそのあたりをあまり考慮していないような雰囲気があります。 また、画像サイズもオリジナルのままだと大きくなってしまいがちなので、可能な限り圧縮して格納をしたいです。

ということで、デフォルトで定義されているshortcodesを改変し、EXIFを削除したり、画像をWebP形式にコンバートしたりしてみます。

/layouts/shortcodes/img.html

やってること

  • オリジナル画像をオリジナル画像と同じ解像度でWebP形式に圧縮
  • サムネイル画像を生成
  • loading=lazyが指定されている場合遅延読み込みさせる

などなど・・・

<figure class="figure">
  {{- $src := .Get "src" -}}
  {{- $link := .Get "link" -}}
  {{- $target := .Get "target" -}}
  {{- $rel := .Get "rel" -}}
  {{- $alt := .Get "alt" | default (.Get "caption") | markdownify | plainify -}}

  {{- $original := .Page.Resources.GetMatch $src -}}

  {{- $thumbURL := $src -}}
  {{- $fullURL := $src -}}

  {{- if $original -}}
    {{- $oriented := $original.Filter images.AutoOrient -}}

    {{- $thumbnail := $oriented.Fit "800x800 webp" -}}
    {{- $thumbURL = $thumbnail.RelPermalink -}}

    {{- $full := $oriented.Resize (printf "%dx%d webp" $oriented.Width $oriented.Height) -}}
    {{- $fullURL = $full.RelPermalink -}}
  {{- end }}
  <a href="{{ if not $link }}{{ $fullURL }}{{ else }}{{ $link }}{{ end }}"
    {{- with $target -}} target="{{ . }}"{{ end }}
    {{- with $rel -}} rel="{{ . }}"{{ end }}
    {{- if not $link -}} class="luminous" title="Original Image"{{ end -}}
  >
    <img src="{{ $thumbURL }}"
      alt="{{ $alt }}"
      {{- with .Get "width" }} width="{{ . }}"{{ end -}}
      {{- with .Get "height" }} height="{{ . }}"{{ end -}}
      {{- with .Get "loading" }} loading="{{ . }}"{{ end -}}
    >
  </a>
  {{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") }}
  <figcaption>
    {{- with (.Get "title") -}}
    <h4>{{ . }}</h4>
    {{- end -}}
    {{- if or (.Get "caption") (.Get "attr")}}
    <p>
      {{ .Get "caption" | markdownify }}
      {{- with .Get "attrlink" }}
      <a href="{{ . }}">
        {{- end -}}
        {{- .Get "attr" | markdownify -}}
        {{- if .Get "attrlink" -}}
      </a>
      {{- end }}
    </p>
    {{- end }}
  </figcaption>
  {{- end }}
</figure>

ちなみにこのままだとオリジナル画像がビルド内に含まれてしまうため、archetypesに以下を指定してあげる必要があります。

build:
  publishResources: false

これだとページ単体の指定になるので、特定ディレクトリ配下の生成をやめたい場合は親ディレクトリの_index.mdに下記を指定してあげます

cascade:
  build:
    publishResources: false # 配下ディレクトリのリソースの制御

移行してみた感想

別にWordPressでもいいじゃん?

まあでも技術的にも面白かったのでOKですし、最近のCSSの流行りとかもキャッチアップできたので勉強になったということにしておきます。

コンテンツの内容は一般的なMarkdown形式で記載されているので別のSSGに移行するのもそこまで難しくないと思いますし、 それ以上に放置してもセキュリティホールになる懸念が少ないというのがメリットですね。

あとはなにかリンクが切れてたりとかがあれば教えてください・・・

シリコンバレー一流プログラマーが教える Goプロフェッショナル大全 Amazon.co.jp