Laikaを使用したScala製ドキュメントツールのバージョニング対応
はじめに
この記事では、Scala製のドキュメントツールであるLaikaを使用して、バージョニング対応を行う方法について解説します。
今回作成した内容は以下リポジトリで公開しています。
また、今回作成したドキュメントは以下で公開しています。
Laikaとは
Laikaに関しては、以前にも記事を書いていますので詳細はこちらを参照してください。
プロジェクトの作成
まず、公式ドキュメントを参考にLaikaを使用して多言語対応のドキュメントを作成するためのプロジェクトを作成します。
sbt自体初めての方は以下の記事も参考になるかと思います。
sbtプロジェクトのproject/plugins.sbtにLaikaのsbtプラグインを追加します。
addSbtPlugin("org.typelevel" % "laika-sbt" % "1.2.0")
次に、プロジェクトのbuild.sbtでプラグインを有効にします。
enablePlugins(LaikaPlugin)
これでプロジェクトの準備が整いました。
ドキュメントの作成
Laikaを使用したドキュメントの作成方法やカスタマイズ方法に関しては、以下記事の「ドキュメントの作成」を参照してください。
バージョニング対応
Laikaはデフォルトでドキュメントをバージョン管理する機能を提供しています。
各ディレクトリと個々のドキュメントは、バージョン付きまたはバージョンなしとしてマークすることができます。バージョン管理されたドキュメントはすべて、ルートのサブディレクトリにレンダリングされます。
バージョン管理の設定
Laikaのバージョン管理は、Versionsというオブジェクトを使用して設定します。
Versionsオブジェクトは、バージョンのリストを保持し、それぞれのバージョンに対してドキュメントのルートディレクトリを指定します。
import laika.config.{ Version, Versions }
次に、Versionsオブジェクトを作成し、バージョンのリストを設定します。まずは、forCurrentVersionメソッドにより、現在のバージョンを指定します。
Versionは2つの引数を取り、それぞれバージョンの表示名とバージョンのパス(ディレクトリ)名を指定します。
val versions = Versions
.forCurrentVersion(Version("0.1.x", "0.1"))
次に、作成したVersionsオブジェクトをHeliumのテーマに設定します。
laikaTheme := Helium.defaults.site
.topNavigationBar(
homeLink = IconLink.internal(Root / "index.md", HeliumIcon.home)
)
.site
.versions(versions)
.build
これでバージョン管理の設定が完了しました。
laikaThemeの設定を行った後sbt laikaSiteを実行し、sbt laikaPreviewでプレビューを確認してください。
以下のようにナビゲーションバーにバージョンを切り替えるためのセレクトボックスが表示されているかと思います。

表示されたバージョンを選択するとVersionの引数で渡したバージョンのパスで始まる/0.1/index.htmlに遷移することができます。
しかし、現時点では0.1のディレクトリが存在しないため、404エラーが発生してしまいます。0.1のディレクトリを作成しても良いのですが、それだとバージョンが増えるたびにディレクトリを作成する必要があり管理が煩雑になってしまいます。
そこで、Laikaではlaika.versionedというメタデータを設定することで自動的にforCurrentVersionで指定したバージョンのディレクトリに作成したドキュメントを配置することができます。
さっそくdocs/directory.confにlaika.versionedを設定してみましょう。
laika.versioned = true
laika.versionedをtrueに設定することで、LaikaはVersionsで指定したバージョンのディレクトリにドキュメントを配置するようになります。
先ほどと同様にsbt laikaSiteを実行してみましょう。
targetディレクトリに0.1のディレクトリが作成され、その中にドキュメントが配置されていることが確認できるかと思います。
target
└── docs
└── site
└── 0.1
├── index.html
└── ...
sbt laikaPreviewでプレビューを確認すると、対応したバージョンのドキュメントが表示されることが確認できるかと思います。

バージョンの追加
先ほどの設定で1つのバージョンを管理することができましたが、複数のバージョンを管理する場合はどうすればよいでしょうか。
Versionsオブジェクトに複数のバージョンを追加するために、withNewerVersionsやwithOlderVersionsメソッドが用意されています。
まずは、withNewerVersionsメソッドを使用して新しいバージョンを追加してみましょう。
val versions = Versions
.forCurrentVersion(Version("0.1.x", "0.1"))
.withNewerVersions(Version("0.2.x", "0.2"))
withNewerVersionsメソッドは、引数にVersionを取り、新しいバージョンを追加します。
これで0.2のバージョンが追加されました。
先ほどと同様にsbt laikaSiteを実行し、sbt laikaPreviewでプレビューを確認してください。
ナビゲーションバーに0.2のバージョンが追加されていることが確認できるかと思います。

ただし、現時点では0.2のディレクトリが存在しないため、404エラーが発生してしまいます。
LaikaはforCurrentVersionで指定したバージョンのディレクトリにドキュメントを配置するため、0.2のディレクトリは別途作成する必要があります。
バージョンの設定を以下のように変更することで、0.2のディレクトリにドキュメントを配置することができます。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2"))
.withOlderVersions(Version("0.1.x", "0.1"))
withOlderVersionsメソッドは、引数にVersionを取り、古いバージョンを追加します。
これで0.2のバージョンのドキュメントを作成できます。
sbt laikaSiteを実行し、sbt laikaPreviewでプレビューを確認してください。
0.2のディレクトリにドキュメントが配置されていることが確認できるかと思います。

新しいバージョンを追加して、そのバージョンでドキュメントを作成することができましたが今度は0.1のバージョンのドキュメントが表示されなくなってしまいました。
これでは、バージョンを切り替えた際に古いバージョンのドキュメントを表示することができず、別のバージョンを表示したい場合はその都度ディレクトリを作成する必要があります。これでは、複数のバージョン用のディレクトリを管理するのと変わらないため、自動でバージョンのディレクトリを作成する旨みがありません。
これをどう解消するかというとGithub Pagesと組み合わせて使用することで、問題を解消することができます。
Github Pagesへのデプロイ
まずは、Github Pagesを使用してドキュメントを公開するために専用のgh-pagesブランチを空で作成します。
$ git checkout --orphan gh-pages
$ git rm -rf .
$ git commit --allow-empty -m "Create gh-pages branch"
$ git push origin gh-pages
ブランチを作成したら、Workflowで書き込みを許可するために、Settings -> Actions -> General -> Workflow permissionsをRead and write permissionsに変更します。

次に、Github Actionsを使用してLaikaで生成したドキュメントをGithub Pagesにデプロイするためのワークフローを作成します。
.github/workflowsディレクトリにdeploy.ymlを作成し、以下の内容を記述します。
deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches:
- master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
concurrency:
group: ${{ github.workflow }} @ ${{ github.ref }}
cancel-in-progress: true
jobs:
site:
name: Generate Site
strategy:
matrix:
os: [ ubuntu-latest ]
java: [ corretto@11 ]
runs-on: ${{ matrix.os }}
steps:
- name: Install sbt
uses: sbt/setup-sbt@v1
- name: Checkout current branch (full)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Java (corretto@11)
id: setup-java-corretto-11
if: matrix.java == 'corretto@11'
uses: actions/setup-java@v4
with:
distribution: corretto
java-version: 11
cache: sbt
- name: sbt update
if: matrix.java == 'corretto@11' && steps.setup-java-corretto-11.outputs.cache-hit == 'false'
run: sbt +update
- name: Generate site
run: sbt laikaSite
- name: Publish site
uses: peaceiris/actions-gh-pages@v4.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: target/docs/site
keep_files: true
このワークフローは、masterブランチにプッシュされた際にLaikaで生成したドキュメントをGithub Pagesにデプロイするものです。
ワークフローを作成したら、Githubにプッシュしてワークフローを実行するのですが、その前にbuild.sbtでバージョンの設定を以下のように変更しておきましょう。
val versions = Versions
.forCurrentVersion(Version("0.1.x", "0.1"))
変更が完了したら、Githubにプッシュしてワークフローを実行します。
ワークフローが正常に完了すると、Github Pagesにドキュメントが公開されているかと思います。
gh-pagesブランチには、Laikaで生成したドキュメントが配置されているかと思います。
gh-pages
├── 0.1
│ ├── index.html
│ └── ...
├── laika
│ └── versionInfo.json
└── .nojekyll
Github Pagesに公開されたドキュメントを確認するには、https://<username>.github.io/<repository>/0.1/にアクセスしてください。
これでGithub PagesにLaikaで生成したドキュメントをデプロイすることができました。
次に、ようやくバージョンを切り替えた際に対応したバージョンのドキュメントを表示する方法について解説します。
といっても難しいことはなく、build.sbtでバージョンの設定を以下のように変更するだけです。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2"))
.withOlderVersions(Version("0.1.x", "0.1"))
これだけ?と思われるかもしれませんが、Github Pagesにデプロイする設定を見返してみましょう。
ここで使用しているpeaceiris/actions-gh-pagesは、keep_filesをtrueに設定することでデプロイ先 (gh-pagesブランチ) にある既存のファイルを保持したまま新しいファイルをデプロイしてくれ、新しいファイルが既存のファイルと同じ名前の場合は上書きされます。
- name: Publish site
uses: peaceiris/actions-gh-pages@v4.0.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: target/docs/site
keep_files: true
つまり、先ほどの設定で0.1のディレクトリでドキュメントを配置しデプロイを行いましたが、今度はforCurrentVersionで指定した0.2のディレクトリにドキュメントを配置しデプロイを行います。
そのため、0.1のディレクトリに配置されていたドキュメントは保持されたまま、新しいバージョンのドキュメントのみがデプロイされることで、古いバージョン用のドキュメントは残り続けるため、バージョンを切り替えた際に対応したバージョンのドキュメントを表示することができるようになるということです。
実際にGithub Pagesにデプロイを行い、ドキュメントを確認してみましょう。
再度build.sbtでバージョンが以下のようになっていることを確認しましょう。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2"))
.withOlderVersions(Version("0.1.x", "0.1"))
また、ちゃんとバージョンごとに異なるドキュメントが表示されているかを確認するためにdocs/index.mdのタイトルを以下のように変更しておきましょう。
# Hello, Laika! v2
全ての変更が完了したらGithubにプッシュしてワークフローを実行します。
ワークフローが正常に完了すると、Github Pagesに新しいバージョンのドキュメントが公開されているかと思います。
バージョン 0.1

バージョン 0.2

gh-pagesブランチには、最初に作成した0.1のディレクトリと新しく作成した0.2のディレクトリが存在しているかと思います。
gh-pages
├── 0.1
│ ├── index.html
│ └── ...
├── 0.2
│ ├── index.html
│ └── ...
├── laika
│ └── versionInfo.json
└── .nojekyll
これでバージョンを切り替えた際に対応したバージョンのドキュメントを表示することができるようになりました。
おまけ
Laikaではバージョン管理に関する他にも様々な設定が可能です。
ラベルの設定
Laikaではバージョンにそれぞれラベルを設定することができます。
今回使用しているHeliumテーマでは、以下3つのラベル(デザイン)が用意されています。
-
Stable: 安定版 -
Dev: 開発版 -
Eol: サポート終了
ラベルを設定するには、VersionにwithLabelメソッドを使用します。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2").withLabel("Stable"))
.withOlderVersions(Version("0.1.x", "0.1").withLabel("EOL"))
.withNewerVersions(Version("0.3.x", "0.3").withLabel("Dev"))
このように設定することで、ナビゲーションバーにラベルが表示されるかと思います。

ドキュメントをバージョニングする際に、バージョンの状態をラベルで表示することで、ユーザーに対してバージョンの状態をわかりやすく伝えることができて便利ですね。
上記3つのラベル以外を使用したい場合は、Laikaはcssも独自に追加・カスタマイズすることができるため、自由にラベルを追加することも可能です。
Canonicalの設定
Laikaでは、VersionsにsetCanonicalメソッドを使用して、バージョンのCanonicalリンクを設定することができます。
Canonicalリンクは、検索エンジンに対して、同じコンテンツが異なるURLで提供されている場合に、どのURLが優先されるべきかを伝えるために使用されます。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2").withLabel("Stable").setCanonical)
.withOlderVersions(Version("0.1.x", "0.1").withLabel("EOL"))
.withNewerVersions(Version("0.3.x", "0.3").withLabel("Dev"))
このように設定することで、バージョンのCanonicalリンクを設定するこたができます。
複数のバージョンを管理する際に、検索エンジンに対して正しいバージョンのドキュメントを表示するように指定することができるため、SEO対策にも有効ですね。
フォールバックの設定
Laikaでは、バージョンのフォールバックを設定することができます。
フォールバックは、指定したバージョンが存在しない場合に、代替のバージョンを表示するために使用されます。
val versions = Versions
.forCurrentVersion(Version("0.2.x", "0.2").withLabel("Stable").setCanonical)
.withOlderVersions(Version("0.1.x", "0.1").withLabel("EOL"))
.withNewerVersions(Version("0.3.x", "0.3").withLabel("Dev").withFallbackLink("/index.html"))
まとめ
今回は、Scala製のドキュメントツールであるLaikaを使用して、バージョニング対応を行う方法について解説しました。
デフォルトでバージョニングがサポートされているため、比較的簡単にバージョン管理を行うことができました。
ただ、古いバージョンのドキュメントを更新したい場合はどうするのだろうか?であったり、新しいバージョン (開発版)と安定版を同時に運用する場合はどうするのだろうか?など、実際の運用においてはさらに検討が必要かもしれません。
ここは、自身のプロジェクトで引き続き検証していこうかなと思います。
Discussion