Docusaurusで既存OSSドキュメントページを作り変えてみた

**2020/04/15更新: Docusaurusによるドキュメントページのリニューアルを実施しました。それに伴い新旧ページのリンクを更新しました。**

## はじめに

私はOSSプロジェクトのPersoniumのコミュニティ活動に2019年5月頃から本格的に加わりました。今回そのPersoniumのドキュメントページをDocusaurusという静的サイトジェネレーターのOSSを使って作り変えてみたので、それについて書いてみます。

結論から言うと本番環境反映はブログ機能のみ行えました。ドキュメントページ全体の反映までには至りませんでしたが、開発中のものは見れるようにできました。

## Personium

![スクリーンショット 2019-12-18 03.01.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/7239cc0b-c7d8-3496-1c05-869446bd464e.png)


[Personium](https://personium.io/)はPDS(Personal Data Store)のオープンソースで、個人中心にデータを格納し、個人に還元できるデータ流通・利活用を目指すものです。

ここでは詳しく説明しませんが、11/23-24のOpen Source Conference発表資料で説明しているのでよかったらそちらもご参照ください。

[OSC2019 Tokyo/Fall発表資料: パーソナルデータのあり方を変える！オープンソース分散型PDS「Personium」を使ってみよう！](https://www.slideshare.net/yasufumitochiori/pdspersonium-196961652)

また、過去の富士通アドベントカレンダーでも @hd__py がPersoniumプロジェクトについて記事を書いていますのでそちらもどうぞ。

[SIerのSEが開発・運営するOSSプロジェクト：Personium](https://qiita.com/hd__py/items/3b44acb012d26c5a9102)

## Personiumのドキュメント

今回作り変えようとしているのはこの[Personiumのドキュメントページ](https://personium.io/legacy-docs/ja/index.html)です。~~2019/12/18現在、本番環境のWebサーバに反映していないので従来のページが見られるはずです。~~

![スクリーンショット 2019-12-16 22.57.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/4a507690-49d6-bacb-a82d-3cee912fe329.png)

このページはMarkdownで書かれていて、pandocを使ってhtmlに変換するようなことを行なっているようです。enとjaの2言語それぞれのMarkdownがあり、[GitHub](https://github.com/personium/docs)に格納されています。

## 旧ドキュメントページの課題

旧ドキュメントページには次のような課題があると考えていました。

1. トピック別のナビゲーションや検索窓がなく、目的のドキュメントを簡単に探し出せない
2. Getting Startedやチュートリアルのような入門ドキュメントがなく、初学者がとっつきづらい
3. モバイル対応していない
4. デザインがちょっとイケてない (これでも大分マシになったそうですが。)

特に1. 2. が重要と思っています。

2.は新たにコンテンツを作る必要があるとして、1. 3. 4.を既存のコンテンツを活かしつつなんとかできないかと考えていた時にたまたま知ったのがDocusaurusでした。

過去のPersoniumのSlackでのつぶやき

![スクリーンショット 2019-12-17 21.36.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/87656cb6-9c22-b795-901b-96c288d943fe.png)

## Docusaurus

![スクリーンショット 2019-12-17 00.01.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/ac1dfd00-d1b8-be6c-fbfc-bc974cfa75f5.png)

[Docusaurus](https://docusaurus.io/en/)はFacebook製の静的サイトジェネレーターのOSSで、特にOSSドキュメントページを簡単にメンテナンスできることを売りにしています。特徴としては以下が挙げられます。

- Markdownでのドキュメント作成
- Reactを使ったカスタムページ作成
- 翻訳プラットフォームの[Crowdin](https://crowdin.com/)を使った多言語対応
- ドキュメントのバージョニング
- [Algolia DocSearch](https://community.algolia.com/docsearch/)を使ったドキュメント検索
- Markdownでのブログ投稿

Docusaurusを使っているOSSとしては[Babel](https://babeljs.io/)、[React Native](https://facebook.github.io/react-native/)、[Redux](https://redux.js.org/)、[Prettier](https://prettier.io/)などFacebook製やJS界隈で著名なOSSが多いようです。自分も知らずに見ていたドキュメントページもありました。Docusaurusのページ自体もDocusaurusで作られています。

DocusaurusはOSSでの使用を想定していますが、OSSではないプロダクトやサービスのページにも使えると思います。ただし、CrowdinとAlgolia DocSearchはOSSでないと無料プランは使えないようです。

## Docusaurusを使用する理由

理由としては以下が挙げられます。

1. 既存のMarkdownを使って、既存課題のナビゲーション、ドキュメント検索、モバイル対応、今風のデザインを対応できる(CSSをいじらなくても)
2. 既存ページが持っている多言語やバージョニングに対応している
3. Docusaurusで作ったページは自分も使っていて読みやすい
4. GitHubスター数も14.5kと人気ありそう(実績がありそう)
5. OSSサイト/ドキュメントに特化したものは他になさそうだった
6. **使ってみたいという気持ちにさせられた**

既存のドキュメントがMarkdownで書かれていなかったり、一般的なOSSドキュメントの形式になっていなさすぎていたら今回の導入は考えなかったと思います。

他の静的サイトジェネレーターも考えてもよかったのですが、これら理由が揃ってたのでひとまず考えなかったです。

なお、6はとても重要です。

## Docusaurus導入の懸念点

導入するにあたって、以下の懸念点がありました。

1. 既に持ちあわせているja/enのMarkdownをそのまま使えるか
2. Docusaurusの多言語機能に対応できるか

上記の懸念はあるものの実際やってみてどうするか考えようと思いました。

## 作り直しでやってみたこと

[Getting Started](https://docusaurus.io/docs/en/installation)に書いてあることをやっていきました。詳しくはそちらをご参照ください。

後から気づいたのですが、この手順で入るDocusaurusのバージョンは1.x系で、[2系](https://v2.docusaurus.io/)もalpha版が出ています。

### example websiteの構築

まず最初にWebサイト・ドキュメントの雛形を作成しました。Node 8.2+であればnpxコマンドで一発で作れます。

```console
$ npx docusaurus-init
```

開発用のWebサーバをローカルで立ち上げられて編集したもののHTMLをブラウザで確認できます。

```console
$ cd website
$ yarn start
yarn run v1.3.2
warning package.json: No license field
$ docusaurus-start
LiveReload server started on port 35729
Docusaurus server started on port 3000
```

![スクリーンショット 2019-12-17 22.19.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/4e4ce2e5-35e0-4795-08ee-bef6366d87cb.png)

PrimaryColorは作るたびに変わります。

ちなみに本番環境のWebサーバに乗せるときは以下コマンドでビルドを行い、生成されるHTMLをWEBサーバに移します。

```console
$ yarn build
```

### siteConfig.jsの編集

Webサイトの設定はsiteConfig.jsで行いました。このファイルをPersoniumに合わせて変更していくことで全体の色、ヘッダー内のアイコン、ラベル名、リンク、使用アイコン、コピーライトなどがかわります。

[siteConfig.js(GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/siteConfig.js)

変更後のヘッダー
![スクリーンショット 2019-12-17 23.19.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/43d66329-b593-fe76-5170-b08d41341643.png)

### フッターの編集

フッター内容を変更しました。フッターを編集するにはsiteConfig.jsに加え、`website/core/Footer.js`を編集します。このファイルはReact.ComponentなのでReactの書き方をします。

[Footer.js(GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/core/Footer.js)

変更後のフッター

![スクリーンショット 2019-12-17 23.54.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/246bdbcb-3766-13a7-a4cb-a824c619f000.png)

### ブログページの作成

Newsという名のブログページを作成しました。

というのも、コミュニティに「せっかくイベント出展などの活動を行なっているのだから、その1つ1つをWebサイトに載せたらいいんじゃない？」という声が寄せられたからです。

Docusaurusのブログ機能を使うとそれが実現できるのではないかと考えて設定しました。ただBlogのような長い文章を書くというより、速報性のあるものを小さく出していく形にしたかったので名前をNewsにしました。

blog機能を設定して表示名をNewsにするには以下のような設定します。

```diff:siteConfig.js
  headerLinks: [
    {href: '/ja/README', label: 'Documentation'},
    {href: '/ja/apiref/000_Rest_API_Reference', label: 'API Reference'},
+    {blog: true, label: 'News'},
    // {page: 'help', label: 'Help'},
  ],
```

作成したNewsページ
https://personium.github.io/blog/

![スクリーンショット 2019-12-18 00.16.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/3baf94a5-3e2a-4b68-eb51-56a968d2a8ab.png)

1つ1つの投稿記事はMarkdownで書いて追加するだけです。(とても便利！)

[blog(GitHub)](https://github.com/personium/new-docs/tree/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/blog)

ドキュメントによればこのブログ機能は単体でも使えるとのことです。ブログをMarkdown+GitHubなどでやっていきたいという方にもDocusaurusをおすすめできるかもしれません。

なお、blog機能は多言語対応はしてないようです。

あとblogを無理やりNewsという表示名にしたものところどころblogと書かれるところがありました。HTMLのタイトルとOGPのデータはビルド後の処理を無理やり差し込むことで対処しました。(あまりよろしくないやり方です)

[package.json (GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/package.json#L6)
[post_build.sh (GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/post_build.sh)

URLのパスはどうしても変えられず、/blogのままとなりました。

### 既存Webサイトの配置

Docusaurusではhtmlなどの静的ファイルはstaticディレクトリに入れることで表示できます。Personiumは既にWebサイトのトップページとなるhtmlがあったのでそれを格納しました。

[static(GitHub)](https://github.com/personium/new-docs/tree/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/static)

Newsページを早く公開したかったので、ここまでできた時点で一旦本番環境のWebサーバにはNewsページと合わせて反映させました。

### GitHub Pagesの設定

移行までの確認用としてGitHub Pagesにデプロイするようにしました。あわよくば今使っているドメインを移行して今後GitHub Pagesでの本運用を考えています。

設定はsiteConfig.jsで行います。

```js:siteConfig.js
|   url: 'https://personium.github.io', // Your website URL |
|:--|
|   baseUrl: '/', // Base URL for your project */ |
|   // For github.io type URLs, you would set the url and baseUrl like: |
|   //   url: 'https://facebook.github.io', |
|   //   baseUrl: '/test-site/', |
|  |
|   // Used for publishing and more |
|   projectName: 'personium.github.io', |
|   organizationName: 'personium', |
```

この設定が悩ましかったです。ここでの設定がソースリポジトリとGitHub Pagesのリポジトリを別にするのか一致させる必要があるのかぱっと見わからなかったです。また、organization/userページのときとprojectページのときでどう設定するかが混同しました。

少なくともprojectNameとorganizationNameはデプロイ先のGitHub Pagesのリポジトリで、分けることも分けないようにすることもできるようです。

今はMarkdownのあるソースのリポジトリは別にしてorganizationのページの方にhtmlを置くようにしています。

ソースリポジトリ: https://github.com/personium/new-docs/
GitHub Pages: https://github.com/personium/personium.github.io/

デプロイするときは以下コマンドで行えます。

```console
$ GIT_USER=<GIT_USER> \
  CURRENT_BRANCH=master \
  USE_SSH=true \
  yarn run publish-gh-pages # or `npm run publish-gh-pages`
```

### CIの設定

ソースが更新されると自動的にデプロイするCIの設定を加えました。GitHub Actionがリリースされたばかりだったのでそれを使おうかとも思ったのですが、Docusaurusのドキュメントに書いてあるCI設定のやり方ではCircleCIの方が楽だったのでそれを設定しました。

[config.yml(GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/.circleci/config.yml)

ここでハマりどころなのは先ほどのローカルコマンドでのデプロイとCircleCIでの挙動が違うというところです。

Docusaurusのドキュメントに少し書いていますが、ソースを見るとその挙動がよくわかりました。

https://github.com/facebook/docusaurus/blob/33622c5347db641931ed98ab4846404744d1f49a/packages/docusaurus-1.x/lib/publish-gh-pages.js#L24-L31

環境変数(ORGANIZATION_NAME, PROJECT_NAME) > CircleCIの環境変数 > siteConfig.js

という優先度であったため、CircleCIの環境変数が優先され、想定と違う挙動を取ったようです。環境変数(ORGANIZATION_NAME, PROJECT_NAME)が最優先なので`.circleci/config.yml`の設定でそれを与えて想定通り動くようにしました。

[config.yml#L23(GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/.circleci/config.yml#L23)

### 多言語対応

既存のja/enの2種類のMarkdownファイルをどうDocusaurusに対応させるかを色々といじりながら考えました。結論から言うと以下のどちらかで結論はペンディングです。

1. Docusaurusの機能を使ってCrowdin上で翻訳したものを使う
2. ja/enのファイルをそのまま置き、切り替えられる機構を別に用意する

Docusaurus1.x系としては1のみを想定しているのでそれが良さそうでしたが、[CrowdinのOpen Source向けのリクエストフォーム](https://crowdin.com/page/open-source-project-setup-request)を見ると以下のような記述が少し引っかかりました。

> You do not have any commercial products related to the open-source project you are requesting a license for.

~~ここが問題ないかを確認中です。~~ 2019-12-18追記: Crowdinへ確認するメールを送っていたのですが、approved!のメール返信がありました。`approved license from an open-source initiative`でパブリックに公開していれば基本OKなのかもしれません。ということで今後Crowdinを使って検討するかもしれません。

2の方法を取るとなると、旧ページのようにヘッダーのプルダウンでen/jaを切り替える形式を取りたいですが、Docusaurusではヘッダーのカスタマイズが難しく、Docusaurus本体に手を入れなくてはできなさそうです。

今回使用したのはDocusaurus v1.x系ですが、v2.x系では多言語は未実装のようです。[ブログ](https://docusaurus.io/blog/2018/09/11/Towards-Docusaurus-2)を読むとCrowdinを使わない選択肢も取れるようにしたいと書いていました。

### 旧ページのMarkdownの移行

旧ページのMarkdownファイルをsrcディレクトリ(デフォルト値はdocsディレクトリ)に移しました。各Markdownファイルの内容は基本的には変更する必要がありませんが、Docusaurus用に以下のようなヘッダーをファイルの先頭に加える必要がありました。

```markdown
---
id: README
title: Personium ドキュメント
sidebar_label: Personium ドキュメント
---
```

数が少ないなら手作業でやってもいいですが、既存のMarkdownファイルがen/jaで合計580ファイルありました。これは手作業でやりたくないと思い、そうだ「退屈なことはPythonにやらせよう」[(元ネタ)](https://www.amazon.co.jp/%E9%80%80%E5%B1%88%E3%81%AA%E3%81%93%E3%81%A8%E3%81%AFPython%E3%81%AB%E3%82%84%E3%82%89%E3%81%9B%E3%82%88%E3%81%86-%E2%80%95%E3%83%8E%E3%83%B3%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%AB%E3%82%82%E3%81%A7%E3%81%8D%E3%82%8B%E8%87%AA%E5%8B%95%E5%8C%96%E5%87%A6%E7%90%86%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Al-Sweigart/dp/487311778X)とスクリプトを書いて大方対処しました。

[ソース(GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/src/add_header.py)

### サイドバーの設定

画面左側のサイドバーの設定をしました。これを行うためには`website/sidebars.json`の編集が必要です。これの設定も大変だったのでファイルパスをうまく使ってスクリプトで生成しました。

[create_base_sidebars_json.py (GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/src/create_base_sidebars_json.py)
[sidebars.json (GitHub)](https://github.com/personium/new-docs/blob/df13b2d562d3abc81c05df8653355323dfc5c8fb/website/sidebars.json)

サイドバー付きのドキュメントページ

![スクリーンショット 2019-12-18 02.52.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103339/a2bddd30-2e28-3ade-459e-1d46c586e060.png)

他ページへ行き来するときは左のサイドバーから行い、ページ内を往き来するときは右のサイドバーから行えます。作られたページはモバイル対応も行えています。

## 作成した新ドキュメント

~~最後まで完成しておりませんが、作成した最新版のドキュメントページはGitHub Pagesで公開しています。今なら比較して見ることができます。~~ 2020/04/15 Docusaurus版に入れ替えました。新旧ページは以下で比較して見られます。

- 旧ページ: https://personium.io/legacy-docs/ja/index.html
- 新ページ: https://personium.io/docs/ja/

~~完成した暁には完全移行を行います。~~

## Docusaurus導入でわかったこと

- Frameworkの枠組みで動かす分にはとても簡単！(既存資産なければ更に)
- /blogのパスを変える、navHeaderをカスタマイズするなど、独自カスタマイズしようとすると難易度が上がる(Frameworkはそうなる場合が多いですね)
- Docusaurusを通して多言語対応・検索機能を使うとよくも悪くもCrowdinとAlgolia DocSearchといった外部サービスに依存する

## 今回できなかったこと/今後やりたいこと

- [ ] APIリファレンス部分のサイドバー設定
- [ ] 多言語対応
- [ ] バージョニング
- [ ] 検索窓の配置
- [ ] ドキュメントの整理・不足分の作成
- [ ] 本番環境への反映
- [ ] DocusaurusのUsersに追加してもらうPull Request

こう並べるとまだまだたくさんありますが、多言語のところがなんとかなれば他作業すれば良いだけでなんとかなりそうです。

Docusaurus自体にもコントリビュートしていきたいです。

## さいごに

Personiumではいっしょに活動する人を常に募集しています。ワンタイムでのissue報告、コード修正、フィードバックも歓迎です。もしよかったらSlackやGitHubにそれらをお願いします。

また、Personiumの活動をいいね！と思ったり、興味を持った方、ぜひGitHubでのスターをお願いします。

[コアコンポーネントのpersonium-coreのGitHubリポジトリ](https://github.com/personium/personium-core)