最強のWiki「Crowi」のフォーク、「GROWI(旧crowi-plus)」を公開した話

GROWI デモ
===========

https://demo.growi.org/

|エディタのテーマ変更|
|---|
|![GIF.gif](https://user-images.githubusercontent.com/1638767/35506125-9fafc6ca-052b-11e8-811f-b842e34f59bb.gif)|

|同時多人数編集 by HackMD|
|---|
|![GIF.gif](https://user-images.githubusercontent.com/1638767/43729131-3f87977c-99e2-11e8-9c4c-9bf75e226fce.gif)|

|Spreadsheet ライクに GUI で表を編集|
|---|
|![GIF.gif](https://user-images.githubusercontent.com/1638767/46668760-615ba200-cc08-11e8-821a-d8b17f3fc255.gif)|

|ページツリーを自動リスト<br>(crowi-plus 時代のデモでテイストが古いけど)|
|---|
|![GIF.gif](https://qiita-image-store.s3.amazonaws.com/0/41678/b81ca2b7-4414-0059-f9b3-309411434bec.gif)|

|色とりどりのテーマ(更に増殖中)|
|---|
|![customize.png](https://qiita-image-store.s3.amazonaws.com/0/41678/cf7096c2-1079-3de8-05fa-fcb777a2154a.png)|



経緯
====

Crowi とは
----------

node.js + jQuery (一部React) 製の、オンプレにディプロイ可能な Wiki システム。Qiita でも [Crowi タグ](http://qiita.com/tags/Crowi) で検索すると20エントリーほど引っかかる。

Pukiwiki から Crowi へ
----------------------

うちの会社では創業から10年来 Pukiwiki Plus! を使っていて、サイトを簡単に量産できるようにするための [Pukiwiki Plus! Plus!](https://github.com/weseek/pukiwiki-plus-plus-i18n) なんていうリポジトリもある程使い倒していたのだが、やはり Markdown で書きたいという動機から代替システムを検討、2016年末くらいから Crowi の試用を行っていた。

が、どうにもかゆいところに手が届かない。
Pukiwiki では利用可能だった以下2点の機能が、移行にあたっては必須事項だった。

1. 任意のページの下の階層のツリー表示を行う事ができること
    * Pukiwiki では sonot's plugin の [lsx](http://ukiya.sakura.ne.jp/index.php?PukiWiki%2F1.4%2F%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB%2F%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%2F%E7%8B%AC%E8%87%AA%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9F%E3%82%82%E3%81%AE%2Flsx) に相当
    * Confluence では[ページツリーマクロ](https://ja.confluence.atlassian.com/confcloud/page-tree-macro-724765260.html)に相当
1. 現在のページを基点にページ内リンクを張れること
    * `parent/child1`ページ内から`../child2`というパス表記で、`parent/child2`ページ、つまり同一レベルの別ページへリンクを張れること
        * これは`parent` ページを移動させたときにいちいちリンクを直すのが面倒だったので

Crowi はこれらを備えていなかった。

Crowi から GROWI(旧crowi-plus) へ
------------------------

ありがたいことに Crowi は MIT ライセンスだったので、「なければ作ってしまえ」の精神で [GROWI(旧crowi-plus)](https://github.com/weseek/growi) を作成し、同じく MIT ライセンスで公開することにした。


成果物
======

- https://github.com/weseek/growi
- [Crowi からの移行ガイド](https://github.com/weseek/crowi-plus/wiki/Migration-Guide-from-Official-Crowi)
- [PukiWiki の文書を Markdown に変換するワンライナー(一部 crowi-plus 仕様)](http://qiita.com/yuki-takei/items/152e20f4421333ae8fd9)
 
機能・改善一覧
---------------

### プラグイン機構

Crowi 本体や GROWI(旧crowi-plus) 本体に頼らずユーザーが独自に機能を追加することが可能なプラグイン機構を搭載。以下はサンプルプラグイン。

* [lsx プラグイン](https://github.com/weseek/growi-plugin-lsx)
* [Pukiwiki Like Linker プラグイン](https://github.com/weseek/growi-plugin-pukiwiki-like-linker)

### よりセキュアに

* jQuery を3系にアップグレード
* 依存ライブラリをアップグレード

    | Crowi | GROWI(旧crowi-plus) |
    |---|---|
    |[![dependencies Status](https://david-dm.org/crowi/crowi/status.svg)](https://david-dm.org/crowi/crowi) <br> [![devDependencies Status](https://david-dm.org/crowi/crowi/dev-status.svg)](https://david-dm.org/crowi/crowi?type=dev)|[![dependencies status](https://david-dm.org/weseek/growi.svg)](https://david-dm.org/weseek/growi) <br> [![devDependencies Status](https://david-dm.org/weseek/growi/dev-status.svg)](https://david-dm.org/weseek/growi?type=dev)|

* **JVN や国内外脆弱性報告者と連携**したセキュリティ対策

### Docker で構築を便利に

* [Docker Ready](https://hub.docker.com/r/weseek/growi)
* [Docker Compose Ready](https://github.com/weseek/growi-docker-compose)
    * [複数サイト同時起動 Example](https://github.com/weseek/growi-docker-compose/tree/master/examples/multi-app)
    * [Let's Encrypt によるSSL運用 Example](https://github.com/weseek/growi-docker-compose/tree/master/examples/https-portal)

### アカウント管理手段を大幅強化

* **LDAP / OAuth / SAML(SSO)**対応
* **ログインしていないユーザーにも閲覧のみ許可**するオプション
* グループに対するページ管理権限設定付与**(Group ACL)**


### 便利な追加機能・ブラッシュアップ

* **同時多人数編集** by HackMD
* Excel/Spreadsheet ライクな **GUI による表の編集** および **表の自動整形**
* **esa.io, Qiita:Team** からのデータインポート
* **Vim/Emacs/Sublime Text** キーバインド
* **Slack** とのカスタム Web hook による連携
* **Markdown によるコメント**投稿
* コメントへの**ファイル添付**
* Visual Studio Code 実装コードを参考にした、プレビュー画面の**賢いスクロール同期**
* 議事録等に便利な**ページテンプレート**機能
* **IFTTT**連携
* カスタムCSS, カスタムスクリプト, カスタムタイトル, カスタムヘッダー
* カラフルでバリエーションに富んだテーマ
* エディタテーマ変更、コードハイライトテーマ変更
* [他にもいろいろ](https://github.com/weseek/crowi-plus/wiki/Additional-Features)
    * わかりにくい挙動の改善、NGram 検索、検索窓でのキーボード操作、検索結果から一括削除、Ctrl+S で保存、配下ページを含む移動/削除、簡単クリップボードコピーボタン、ページの複製、承認リクエストの取り下げ、Gravatar 対応などなど
* Windows での閲覧時も野暮ったくないフォント選択、サイズ設定に

### 初心者にも優しく

* インストールと同時にサンドボックスページを自動生成
* Markdown 書式のヘルプをエディタエリアに表示



### [WESEEK, Inc.](http://weseek.co.jp) メンバーによる、要望やバグ報告への対応

* 本家で解決されていない Issue が解決されていることもある
    * [crowi#94](https://github.com/crowi/crowi/issues/94)
    * [crowi#96](https://github.com/crowi/crowi/issues/96)
    * [crowi#97](https://github.com/crowi/crowi/issues/97)
    * [crowi#155](https://github.com/crowi/crowi/issues/155)
    * [crowi#178](https://github.com/crowi/crowi/issues/178)
    * [crowi#264](https://github.com/crowi/crowi/issues/264)
    * [crowi#265](https://github.com/crowi/crowi/issues/265)
    * [crowi#266](https://github.com/crowi/crowi/issues/266)
    * [crowi#269](https://github.com/crowi/crowi/issues/269)
* 本家で直っていないバグが直っていることもある
    * コードブロック内で `</hoge/fuga>` が悪さをするバグ
    * [growi#14](https://github.com/weseek/growi/issues/14)
    * [growi#19](https://github.com/weseek/growi/issues/19)
    * [growi#119](https://github.com/weseek/growi/issues/119)
    * [growi#129](https://github.com/weseek/growi/issues/129)
    * [growi#234](https://github.com/weseek/growi/issues/234)
    * etc...


開発ポリシー
-----------

*2017.05.31 修正*

大きくは下記3点。これらは fork を決めた理由でもある。


### 1. Crowi には搭載されない、あるいは搭載されにくい機能を積極的に実装し、かつ**ユーザーが選択的に利用できるようにする**

個人的な想いとしては、Wiki はただの業務用ツールなので、ユーザー(つまり自分たち)にとってなるべく柔軟かつ弾力的な運用ができるシステムであってほしい。その点、Crowi は良くも悪くも「Wiki とはこうあるべき」という確固たる哲学に則って開発されているようで、PR もその方向性と一致していないと通らないし、マージされるまでのチェックも厳しく、野ざらし PR が多い(もったいない…)。また、v1.6.0 から v1.6.1 のバージョンアップで急に利用できなくなった機能もあるので、ユーザー側が「Crowi流」に絶えず追従していく必要がある。

GROWI(旧crowi-plus) は Crowi が搭載する機能はそのまま継承しつつ、独自に追加した機能に関してはユーザーが利用する/しないを選べるようになっている。プラグイン機構はそのための手段の一つであり、本体の設定ページでも様々なオプションを有効化/無効化できるようになっている。また、先に述べた廃止機能に関してはそもそも選択性を持った機能だったので復活させてある。

これは今後も踏襲し続けるであろう方針で、

* 実験的な機能でもまずは実装したり取り込んでみる
    * ただし初期状態では無効化しておく
* 設定によっては Crowi と全く同様の挙動を再現できるようにする
* ユーザーが Crowi での運用に戻したくなった場合もデータを棄損することのないよう、完全な後方互換性を保つ

という姿勢で機能を増やしてしていくつもりでいる。


### 2. 変更はすぐリリースする

ユーザーとしては、待望の新機能はすぐ使いたい。BugFix が Merge されたら、なんなら次の日に修正された版をディプロイしたい(少なくとも我々はそう)。Crowi は平均2ヶ月程度のリリースサイクルなので、仮に Contribution が取り入れられても、その変更がリリースされるには1～3ヶ月程度待たないといけない状況が発生するところに歯がゆさを感じていた(もちろんそれ故に、1リリースごとに安定したバージョンが供給されるというのは大きなメリットでもある)。

GROWI(旧crowi-plus) は小さな変更もリリース対象として扱うことにしていて、これまでは立ち上がりと言うこともあって 2017/04/10 の v1.0.0 リリースから 1.5 ヶ月で大小 21 回 のバージョンアップを行った。流石にこの先同様のペースが維持されることはないとは思うが、今後もバグが一つでも修正されればリリースしようと考えている。

また、リリースと同時に Docker Hub でのイメージの公開までセットで行っており、アップグレードのしやすさも重視している。


### 3. 開発しやすいアーキテクチャを保つ

#### 3.1. 開発環境における OS への依存性を削減

これは「昨今の Web 開発者はすべからく Mac を使うべきだ」という潮流(?)から我々が逸脱しているのも問題の一端なのかもしれないが、Windows ユーザーにとって本家 Crowi は開発しにくかった。具体的には

* リポジトリ管理対象に symlink が入っていて、それが機能すること前提の作りになっている
* プログラム中でパスセパレータのバックスラッシュを考慮しない作りになっている
* npm 管理パッケージ以外に予めインストールしておくべきライブラリが存在する

などが開発を始める上ではネックになった。
GROWI(旧crowi-plus) ではそれらの問題を解決し、OSを問わず開発を始めやすくなっている。

#### 3.2. 開発者のストレス軽減

gulp タスクが核となっていたクライアントのビルドアーキテクチャと開発用サーバー起動手段には大きく手を入れた。

* クライアントビルドは gulp を廃し、npm script と webpack2 のみを用いた今風の方式に刷新
    * 環境(dev/prod)に応じた処理の変更
    * 開発時は DLL プリビルドを行う事によってソースコード変更時に走るインクリメンタルビルドの時間を軽減
* サーバーサイドソース変更をトリガとするサーバー自動再起動
* アセット変更をトリガとするブラウザのライブリロード

ことさら先進的と言うつもりもないが、これらは開発時のルーティーンのストレスを大幅に軽減してくれる。アーキテクチャ変更には初期コストがつきものだが、開発しやすさが向上すればその後の生産性に大きく影響するはずなので、今後もコスパを考えつつ改善は続けていくし、特に識者からの提案があればその施策は積極的に検討したい。


Contributor 募集
=================

このようにせっかく整備した GROWI(旧crowi-plus) なので、今のところ Contributor は WESEEK, Inc. 関係者に限られているが、この記事を読んだ ~~暇なエンジニア達~~ 英気旺盛なOSS開発者のみなさまによる Contribution が増え、GROWI(旧crowi-plus) 及び Crowi が更なる飛躍を遂げることを願ってやまない。そして Pukiwiki から GROWI に全面移行した我々の生活をもっと快適にしてください。

気軽に Issue, PR を。書いたコードは決して無駄にしない。(たぶん)

https://github.com/weseek/growi


冷やかし歓迎
-----------

[![Chat on Slack](https://growi-slackin.weseek.co.jp/badge.svg)](https://growi-slackin.weseek.co.jp/)

ドラスティックな変更を伴う変更要望がある場合も、ここで予め相談もらえると助かります。