NHN Cloud Meetup 編集部
JBakeでAPI文書を管理する
2017.12.21
880
1.プロジェクトの背景と目的
- 背景
1. Javaは最も人気のあるプログラミング言語で、多くの企業で主力言語として選択されています。
2. 大部分のCMS(Content Management System)は、Python、JavaScript言語からなり、Java開発者が意図的に修正するのが困難です。 - 目的
API文書サイト管理に対応したJavaベースのオープンソースのフレームワークを調査し、開発します。
2.用語の説明
これからよく登場する用語を簡単に紹介します。
- Markdown
テキストベースのマークアップ言語として簡単に読み書きができ、HTMLに変換できる
簡単な構造の文法を用いて、Webで迅速にコンテンツを作成でき、より直感的に認識できる - CMS(= Content Management System)
協業環境での電子文書の作成または変更をサポートするシステム - Static Gen(= Static Site Generator)
Markdownのような形式のファイルをテンプレートなどと連携して、静的な文書(HTML)に変換する
CMSにホスティングして文書作成に利用される - JBake
Java言語ベースのStatic Gen - Bootstrap
Webページでよく使われるスタイル(各種レイアウト、ボタン、入力ウィンドウなど)が定義されたCSSフレームワーク
3. Static GenとCMSの関係
JBakeは、CMSではなく、Static Genです。
Static Genは、CMSが持つ様々な機能のうち、1つの機能を持ったToolと見做せます。
Static GenはMarkdown形式のソース文書からHTML形式の静的なサイトを作成できる機能です。
【参考】Staitc Genは様々な形態の元ソースファイルを取り扱います。
(ex. AsciiDoc, Markdown, XML, JSON, YAML, old HTML…)
CMS | Static Site Generator |
---|---|
-サイト文書を効率的に管理できるようにサポートするシステム -文書管理のため複数のtoolをホスティング -CMS別に異なるtoolを持つ ※代表的なものとして、Read the Docs |
-ソースコードからHTML形式の文書を生成するtool -CMSがホスティングするいくつかのtoolの1つ ※代表的なものとして、JBake |
[表1] CMSとStatic Site Generatorの違い
■Research&Development
※進行戦略
まず、API文書管理ができるJavaベースのCMSを見つけます。しかし実際にAPI文書管理に適用できるかは、適用してみるまで分かりません。そこで「プロトタイピング開発手法」を用いることにしました。
Step2) 開発したプロトタイプを使ってTOAST Cloud API文書サイトに適用。正しく文書が管理できない場合、再びStep1に戻る
Step3) Step2を通過したらプロトタイプ性能を補完·改善
1. CMSリサーチ
CMSにはいくつかの種類があり、それぞれが持つ機能は様々です。すべての機能を満たす必要はなく、自分たちが運営する文書サイトを効率的に管理できる機能さえ備えていればよいでしょう。
1-1.オープンソースTool選定
まずはAPI文書管理に必要な条件を最大限満たすオープンソースToolを見つけよう。そのオープンソースで満足できない事項があれば、対象部分については別途開発する必要があります。今回のリサーチの核心は、API文書管理機能を最大限に満たすCMSを検出して、開発コストを最小限に抑えることを念頭に置きました。CMS選定の最小要件は以下のとおりです。
①最小要件
- Java言語基盤
- オープンライセンス(Apache 2.0 / MIT / BSD)
- MarkdownファイルをHTMLファイルに変換する必要がある
- GitHubとの連動
- Versioning(生成する/生成された文書をrepositoryにバージョンごとに保管可能)
- bootstrap適用可能
- 生成物のディレクトリ構造と、ソースファイルのディレクトリ構造が同じであること
以下は、ライセンスの条件を満たす代表的なJavaベースToolを比較した表です。
要件 | JBake | Swagger | Hippo |
---|---|---|---|
GitHub連動 | O | △(有料) | X(GitHub連動サポートなし) |
.md(Markdown) – > .html(HTML) | O | △(JSON / YAMLサポート) | X(XMLサポート) |
バージョン管理 | X | O | △(修正履歴の管理) |
Bootstrap | O | △ | O |
Editor | X | O | O |
[表2]JavaベースのCMS比較
SwaggerとHippoは便利なエディタ機能を提供しており、現在、多くで使用されている代表的なCMSです。この2つのCMSはMarkdownファイルを扱っておらず、ディレクトリ構造を反映した成果物が生成できません。またSwaggerは静的なサイトを作成せず、REST API文書に特化しているため、Bootstrap対応に乏しいです。JBakeのみが、Markdown(.md)ファイルをサイト形態の(.html)文書ファイルに変換できる「Static Gen」でした。ここでは、CMSというよりは付属品の役割をするJBakeを選定しました。
②JBake選定理由
- Markdown – > HTML
他のオープンソースができないMarkdownファイルをHTMLファイルに変換することができる - Bootstrap対応
Bootstrapに対応しており、より多様なUIを簡単かつ効率的に表現できる - ディレクトリ構造を反映した成果物の生成
ディレクトリ構造を反映した成果物の生成機能を備えている
希望する形状の成果物(HTMLファイル)のみ作成すれば、GitHubと連動してversioningする部分は、他のオープンソースtoolを利用して、簡単に実装できると判断しました。このような理由から、JBakeをTOAST Cloud API文書管理に適用することにしました。
1-2.JBake紹介
①JBakeとは?
- Markdown、AsciiDocで作成された文書をHTML文書に生成するTool
- Java基盤
- 無償で利用できるMITライセンス
- Gradle、Maven、Sbuildのようなbuild toolに対応
- Bootstrap、FoundationのCSSフレームワーク対応
- Freemarker、Groovy、Thymeleaf、Jadeなど、様々なテンプレートに対応
②JBakeフォルダ構造
下図はJBakeのrootフォルダ形態です。
各フォルダ、ファイルの役割は次のとおりです。
- content:HTMLファイルに変換するためのテキストソース文書がある- > HTMLファイル作成時、contentフォルダと同じ構造で生成されることに注意すること
- assets:JavaScriptファイル、CSSファイルはImageファイルのようなデザイン用のリソースがある
- templates:生成されるHTMLファイルの基本スキームを定義したテンプレートファイルがある
- jbake.properties:グローバル変数とビルド設定を行うファイル
2.プロトタイプの設計と開発
2-1.Issue
①GitHub連動と文書のバージョン管理ができない
前述のようにJBakeの役割は、単にMarkdownファイルからHTMLファイルを生成することで、GitHubと連動してブランチ別にバージョンを管理するには、このような機能を持った別途Toolを利用する必要があります。
②メニューバーの作成と動作エラー
JBakeでTOAST Cloud API文書サイトのように作成するには、ナビゲーションサイドメニューバーの作成と、選択したメニューをactiveにするための措置が必要です。
2-2.Issue解決
①GitHub連動と文書のバージョン管理ができない
– >解決方法:「Jenkinsと組み合わせ」
下図はJenkinsを利用したGitHub Repositoryとの連動図です。
◎GitHubと連動した文書のバージョン管理
[各ステップの説明]
2.文書担当者が修正された文書をGitHub Repositoryにcommit
3.devバージョンの文書をrealバージョンに反映する場合、merge
4.特定バージョンの文書を削除する場合、delete
5.修正した文書を共有保存場所に反映したい場合、git remote repositoryにpush
6.Webhookからイベントを感知したjenkins serverは、repositoryにあるファイルをpull
7.buildを通じて文書サイト生成(Markdown -> HTML)
8.運営サーバーに配布
しかし、上記のプロセスで生成された成果物は、ビルドされたGitHub branchによって個別に生成されず、1つのディレクトリに上書きされます。ここでは、生成された文書のサイトもバージョン別に生成されるようにしたかったので、次のようなアイデアを出しました。
build.gradleでビルドの成果物の位置を指定することができます。
これを利用して文書バージョン別にbuild.gradleの内容を変更します。
簡単に説明すると、各ブランチにあるbuild.gradleファイルで成果物を生成するコード部分を別々に設定し、成果物がブランチ別に異なる位置に作成されるようにします。これは、github Repositoryに変更されたMarkdown文書を該当バージョンのブランチにpushするだけで、自動的にHTML文書サイトをバージョン別に管理するのと同じ効果を与えます。
◎ Githubと連動した文書のバージョン管理 + 生成されたHTML文書のバージョン管理
[build.gradleで成果物生成関連コード]
[ビルド後、バージョン別に成果物が生成された様子]
②メニューバーの作成と動作エラー
– >解決方法: 「JavaScriptを利用したメニューバーの動作」
既存の文書サイトのメニューバー機能を動作させるためにJBakeで別途作業が必要でした。
まず、実際に運用しているTOAST Cloud API文書サイトでのメニューバーの動作機能は、次のとおりです。
◎TOAST Cloud API文書サイトのメニューバーの機能
- 上段メニューバーActive機能
上段メニューバーは、現在ユーザーが表示している文書に該当する項目を濃く表示する
自分が見ているメニュー項目の位置が分かるようにする機能で「上段メニューバーActive機能」と呼ぶ - 右メニューバーActive機能
上段メニューバーactive機能と同様に、現在のメニュー位置を表示する
現在のメニューの親メニューをrootにして、下位メニューと共にリスト形式で表示する
この機能を「右メニューバーActive機能」と呼ぶ - 左メニューバーActive機能
現在のページに該当する文書のうち、ユーザーが見ている本文の位置を表示する
ページをスクロールすると、メニューバーの項目も本文の内容に合わせて、該当するメニューがactiveになる
この機能を「左メニューバーActive機能」と呼ぶ
これらのメニューバーが正しく生成されて動作するようにするには、次の事項を理解する必要があります。
◎メニューバーissueを解決するために必要な予備知識
(1) テンプレート
- テンプレートはhtmlファイル作成時、「スケルトン」の役割をするツールと見做せます。
- テンプレートは、数百、数千個のhtmlファイルを効率的に生成できるようにサポートします。
- ページで特定の位置に固定されている部分は(ex.ツールバー、メニューバー等)事前に定義したテンプレートファイルを使用します。
- JBakeは基本的にFreemarkerテンプレートをサポートします。(freemarker公式サイト(英語))
※ページテンプレート
上図はJBakeが基本提供するページテンプレートファイルの形式です。
各位置に予め定義しておいたテンプレートファイルをincludeして、組み立てブロックを合わせるようにページの骨格を定義したことが分かります。ページ別に異なる本文内容は、${content.body}変数を使って参照し、本文の位置に内容を満たします。
(2) Markdownファイル内のメタデータ
- 上記は、contentフォルダ内のMarkdownファイルの最上位の部分。ここを「メタデータ」と呼びます。
- JBakeはビルド時、最初にMarkdownファイルのメタデータを読み取ります。このメタデータは、各ページで使用できるローカル変数の定義、タイトルの定義、型定義などを行うことができます。
- 各変数の役割は次のとおりです。
-date: 該当文書の作成日、optional value
-type: 掲示用 or 一般ページを区別する情報、Mandatory value
値がpageならページ生成時にpage.ftlテンプレートが適用され、postならpost.ftlテンプレートが適用される
-status: 配布用かどうかを区別する情報、optional value。値がドラフトの場合、ビルド時に該当文書をhtml変換した成果物は生成されない
(3) メニューバーフローチャート
[メニューバーの作成と動作フローチャート]
①Markdownファイルの本文内容は、ページのbodyに位置
②右メニューバー : メニューバーからactive状態になっている項目のリストを取得して、メニューバーの作成及び動作(このプロセスは JavaScript関数を使用)
左メニューバー : 現在のページからタイトルタグを抽出してリストを作成した後、メニューバーの作成及び動作(このプロセスはJavaScriptの関数を使用)
③JavaScriptで作成したメニューバーのhtmlソースコードをページに挿入
上記のような原理と特徴をもとに、メニューバーの関連issueを次のように解決します。
◎2番目のIssue(メニューバーの作成と動作エラー)解決方法
- 方法1)上段メニューバーActive機能を有効にする
元ソース文書に該当するMarkdownファイル上段部に、現在のページの位置情報をメタデータとして記載しています。
html変換時、テンプレートファイルではメタデータを参照して、現在のページに対応するメニューを認識し、上段メニューバーから現在の位置に対応するメニューをActive状態にします。 - 方法2)右メニューバーの作成、およびActive機能を有効にする
右メニューバーは、上段メニューバーからActive状態の項目を見つけてリスト形式に変えてページに表示します。
つまり、上段メニューバーActive機能が正常に動作すれば、右メニューバーは自動的に生成され動作します。 - 方法3)左メニューバーの作成、およびActive機能を有効にする
現在、html文書でタイトルタグh1、h2、h3の値を抽出します。次に抽出したタイトルをリスト形式にしてページに表示します。
Active機能はhtmlページ作成時、タイトル別にidを付与するコードをテンプレートファイルに挿入して解決しました。付与されたidによってタイトルインデックスが可能となり、現在の本文の位置に対応する項目がactiveになります。
3.結果
Issueを解決したプロトタイプモデルをTOAST Cloud API文書に適用します。
3-1.文書サイトの作成
下図は、markdown形式で受信したTOAST Cloud API文書ファイルからHTML形式の文書サイトを作成したものです。
既存のTOAST Cloud API文書サイトのUIと同様に実装した様子を見ることができます。
3-2.Githubと連動した文書のバージョン管理
①ブランチ別のbuild.gradleの内容を修正する
betaブランチ、devブランチなど、ブランチ別にbuild.gradleでoutputのタイトルを別途設定します。(ex.’build/DEVoutput+Date’)
[alphaブランチbuild.gradleの内容】
②文書修正後、git checkoutを通じて修正文書のブランチに移動し、その後pushします。
③ビルドの成果物はbuild.gradleで定義したディレクトリに生成されます。
[生成結果]
考察
ここまでプロトタイプを使って、CMSがTOAST Cloud API文書管理システムとしての任務を遂行できることを確認しました。しかし、これはあくまで最低限の条件を確認しただけで、パフォーマンス、効率、セキュリティなどは全く考慮していません。よって選定したCMSが本来の機能を十分に実行できるように、効率性を考慮する作業が必要です。ここでは「文書管理の利便性」、「ビルド速度」の観点からJBake CMSの今後の開発の方向性について考察します。
1.パフォーマンス測定
JBake CMSのパフォーマンスを測定し、不足している部分を把握します。参考までにパフォーマンスの甲乙は、API文書のCMSでよく知られているReadTheDocsとCMSを比較することで、その程度を計ることにします。
1.ビルド速度(githubにpushした時、成果物の生成までに要する時間)
2.文書作成の容易性
3.文書管理の利便性
①ビルド速度
- ビルド条件
– Markdown言語で簡単に作成した同一文書1200枚をビルド(cf.文書1枚の容量1KB / Template、CSS、font、image適用なし)
– ビルド方式はGithub Webhookを介して行います - ビルド結果
10回ビルドして平均時間を測定
– JBake&Jenkins CMS:51.8 sec
– ReadTheDocs CMS:220 sec - 考察
単純に作成されたMarkdownファイルで測定しましたが、4倍以上の性能差が見られ、構築速度ではJBake&Jenkins CMSが優れているという結果が出ました。実際に文書サイトを作成する際は、markdownファイルをhtmlファイルに変換するときにTemplate、CSS、font、imageを適用するため、ビルド時にはさらに複雑な処理が必要となるため、より大きなパフォーマンスの違いを示すと予想されます。
②文書作成の容易性
- JBake&Jenkins
Markdownファイルにソースを作成する際、JBakeを利用するため最上段に当該文書のメタデータを記載する必要があります。
JBakeの主な機能はstatic genですが、一部の文書管理機能に対応している。したがって文書管理を行うための情報を元のソースファイルの上端部に記載する必要があります。これは、既存のMarkdown形式の文書ファイルをすべて修正することになり、これから作成される文書でもメタデータを追加しなければならないため、非常に面倒です。 - ReadTheDocs
ReadTheDocsはMarkdownファイル作成時に、別途要求する事項はありません。 - 考察
文書を作成するたびに、該当文書に適した適切なメタデータを記載する必要がある場合、利便性が損なわれます。
しかし、ここで開発したJBake&Jenkins CMSは、文書ごとに記載が必要なメタデータ変数が1つで、その変数の値が全文書で同一です。
type = page ~~~~~~
Markdownファイル最上段に上の2行だけ追加すればよいでしょう。
これを使わずメタデータを全く記載しないようにしたい場合は、JBakeのbinファイルから関連するソースコードを探してtype変数の値が常にpageになるようにすることで、解決できます。
③文書管理の利便性
- 快適比較
JBake&Jenkins | ReadTheDocs | |
---|---|---|
バージョン管理 | ブランチ別に適切なbuild.gradleファイルを作成する必要がある | ダッシュボードを使って簡単にバージョン管理できる |
文書提供 | HTML形式のサイト文書のみ提供 | HTMLだけでなく、PDF、ePub形式の文書も提供 |
環境設定 | JBakeとJenkinsの2つの機能を利用したもので、初期の環境構成作業が必要 | すべての機能に対応しており、別途環境設定は不要 |
【表2】CMS間の利便性の比較
- 考察
初期段階でJBake&Jenkinsを使用するためにJenkins環境を構成してGithubのブランチ別にソースコードを別途管理するのは、文書を管理する上で不便なことです。 しかし、それほど難しい環境構成でもなく初期に構築すればよいので、環境設定後に使用する場合は障害要因になりません。もし新しいバージョンのブランチを作成したいときは、build.gradleのソースコードに下の1行だけ別にすればよいでしょう。
文書提供がHTML形式だけなのは少し残念ですが、CMSの重要な機能は文書サイトの作成・管理であるため、他の付加的な文書提供はオプション事項と思われます。
※比較まとめ
JBake&Jenkins | ReadTheDocs | |
---|---|---|
ビルド速度 | 高速(ReadTheDocsより4倍以上) | 遅い |
文書作成の容易性 | 文書作成時、メタデータ2行を追加する必要あり | 注意事項なし |
文書管理の利便性 | 初期環境設定が必要 | 別途の環境構成は不要 |
【表3】CMS最終比較
※最終的な考察
JBakeは単独では十分な文書管理ができない不完全なCMSです。したがってJBakeに不足している機能を補完できる他のオープンソースtoolと結合しなければなりません。
ここでは、Github連動を介して文書を管理するためJenkinsと結合しました。もし他にも文書管理に必要な機能があれば、もう一度有用なtoolを探して結合する必要があるでしょう。
ReadTheDocs、Hippo、Swagger、Wordpressのように、それ自体で完全な文書管理ができるCMSは、JBakeより豊かで多様な機能を提供してくれるかもしれません。しかしすべてのものは、等価交換(trade off)があります。
付加的な機能が多くなると、その分、SWは重くなりがちで、これはパフォーマンスの低下にもつながります。あえて必要のないもののために重要な必須機能が悪影響を受けることは回避すべきでしょう。CMSが必ずしもすべての機能を持っている必要はなく、オーナが意図した条件を十分に満たす機能だけあればよいでしょう。つまりAPI文書管理をするにあたり、必要な機能をあらかじめ定義しておき、それに合うオーダーメイドのCMSを制作することが有効です。
JBakeを用いてより速い速度で目的の文書サイトを作成できるようにして、Jenkinsを用いて様々な協業ツールと連動した文書作成、配布ができるようにしました。もちろん、それぞれの機能を持ったtoolを混ぜてあるので、文書作成時や、文書管理時に感じる不便性などのイシューがあります。甘受できない問題は、既存toolのソースコードの修正や他のオープンソースtoolとの結合によって機能を追加し、要件を満たすCMSを作成すれば、より良いCMSが誕生することでしょう。