blogdownと絶対URL・相対URLの話

(この文章は、某所に書いた説明をコピペしつつ加筆したものです)

基礎知識:blogdownのサイトのビルド方法

blogdownのサイトをビルドする関数には以下の3つがあります。Hugoのテーマのテンプレートに埋め込まれている{{ .Site.BaseURL }}に相対URLが入るか絶対URLが入るか、Rmdをどこまでknitするか、といった点に違いがあります。

関数 目的 {{ .Site.BaseURL }} Rmdをknitするか
serve_site() 手元でのプレビュー /(つまり相対URL まだknitしていないものだけknitする
hugo_build() 公開用 config.tomlで設定したもの(つまり絶対URL knitしない
build_site() 公開用 config.tomlで設定したもの(つまり絶対URL すべてのRmdをknitしなおす

基本的には、serve_site()で見え方を確認して、build_site()でサイト全体を生成しなおしてから公開する、というステップが推奨されています。

{{ .Site.BaseURL }}の具体例

{{ .Site.BaseURL }}は、例えば以下のような形でテンプレートに埋め込まれています。

<a href="{{ .Site.BaseURL }}img/oyabun.jpg">

これは、server_site()だと↓になります。

<a href="/img/oyabun.jpg">

hugo_build()またはbuild_site()の場合は、config.tomlbaseurl = http://blog.hoxo-m.com/と指定してあれば、↓になります。

<a href="http://blog.hoxo-m.com/img/oyabun.jpg">

ここで、もし設定していたbaseurlに最後のスラッシュが付いてないと、

<a href="http://blog.hoxo-m.comimg/oyabun.jpg">

になってしまいます。ということで最後のスラッシュは付けましょう(もちろんテンプレートがどうなってるか次第ですけど)

serve_site()だとだめなの?

だいたいの部分は相対パスでも問題ないのでserve_site()でもいいんですが、一部絶対パスじゃないと動かないのがあります。例えば、

  • ツイートボタン
  • RSS

とかです。このへんのために絶対パスにする必要があります。

これもまあテンプレートが相対パスを前提にしていれば問題ないっちゃないんですけど。こんな感じで:

 <link>http://blog.hoxo-m.com{{ .Permalink }}</link>

ただ、ここで間違えてhugo_build()とかbuild_site()してしまうとこんな感じでバグることになります。

 <link>http://blog.hoxo-m.comhttp://blog.hoxo-m.com/page/1.html</link>

ここまでのまとめ

混ぜるな危険。

どうすればいいのか

ではどうすればいいんでしょう。これだ!という決定打はないんですけど、いくつか書いてみます。

解決策1: 気を付ける

1人でブログを書いているなら一番安上がりな解決策です。忘れそうで不安なら、「serve_site()は手元の確認用、build_site()は公開用!」という標語をトイレのドアにでも貼っておきましょう。

解決策2: テンプレートをいじってserve_site()でもbuild_site()でも同じ結果になるようにする

このissueで知ったんですが、{{ .Site.BaseURL }}に何が渡ってくるかに関わらず、強制的に相対URL・絶対URLにする関数がHugoにはあります。

それぞれ、relURLabsURLとです。

これを、相対URLにしたいところには、

{{ .Site.BaseURL | relURL }}

絶対パスにしたいところには、

{{ .Site.BaseURL | absURL }}

と書いて回る、という方法です。こうしておけば、serve_site()でもbuild_site()でも同じ結果になるはずです。

解決策3. HTMLではなくMarkdownファイルをgit管理下に入れ、HTMLへの変換はリモートのHugoにやってもらう

これは、Netlifyを使うのが前提になります。Netlifyについては、以下を読んでください。まあここでは、Hugoを使うGitHub Pages、くらいに理解しておいてもらえれば大丈夫です。

こうしておくと、手元でserve_site()しようとbuild_site()しようと、公開用のものはHugoが自動でビルドすることになるので絶対URLを強制できます。

あと、Netlifyだと独自ドメインHTTPSを使えるという利点があります。

余談

上に書いたように、公式の手順に従うとbuild_site()で全てのR Markdownファイルをknitしなおすことになります。記事を公開しようと思うたびに毎回やることになります。大変そうですよね。

実は、blogdownのレポジトリにはR Markdownファイルではなく、knit済みのMarkdownファイルを突っ込む方がいいのかもしれません。このへんまだベストプラクティスがよく分からないんですが、例えばYihuiのブログはMarkdownファイルしかありません。

まとめ

どうしたもんかなーという感じですね。よいやり方をご存知の方おしえてください。。