Redmine テーマのつくりかた
本記事は Redmine Advent Calendar 2018 の 17 日目です。Redmine テーマ開発について書きます。
Redmine テーマとは?
Redmine を機能拡張する方法としてプラグインとテーマが提供されている。
プラグインは Redmine の API や DB を直に参照・操作可能なので高度な用途に向く。テーマは CSS と画像、JavaScript など Web フロントエンド技術のみで開発され、外観の変更や Web ブラウザーで可能な範囲の簡単なカスタマイズを担当する。
プラグインは高度な機能拡張を可能とする反面、開発の難易度も高い。バグや Redmine 本体との互換問題が起きるとシステムそのものが動作しなくなる危険性もある。そのため上級者向きといえよう。エンド ユーザーとして利用するにしても慎重な管理を要求される。
テーマの機能は Web ブラウザーの範疇に限定されるものの、プラグインに比べて開発の難易度は低い。バグや互換性の問題が起きたとしても Redmine の外観が崩れるぐらいで済む。プラグインほど気負わず開発・利用可能なため、カジュアルに Redmine 拡張を試したい向きにもオススメ。
かくいう私も以下のテーマを開発している。
本記事では私の経験や知見を踏まえた Redmine テーマ開発手法をとりあげる。
Starter Kit
テーマ開発の説明にあたり Starter Kit を用意した。README に従ってセットアップすればテーマ開発環境を構築できる。
以降の内容は Starter Kit プロジェクトを Atom や Visual Studio Code に開いた状態でお読みいただくと理解しやすいはず。
Redmine テーマ構成ファイル
Redmine テーマを構成するファイルについて。
特別なフォルダーはルート直下の stylesheets/
が CSS 用、javascripts/
は JavaScript 用。それぞれ以下の固定ファイルを配置する。テーマとしては最低限 application.css
があればよい。その他は必要なら定義。
ファイル | 役割 |
---|---|
application.css |
Redmine の外観を定義する CSS。 |
responsive.css |
Redmine の表示された Web ブラウザー表示幅が一定量を下回った際の外観を定義する CSS。 |
theme.js |
Web ブラウザー機能の範疇で動的な処理を実行するための JavaScript。 |
画像などがあれば適宜、追加してゆく。その際の構成はテーマのフォルダー内で完結すること。Redmine 標準テーマだと画像は images/
に配置して CSS からは ../images/add.png
という感じの相対パスで参照している。
CSS
CSS を開発する方法は主に
- 標準テーマ CSS を自作テーマ CSS の先頭に
@import
して必要なスタイルを上書き - 標準テーマ CSS を自作テーマにコピーして編集
となるだろう。方法 1 は可動している Redmine の標準テーマ CSS を
@import url(../../../stylesheets/application.css);
/* 以下に必要なスタイルを上書き */
のように取り込むため、上書き部分の量や構成にもよるが壊れにくい。問題が起きたら上書き部分を削除すれば標準へ戻せる。標準テーマとの差分が少なくて @import
のパフォーマンス問題を許容できるならオススメ。
方法 2 は 1 の @import
なし版。パフォーマンスが気になるとか、標準に対して大胆に改造する場合によい。
Sass (SCSS)
CSS 開発において直に編集してもよいが AltCSS を利用すると便利だ。AltCSS は CSS を拡張したメタ言語。CSS 標準にない機能や記法を利用しながら編集して CSS に変換する。今回は最も普及しているであろう Sass の SCSS 記法を採用。ファイルの拡張子は *.scss
としておく。
Sass は様々なプログラミング言語用のパッケージを提供しているが、今回は Web フロントエンド開発でよく使われる Node.js 版を選択。Node.js で利用するライブラリーやツールは npm 形式で配布されており Sass は node-sass - npm になる。
Starter Kit の CSS/SCSS ファイル関連は以下のように構成。
.
└── src/
├── assets/
│ ├── images/
│ └── stylesheets/
│ ├── application.css
│ └── responsive.css
└── scss/
├── App.scss
├── Responsive.scss
└── default/
├── application.css
└── responsive.css
それぞれのフォルダーについて解説する。
フォルダー | 役割 |
---|---|
src/ |
開発者が編集する CSS やソース コードなどを格納。 |
src/assets/ |
開発時にテーマとして解釈されるフォルダー。後述するローカル HTML を配置したり Docker コンテナ上の Redmine からテーマ フォルダーとして参照される場所。 |
src/assets/images/ |
テーマの画像ファイル置き場。 |
src/assets/stylesheets/ |
テーマの CSS ファイル置き場。SCSS から変換されたものの出力先。 |
scss/ |
SCSS ファイル置き場。App.scss が application.css 、Responsive.scss は responsive.css に変換される。 |
scss/default/ |
Redmine 標準 CSS 置き場。これらは SCSS ファイルから参照される。 |
Sass の提供する便利機能のうち、特に便利なのが @import
によるファイル参照と結合。前述のように CSS 標準の @import
は対象を動的に参照するため、CSS ファイルとして別れていてもダウンロードを並列化できずパフォーマンスを損なう可能性がある。
Sass の @import
はコンパイル時に参照を解決するため、出力された CSS ではファイル間が @import
した順番で結合された状態となる。これを前提として Redmine 標準 CSS を取り込むとか、SCSS ファイルが肥大化してきたら別ファイルに分割して後から結合といった運用を実現。
theme.js
CSS ではカスタマイズしきれない部分、例えばページの要素を増減するなどの処理は theme.js
に実装する。Starter Kit では以下に配置されているものを編集。
.
└── src/
└── assets/
└── javascripts/
└── theme.js
最近の代表的な Web ブラウザーにおける JavaScript は非常に機能が充実している。そのため外部ライブラリーやツールを使用せずとも実用十分だが、要素の操作などを簡単に処理したければ Redmine 付属の jQuery も利用可能。
Starter Kit の theme.js
では以下のようにしている。
(function ($) {
if (!($)) {
return
}
// Cutomize
})(window.jQuery)
// Cutomize
というコメント以降に $
で jQuery の機能を呼び出しながらカスタマイズしてゆく。この処理では jQuery がグローバル定義されていることを判定。Redmine に付属しなくなったらカスタマイズはキャンセルされるようにしてある。
開発スタイル
Starter Kit の提供する機能を利用したテーマ開発スタイルについて。
セットアップ
Starter Kit のセットアップ手順。Windows のコマンド プロンプトや PowerShell、macOS であれば Terminal を使用する。以降、これらをまとめて CLI と呼ぶ。
- Node.js 最新版をインストールまたは更新
- Starter Kit を入手、Git がなくても GitHub から ZIP 形式で取得可能
- CLI 上で
cd
コマンドにより Starter Kit フォルダーへ移動 - CLI 上で
npm i
コマンドを実行
これで Starter Kit に必要な環境が揃ったはず。
タスク実行
Starter Kit は package.json
というファイルに開発で必要とされる機能をタスクとして定義。これらは CLI から npm run タスク
という形式で呼び出す。以下にタスクをまとめる。
タスク | 機能 |
---|---|
start |
SCSS ファイルの変更監視と自動 CSS コンパイル、プレビューを起動。キーボードから Ctrl + C を押すことで終了する。 |
release |
テーマのリリース用イメージを出力。 |
他にも細かなタスクはあるが、基本的にこれらだけで実用十分なはず。開発中は npm run start
で SCSS 編集しながらプレビューで確認。十分な品質となったら npm run release
でリリース用イメージを生成 (テーマを ZIP に固めたもの)、それを Web に公開する。
なお start
は特殊なタスクで run
を省略して npm start
でも実行可能。
自動 CSS コンパイルとプレビュー
start
タスクで実行される処理について。
SCSS ファイルの変更を監視しており、編集して保存すると自動的に CSS コンパイルされる。プレビューは Redmine の代表的なページを対象に HTML 化したものを Web ブラウザーに表示。CSS がコンパイルされると Web ブラウザー上のプレビューも自動更新される。
そのため SCSS ファイルを編集するエディターと Web ブラウザーのウィンドウを横へ並べると開発しやすい。エディターはお好みで。私の推奨は以下。
これらに Sass (SCSS) 関連プラグインを入れることで構文強調や CSS プロパティーの入力補完などが効くようになる。こうした機能は開発を快適にしてくれるので、ぜひ。
注意点。プレビュー用 HTML は私が Redmine から取得した時点のもの。つまり厳密には Redmine 本体のものと異なるし本体の更新に追従できていない可能性がある。大まかな外観をプレビューするにはよいが、最終的には Redmine 本体で確認したほうがよい。
Redmine 上の動作確認
テーマが Redmine 上で実際に動作することを確認したい。しかし開発中のものを本番環境で試すのはリスクが高く、検証用にサーバーを用意するのも面倒だ。
という開発者のために Starter Kit では Docker と Docker Compose により手元で気軽に Redmine 動作環境を構築できるようにしてある。手順は以下。
- Docker と Docker Compose をインストール
- CLI 上で
cd
コマンドにより Starter Kit フォルダーへ移動 - CLI 上で
docker-compose up -d
コマンドで Redmine 起動、停止はdocker-compose stop
この状態で Web ブラウザーから http://localhost:8080/ にアクセスすると Redmine が表示されるはず。ちなみに初期状態の Redmine における user/pass は admin/admin のみとなっている。admin で Sign In したら管理画面からテーマを変更してみよう。mytheme
という候補があるので選択すると開発中しているテーマが Redmine へ適用される。
Docker 上の Redmine テーマ フォルダーは Starter Kit の src/assets
と連携するように設定済み。そのため SCSS を CSS にコンパイルしたり src/assets
内の構造を変更すれば、そのまま反映される。なにかテーマを変更したら Web ブラウザーから Redmine ページを表示更新することで最新の状態を確認可能。
Docker 関連の設定は以下を参考にした。これまで Redmine 用 Docker イメージは sameersbn/redmine を使用していたのだが、本家となる redmine のほうがバージョン追従や継続性の面でよかろうと判断して移行。
もし Redmine が表示されないようなら Docker コンテナが落ちているかもしれない。コンテナの起動状況は docker ps
コマンドで確認。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d56a255d3cb3 redmine:passenger "/docker-entrypoint.…" 11 minutes ago Up 2 seconds 0.0.0.0:8080->3000/tcp redmine
c299c663ee67 mysql:5.7 "docker-entrypoint.s…" 14 minutes ago Up 3 seconds 3306/tcp, 33060/tcp mysql
こんな感じで redmine
と mysql
が両方とも存在すれば成功。ないものがあれば docker logs redmine
のようにすると対象コンテナのログが表示される。そのメッセージを参考に環境や設定を見直したり、Docker イメージのバグと予想されるなら作者に修正要望を出すなどすること。
リリース用イメージ生成
CLI 上で npm run release
を実行することでテーマのリリース用イメージが生成される。その詳細について。
- テーマ名でリリース用フォルダーを作成
src/assets
に置かれた静的な画像とtheme.js
をリリース用フォルダーにコピー- プロジェクト直下の
CHANGELOG.md
とLICENSE
ファイルをリリース用フォルダーにコピー - SCSS をリリース用フォルダーに CSS コンパイル出力
- リリース用フォルダーを ZIP 圧縮
これらの処理により Web ページなどで配布するためのイメージができあがる。テーマの名前とバージョンはプロジェクトのルートにある package.json
の当該設定を編集することで更新可能。
{
"name": "mytheme",
"version": "1.0.0"
}
上記ならテーマは mytheme
フォルダー、それを圧縮した ZIP ファイルは mytheme-1.0.0.zip
というファイル名。私はこのように生成した ZIP を GitHub の Releases ページへアップロードすることでテーマ配信している。
まとめ
この記事により一人でもテーマ開発者が増えることを願っている。質問などがあれば Twitter で声をかけてください。