🖨

Sphinxにひっそり存在するビルダー "dirhtml"の使い勝手を知る

2021/09/18に公開

ドキュメンテーションビルダーのSphinxは、組み込みで結構な数のビルドターゲットが存在します。
いくつか例を挙げると、このようにバラエティもかなりありますね。

  • スタンダードなHTMLを出力する、 html
  • 電子書籍スタイルの、 epub
  • Texと連動してPDFを生成できる、 latexpdf
  • ドキュメント内にあるリンク先の健全性のチェックができる、 linkcheck

そんな中で、htmlの影にひっそり存在しているビルダーに気づきました。
今回は、このdirhtmlビルダーについての、特徴・使用感などの検証や紹介をしていきます。

dirhtmlビルダーとは

Sphinx組み込みのビルダーです。
標準的なHTMLファイル群を生成するhtmlビルダーと違って、 全てのドキュメントを{ページ名}/index.htmlというファイルパスで生成する ことができます。

組み込みビルダーであるため、よく使うmake htmlからmake dirhtmlに変えるだけですぐに出力できます。

挙動の特徴

出力のファイル名ルールが変わる

例えば、以下のような構造のソースがあるとします。

- index.rst
- hello.rst
- demo1/
  - sub1.rst

html ビルダーを用いると、このようなファイル出力をします。

- index.html
- hello.html
- demo1/
  - sub1.html

一方、dirhtmlビルダーでは、このようなファイル出力をします。

- index.html
- hello/
  - index.html
- demo1/
  - sub1/
    - index.html

見ての通り、{ページ名}.rstから{ページ名}.htmlを出力するhtmlに対して、{ページ名}.rstから{ページ名}/index.htmlを出力しています。
このように、「ページ名からはディレクトリを生成して、ディレクトリ内にindex.htmlを出力する」振る舞いが、dirhtmlとなっています。

もちろんですが、「htmlビルドでのhello.html」と「dirhtmlビルドでのhello/index.html」はコンテンツとしての中身は同じです。

ページ名.rst vs ページ名/index.rst は後者が優先される?

index.rstindex.htmlへ出力されます。hello.rsthello/index.htmlへ出力されます。

dirhtmlを利用した際に、次の2ファイルがある場合、どのような挙動をするでしょうか。

  • hello.rst
  • hello/index.rst

この2ファイルは、dirhtmlでの出力先としてはどちらもhello/index.htmlになります。
手元で試す感じでは、最終的に出力内容として残るのはhello/index.rstをソースとするものでした。

おそらくですが、次の2.5点から起きていると考えています。(細かくは見ていない)

  • 出力先に何かあっても、基本的には上書き出力する
  • ページ一覧を取りまとめた後に、辞書順に出力処理をする
    • ページ一覧としては拡張子を無視するため、hello->hello/indexの順が固定になっている

ページ間リンクは、何の問題もなく機能する

Sphinxにはドキュメント間のリファレンス用の文法として:doc:が提供されています。
この文法を利用すると、例えばhello.rst内で:doc:`demo1/sub1`と書いてビルドすると、「demo1/sub1.rstから生成されたファイル」へのリンクを生成します。
これはhtmlビルドでもdirhtmlビルドでも正しく機能します。当たり前ではあるのですが。

検証を飛ばしましたが、同類の:ref:もおそらく問題なくリンクできるでしょう。

実用面で考えるdirhtmlビルド

ここからは、htmlビルドとdirhtmlビルドの生成物を、ホスティング観点で考えてみます。

静的サイトとしての機能自体は大きな差はない

2ビルダーの違いは実質的に「ページ生成におけるファイルの出力先」のみと考えて良いでしょう。

どちらにしても静的サイトとしての生成となることから、基本機能としては変わりません。
そのため、ただただ配信することだけに着目スル分には、htmlビルド・dirhtmlビルドの好きな方を使えばよいでしょう。

後方互換性の向上が見込める

前提として、多くのWebサーバーではディレクトリとなる/へのアクセスに対して、何を返すかを指定できます。
ApacheなどではDirectory Indexディレクティブで設定でき、よく設定されているものがindex.htmlとなっています。
Firebase Hostingなどのような静的サイト配信基盤でもこのあたりは変わらず、/に対してはindex.htmlを探して返します。

dirhtmlビルドも主体としてはDirectory側にあります。
そのため、上記で説明したサイト内のページ内リンクは../index.htmlといったファイル指定ではなく../というディレクトリ形式のリンクになっています。
つまり、dirhtmlビルドを行ったサイトを配信すると、index.htmlというファイル名を意識することがなくなります。

これは、「Webサイトの後方互換性」という観点を考えると、非常に有効になります。

ディレクトリ形式のURLが前提になるということは、URLがファイル名・さらには拡張子に依存しなくなることを意味します。
このため、よりよいURLでのサイト提供が出来るという初動のメリットがあると同時に、サイトジェネレーターの変更にも強くなれます。
この点を今回は「Webサイトの後方互換性が高い」と表現できるでしょう。

RTDもdirhtmlをサポートしている

Sphinxドキュメントのホスティングサービスである、Read the Docsはビルド時のビルダーが制限されています。

HTML系統に属するもののうち一部のみに対応しているのですが、幸いdirhtmlはサポート対象のビルダーに含まれています。
そのため、自作ライブラリのドキュメントをdirhtml形式で配信をすることは非常に簡単となっています。

実際に切り替えるには(実例つき)

作業コストに対してメリットがそれなりに高い物となっています。そうなると「じゃあ試してみようか」と考える人もいるでしょう。

実際に、Sphinxとablogで生成している自分の個人サイトをdirhtml化してみたのですが、その際の注意点と特定環境での実例を紹介します。

出力方式のまとめ

  • htmlビルドでhello.rst->hello.htmlだった箇所が、全てhello.rst->hello/index.htmlになる
  • 出力されるHTMLにおけるページ間遷移については、/形式へのリンクが正しく設定される
  • _static(js/cssのような静的ファイル群)フォルダに関しては変わらない

Webサーバーとして何をしておく必要があるか

もともとhtmlビルドを配信していたものをdirhtmlビルドで配信するときに気をつける点は、上記まとめのうち最初の1つのみです。

この出力に対して、次のようなリダイレクト処理を施す必要があります。

  • **/hello.htmlといったページへのリクエストは、**/hello/のように「拡張子箇所の削除と/を追加」したURLへのリダイレクトをさせる
  • ただし、**/index.htmlを直接指定したリクエストは、**/へのリダイレクトをさせる

※もし、検索エンジンなどのことを無視していいのであれば、放置でも別に平気です。

Firebase Hostingでの例

Firebase Hostingでは、リダイレクト周りの挙動をfirebase.json内に記述できます。

{
  "hosting": {
    "redirects": [
      {
        "regex": "^(.*?)(\\/index)?\\.html$",
        "destination": ":1:3/",
        "type": 302
      }
    ]
  }
}

上記は自サイトでの例ですが、このような記述で以前のページのブックマークなどに対して適切なリダイレクトを返せるようになっています。

振り返り

自サイトをdirhtml化してからしばらく経過してますが、運用上はトラブルらしいトラブルにはなっていません。

もし、「個人サイトをSphinxで管理している(したい)」「けどURLにhtmlが常時つくのは気になる」という方は、切り替えに挑戦してみてはいかがでしょう。

GitHubで編集を提案

Discussion