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

crowi-plus with lsx plugin
GIF.gif

crowi-plus デモサイト

2017.05.30 追記

@inductor さんがデモサイトを作ってくれました(しかもドメイン取得まで…!)
ありがとうございます。

https://demo.crowi-plus.org/

彼が PR してくれた nginx + Let's Encrypt コンテナ入りの docker-compose Example で動作しています。

経緯

Crowi とは

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

Pukiwiki から Crowi へ

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

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

  1. 任意のページの下の階層のツリー表示を行う事ができること
  2. 現在のページを基点にページ内リンクを張れること
    • parent/child1ページ内から../child2というパス表記で、parent/child2ページ、つまり同一レベルの別ページへリンクを張れること
      • これはparent ページを移動させたときにいちいちリンクを直すのが面倒だったので

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

Crowi から crowi-plus へ

ありがたいことに Crowi は MIT ライセンスだったので、「なければ作ってしまえ」の精神で crowi-plus を作成し、同じく MIT ライセンスで公開することにした。

成果物

主な「plus」部分

プラグイン機構

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

よりセキュアに

  • jQuery を3系にアップグレード
  • 依存ライブラリをアップグレード
Crowi crowi-plus
dependencies Status
devDependencies Status
dependencies status
devDependencies Status

Docker で構築を便利に

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

  • ログインしていないユーザーにも閲覧のみ許可するオプション
  • カスタムCSS, カスタムスクリプト
  • Slack と簡単に連携できる
  • 他にもいろいろ
    • わかりにくい挙動の改善、NGram 検索、検索窓でのキーボード操作、検索結果から一括削除、Ctrl+S で保存、配下ページを含む移動/削除、簡単クリップボードコピーボタン、ページの複製、承認リクエストの取り下げ、Gravatar 対応などなど
  • Windows での閲覧時も野暮ったくないフォント選択、サイズ設定に

WESEEK, Inc. メンバーによる、要望やバグ報告への対応

開発ポリシー

2017.05.31 修正

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Contributor 募集

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

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

https://github.com/weseek/crowi-plus

冷やかし歓迎

Chat on Slack

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

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.