オープンソースのHeadless CMS「Strapi」の使い勝手を調べる

ヘッドレスCMSの一種である[Strapi](https://strapi.io/)の使用感などを調査しました。
1コンテンツにつき複数の画像を投稿・管理したかったため、その辺りに重きを置いて試しています。

参考: https://strapi.io/documentation/3.0.0-beta.x/getting-started/quick-start.html

# Strapiとは
Strapiはヘッドレス（コンテンツを表示するビューがない）CMSで、以下のような特徴があります。

- オープンソース  
GitHubにソースがあります（https://github.com/strapi/strapi ）。
- 容易にカスタマイズできる  
管理パネルとAPIを簡単にカスタマイズできます。
- JavaScript（Node.js）製
- セルフホスト
- REST APIとGraphQLの両方が使える  
任意のクライアント（React, Vue, Angularなど）やモバイルアプリ、IoTからAPIを使えます。
- 設計によって拡張可能  
プラグインがあり、認証システムやコンテンツ管理がすぐできるようになります。

CMSなので、例えばブログ記事の投稿管理やコーポレートサイト・カタログサイトの構築などに利用できます。さらに、ヘッドレスであるためアプリ開発にも向いています。

# クイックスタートを試してみる
## セットアップ
デフォルト設定でよければ、
`yarn create strapi-app <プロジェクト名> --quickstart`
のコマンド1行でサーバ立ち上げまでできました。すごい。
`create-strapi-app`のオプションは以下の通りです。

```
Usage: create-strapi-app [options] <directory>

Options:
  -V, --version              output the version number
  --no-run                   Do not start the application after it is created
  --use-npm                  Force usage of npm instead of yarn to create the project
  --debug                    Display database connection error
  --quickstart               Quickstart app creation
  --dbclient <dbclient>      Database client
  --dbhost <dbhost>          Database host
  --dbsrv <dbsrv>            Database srv
  --dbport <dbport>          Database port
  --dbname <dbname>          Database name
  --dbusername <dbusername>  Database username
  --dbpassword <dbpassword>  Database password
  --dbssl <dbssl>            Database SSL
  --dbauth <dbauth>          Authentication Database
  --dbfile <dbfile>          Database file path for sqlite
  --dbforce                  Overwrite database content if any
  -h, --help                 output usage information
```

サポートされているDBはPostgreSQL, MongoDB, SQLite, MySQLの4種類です。
クイックスタートではデータベースはSQLiteになります。
クイックスタートにしなかった場合に入力する情報は以下の通りです。

```
? Choose your default database client postgres
? Database name: hoge
? Host: 127.0.0.1
? Port: 5432
? Username: Hoge Fuga
? Password: ********
? Enable SSL connection: No
```

クイックスタートを実行するとサーバが立ち上がるので、`http://localhost:1337/admin`にアクセスします。
Adminユーザを作成してスタートしてください。

## コンテンツタイプ・フィールド作成
コンテンツタイプ: 「投稿」のようなタイプです。
フィールド: カラムのようなものです。

### コンテンツタイプ
1. プラグイン -> コンテンツタイプ作成 -> [+ Create new content-type] で新しいコンテンツタイプを作成します。
2. 基本設定のDisplay nameにコンテンツタイプの名前を入力して「続ける」をクリックします。
3. フィールドを追加したあとに保存します。

### フィールド
以下では、複数画像を投稿するフィールドを作成しています。
1. フィールドのタイプはMediaを選択します。
2. Nameにフィールド名を入力します。
3. TypeはMultiple mediaを選択します。
4. 高度な設定（Private, Required, Unique）を適宜設定します。
5. 「Finish」をクリックします。

これで、複数ファイルに対応した画像（メディア）フィールドが作成されます。

## エントリーを作成して画像をアップロード
1. CONTENT TYPES -> 先ほど作成したコンテンツタイプ を選択します。
2. [+ <コンテンツタイプ名>を追加] でエントリーを追加します。

作成画面
![スクリーンショット 2020-01-10 18.56.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124752/f70b29f2-b801-73bd-7ad2-99ab7c468646.png)

上の画像の「コミック画像」のエリアで画像を編集できます（エリアのラベルは変更することができます）。
ファイルのアップロード方法は、ドラッグ&ドロップまたはファイル選択です。複数同時にアップロードできます。

画像をアップロードすると以下のようになります。
![スクリーンショット 2020-01-10 18.59.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124752/dfbdbb28-f19b-1918-17de-bf6e28903396.png)
「別のタブを開く」をクリックすると、該当の画像を別のタブで開くことができます（その場で拡大プレビューなどはできませんでした……）。
画像を並び替える機能はなさそうでした。

画像をアップロード後、保存してエントリーを作成すると、コンテンツタイプのページにエントリーが表示されます。
エントリーのリストにサムネイルが表示されます（小さい）。
サムネイルにマウスオーバーすると少し拡大しました。
![スクリーンショット 2020-01-10 19.03.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124752/ed65e677-1185-d780-b42c-dfa954a1650b.png)

# プラグイン
Strapiにはプラグインがあります。APIの権限設定、コンテンツタイプの作成やファイルアップロードなどもプラグインで実現されているようでした。
1つのコンテンツにつき複数の画像を管理する場合、画像の並び替えや挿入、削除などができると便利だと思います。
フィールドの画像を並び替える機能は標準では実装されていなかったため、プラグインがあるか（または作成できるか）どうか調べました。

## コンセプト
https://strapi.io/documentation/3.0.0-beta.x/concepts/plugins.html より
> A plugin is like a small independent sub-application. It has its own business logic with dedicated models, controllers, services, middlewares or hooks. It can also have it's own UI integrated in the admin panel.

Strapiにおいて、プラグインとは小さな独立したサブアプリケーションのようなもので、専用モデルやコントローラ等をもった特有のビジネスロジックを持ちます。

## 既存のプラグイン
- Content Manager
- Content Type Builder
- Roles & Permissions
- Documantation
- Email
- GraphQL
- Files Upload

（他にもあるかもしれませんが、自分が確認できたのは上記でした）

GraphQLにはsortクエリが存在しますが、特定のフィールドによってエントリーを並び替える機能のようなので、そのままでは複数画像の並び替えには使えなさそうです。

エントリーの作成・編集はContent Managerで行われているため、これをカスタマイズすれば並び替え等もできるようになるかもしれないと思いました。
ドキュメントにCustomize a pluginの項が存在します: 
https://strapi.io/documentation/3.0.0-beta.x/admin-panel/customization.html#development-mode

結論: カスタマイズできれば並び替え等を実現できるかもしれません。

## プラグインを自作する
Strapiのブログに[How to create your own plugin](https://strapi.io/blog/how-to-create-your-own-plugin-part-1-4?redirectPage=1)（Part 4まである）という記事があり、プラグインの自作は可能なようでした。
GUIで画像を並び替えるには、管理パネル用のプラグインを作れば良さそうだと考えました。
＊管理パネル: コンテンツを管理する画面（フロントエンド）

> The admin panel integration is currently not available. You can still add backend features.

2020/1/29現在: 管理パネルのプラグインはまだ使えず、バックエンドのプラグインのみ使えるようでした。
https://strapi.io/documentation/3.0.0-beta.x/plugin-development/quick-start.html#plugin-development-setup

結論: 現状はGUIでの並び替え等は実現できなさそうでした。

# メモ
[10月のアップデート記事](https://strapi.io/blog/monthly-update-october-2019)にロードマップが記載されており、詳細に以下の記述があるため、2020年1〜2月頃にMediaの並び替えができるようになるかもしれない？
> Then, with the Media Library, you'll be able to sort your files and reuse them across multiple entries.

2020/1/29現在: 
Media Libraryの新機能実装はin progressである模様
https://portal.productboard.com/strapi/1-public-roadmap/tabs/6-in-progress-design
「Custom plugin」がロードマップの「Under Consideration」内にある
https://portal.productboard.com/strapi/1-public-roadmap/tabs/2-under-consideration