WordPressのテーマ開発を超効率化するためのテーマMimizukuを作りました

先日「WordCamp Tokyo 2016 で「本当に使えるテーマとはどのようなものかを考え続けた結果」というLTをやったけど全然間に合わなかったので補足記事を書きました」という記事を書きまして、その中のスライドで開発中のテーマ Mimizuku の URL を載せていましたが、ある程度形になったので記事を書くことにしました。

Mimizuku の特徴

  • 子テーマ開発用の親テーマ
  • Habakiri で得た知見をもとに開発
  • レイアウトテンプレートとビューテンプレートを簡単に差し替え
  • static ビューテンプレート
  • get_template_part()に外部変数を渡せる独自テンプレートタグ
  • CSS フレームワーク Basis
  • アイコンフォント
  • 便利 Composer スクリプトいろいろ
  • CI(継続的インテグレーション)

子テーマ開発用の親テーマ

テーマの開発手法は主に「フルスクラッチで開発」「あるテーマを親として、その子テーマとして開発」「スターターテーマをカスタマイズして開発」に分類できますが、Mimizuku は「あるテーマを親として、その子テーマとして開発」する場合の親テーマにあたるものです。

フルスクラッチは単純に一から作らないといけないのが非効率、スターターテーマはそれを直接カスタマイズする都合上簡単にはアップデートできなくなるという点が嫌で、「親テーマ」として使う形にしました。これは Habakiri から引き継いだ考えです。

Habakiri を得た知見をもとに開発

根底の思想は Habakiri と同じですが、Mimizuku は Habakiri にあった「やりすぎ感」を徹底的に無くしました。例えば「Bootstrap ではなくもっと薄い CSS フレームワークを使う」「カスタマイザーは無くす」「HTML と CSS の結合度を下げる」等です。

Habakiri はどのような案件でも使えるテーマとして開発したものですが、結果として「そのままの機能を活かして使うとめちゃ便利だけどそれ以上のカスタマイズをしようとすると思ったほど効率化できていない」テーマになってしまいました。Mimizuku はそのまま使うことは全く想定外にして、とにかくどのような案件にでも使える、そして邪魔をしない、ということを追求しました。

レイアウトテンプレートとビューテンプレートを簡単に差し替え

Mimizuku はメインテンプレート(index.php とか single.php とか)に直接 HTML を書かず、それらのファイルをビューコントローラーとして使うようにしています。例えば singular.php だとこんな感じです。

$controller = new \Mimizuku\App\Controllers\Controller();
$controller->layout( 'right-sidebar' );
$controller->render( 'content/content', get_post_type() );

レイアウトテンプレート

Mimizuku には「レイアウトテンプレート」という概念があります。WordPress の場合はそれぞれのメインテンプレートに(部分部分で切り出すにせよ)ヘッダーからフッターまでまるっとコードを書きますが、メインテンプレート間でのコードの重複度が高く、変更にあまり強くありません。そこでメインコンテンツ部分を「ビューテンプレート」それ以外の周りの部分を「レイアウトテンプレート」として分けて管理するようにしました。そうすることで1つのレイアウトテンプレートを修正するだけで全てのページのレイアウトを統一的に変更できるようになります。

また、$controller->layout()にはフィルターフックが仕込んであるので条件に応じて簡単にレイアウトテンプレートを差し替えることができます。例えば以下のような感じです。

add_filter( 'mimizuku_layout', function( $layout ) {
    // トップページの場合は /layout/wrapper/one-column.php をレイアウトテンプレートとして使う
    if ( is_front_page() ) {
        return 'one-column';
    }
    return $layout;
} );

さらに、ヘッダー、フッターの呼び出し部分にも同じようなフィルターフックが仕込んであるので、こちらも条件に応じて簡単に差し替えることができます。

add_filter( 'mimizuku_header', function( $header ) {
    // トップページの場合は /layout/header/center.php を使用
    if ( is_front_page() ) {
        return 'center';
    }
    return $header;
} );

add_filter( 'mimizuku_footer', function( $footer ) {
    // トップページの場合は /layout/footer/center.php を使用
    if ( is_front_page() ) {
        return 'center';
    }
    return $footer;
} );

ビューテンプレート

$controller->render()にもフィルターフックを仕込んでおり、そのフックを使うことで簡単にビューテンプレートを差し替えることができます(なのではじめに書いたようなコントローラーを使うコードを子テーマで書く必要はほとんど無いと思います)。例えば以下のような感じでビューを差し替えることができます。

add_filter( 'mimizuku_view', function( $view ) {
    // 投稿タイプが news なら /views/content/content-news.php をビューとして使う
    if ( 'news' === get_post_type() ) {
        return [
            'slug' => 'content/content',
            'name' => 'news',
        ];
    }
    return $view;
} );

Mimizuku は最初から投稿タイプに応じて/views/content/content-news.phpとか/views/content/content-page.phpとかを自動的に読もうとする(無い場合は/views/content/content.phpを読む)ので上記のサンプルコードはあまり実用的ではありませんが、まぁそんな感じでフックすれば任意の条件でビューを自由に差し替えられるというわけです。

static ビューテンプレート

この仕組みの一般的な名称がわからなかったのでとりあえず「static ビューテンプレート」としたのですが、Mimizuku は URL に応じて自動的にそれに一致したテンプレートを読もうとします。例えば、http://example.com/about/ という固定ページがあったとすると、/views/static/about.phpを読もうとします(無い場合は通常通り/views/content/content-page.php)。

WordPress の管理画面ではなくテンプレートに直接 HTML を書くことがあると思いますが、そういうときにpage-about.phpとか作っていくとテーマのルートにファイルがものすごく散らばってしまいますし、/about/、/product/about/ みたいに複数のページで同じスラッグだったらどうするんだ問題もありますし、そういうのを解決することができます。

ちなみに、固定ページのときだけじゃなくカスタム投稿タイプでもカテゴリーでもだいたいの場合でこの static ビューファイルは使えるようにしているので結構便利なのではと思います。

get_template_part() に外部変数を渡せる独自テンプレートタグ

get_template_part()は任意のテンプレートを呼び出す WordPress 標準のテンプレートタグですが、似たような繰り返しだけど中身は違うとかで外部から変数で渡したいなーっていうときあるじゃないですか。でも普通にはできないんですよね。なので作りました。

呼び出し側

\Mimizuku\App\Tags\get_template_part( 'path/to/template-parts', [
    '_foo' => 'bar',
    '_baz' => 'qux',
] );

呼び出される側

echo esc_html( $_foo ); // bar と表示される
echo esc_html( $_baz ); // qux と表示される

CSS フレームワーク Basis

Mimizuku では CSS フレームワークに Basis を使っています。Habakiri のときは Bootstrap でしたが、管理画面とか Web アプリではなく一般的な Web サイトの場合だと結構 Bootstrap の CSS を打ち消すことが多くて面倒で、余白のとり方とかもあんまり好きじゃなかったりしたので、邪魔をしないけど便利に使える CSS フレームワークに変えよう、でもそんなの無いので作ろうということで別途つくりました。詳しくは「FlexboxベースのレスポンシブStylus/CSSフレームワークBasisをつくったので設計思想や特徴など」をご参照ください。

で、この Basis が Stylus で書いてあるので Mimizuku の CSS も Stylus になっています。Basis は文字サイズや line-height を変数化してあるので、変数を上書きすれば簡単に基本文字サイズを変更したり line-height を大きくしたりすることができ、それに応じて余白のサイズも最適な値が勝手に設定されるようになっています。具体的なコードは Mimizuku の /src/stylus/style.stylをご参照ください。

ちなみに、Mimizuku は子テーマで Mimizuku の style.css を import もしくは enqueue して使うことを全く想定していません。これは「WordCamp Tokyo 2016 で「本当に使えるテーマとはどのようなものかを考え続けた結果」というLTをやったけど全然間に合わなかったので補足記事を書きました」のスライドでも書きましたが、CSS をそのまま使うと便利なミックスインを全て殺してしまうことになりますし、前述したような文字サイズや余白の自動化も行えなくなるためです。子テーマからは Mimizuku の/src/stylus/style.stylをインポートして使うことをおすすめします(なので子テーマの CSS は必然的に Stylus で書くことになりますが…)。そうすることで便利ミックスインも使える上、各種自動化の恩恵も受けられますし、必要なコンポーネントだけ個別に import する、ということもできるようになります。

アイコンフォント

Habakiri から引き続き Font Awesome を入れています。Habakiri には Genericons も入れていましたが、実際にはほとんど使う機会がなかったので Mimizuku からは外しました。

便利 Composer スクリプトいろいろ

Mimizuku にはいくつかの便利なシェルスクリプトが用意してあります。

ビルトインサーバーを起動して自動的にブラウザも開く

WP-CLI を使ってビルトインサーバーで WordPress を起動し、自動的にそのページをブラウザで開くシェルスクリプトです。事前にビルトインサーバーで WordPress を立ち上げれる環境を作っておく必要があります。参考:「MacBook Airの容量が限界に近づいてきたので脱VCCWを進めてビルトインサーバーでローカル環境を作るようにした話」

$ composer server

テーマユニットテストデータをインポート

テーマユニットテストって手動でやろうとすると WordPress Importer のインストールをしないといけないし、テーマユニットテストで使う xml の URL を調べないといけないしで結構面倒なんですよね。なのでそこら辺を一括でやるシェルスクリプトを作りました。インポート時に投稿と固定ページを全部削除するので注意。インポート前にデータベースの dump は自動的に行います。

$ composer theme-unit-test

日本語のテーマユニットテストをインポートしたい場合は下記。

$ composer theme-unit-test-ja

PHPUnit を実行するためのファイルを展開する

これが一番苦労しました…。WP-CLI には wp scaffold plugin-tests というプラグインに PHPUnit の実行環境とかサンプルコードを追加するためのコマンドがあるのですが、テーマのものはありません。WP-CLI のコードは全て GitHub で公開されているのでそれを参考にテーマ用のものを作ることもできますが、わざわざそんなことをするのもめんどくさい…。

ということで、wp scaffold plugin-testsしたときに展開されるファイルをテーマに同じように展開させ、テーマでユニットテストが走るように一部書き換える、というシェルスクリプトを作りました。有効化されているテーマのディレクトリに対してファイルが展開されます。

$ composer scaffold-test

ローカルに WordPress のテスト用環境を自動的に作ってそこで PHPUnit を実行する

加えて、展開されたファイルを使ってローカルに WordPress のテスト用環境を自動的に作ってそこで PHPUnit を実行するシェルスクリプトも作りました。子テーマを有効化してscaffold-test.shで子テーマに PHPUnit を実行するためのファイルを展開、下記コマンドを実行すれば子テーマにて PHPUnit が実行できます。

$ composer phpunit

CI(継続的インテグレーション)

プラグインとか CSS フレームワークとか、いろいろなプロダクトで結構テスト走らせたり自動デプロイしたりとかしてたのですが、テーマではほとんどやったことがありませんでした。とにかく開発に集中してめんどうな部分は自動化したかったので、Mimizuku では CI にも結構力をいれました。いずれも Travis CI を使い、GitHub へのプッシュ時に自動的に実行されるようにしています。

amethystvanilla はかなり参考にさせてもらいました。ありがとうございました!

CSS、JS のビルド

Mimizuku は CSS を Stylus、JS を ES2015 で書いているのでビルドツールでビルドする必要があります。Gulp タスクを用意しているので、Travis CI でnvm install 6npm installcomposer installして環境構築、そしてnpm run gulp buildしてビルドを行うようにしています。

テーマ必須ファイルの存在確認

WordPress のテーマはstyle.cssindex.phpが必須です。とりあえずこのファイルだけは無いといけないので、存在確認をするようにしています。

PHPMD による PHP の静的コード解析

PHPMD という静的コード解析ツールを使ってコードの品質をチェックしています。結構「そんなところまで?」とか「それは逆にわかりにくくなるやろ」という感じのアラートもあったので、いくつかオフにして使っています。

PHP_CodeSniffer で WordPress のコーディング規約を守れているか確認

PHP_CodeSniffer というコーディング規約を守れているかチェックするツールと WordPress のコーディング規約のルールセット WordPress Coding Standards を組み合わせて実行させています。

PHPUnit によるユニットテスト

PHPUnit をテスト用の WordPress 環境で実行するためのシェルスクリプトを Travis CI でも実行させています。

WordPress 公式テーマディレクトリ用のブランチへ自動プッシュ

Mimizuku は主に master ブランチと develop ブランチで開発していますが、これらのブランチには開発用のファイルやコード等、実際の運用時には無くても良いファイルが含まれています。WordPress の公式テーマディレクトリに掲載するときには、そのようなファイルは含めないように言われるのですが、これを手作業で削除しようとするとくそめんどくさいので、全てのテストが通った場合はそれらファイルの削除を自動的に行い wprepository というブランチにプッシュするようにしています。

GitHub Releases への自動リリース

GitHub のリポジトリには Releases という各バージョンのソースコードをダウンロードできるページがあるのですが、zip ファイルを作ってここに登録するのを毎回やるのはくそめんどくさいので Habakiri では全くやっていませんでした。でもこのリリース作業を Travis CI で自動的にやれるというのを見つけたので Mimizuku に組み込んでみました。zip にまとめるのは WordPress 公式ディレクトリに載せる場合のものと同じもので良いと思いますので、不要ファイルの削除とzip ファイルの作成を Gulp で行い、それを Travis CI 経由で GitHub にリリース、という流れになっています。

公式ディレクトリでの公開について

公式ディレクトリにも登録しようと思ったのですが、公式にあげちゃうと便利シェルスクリプトとかを全部削除しなくてはいけない、また、それならと GitHub のものを使ったとしても、WordPress の管理画面にでた更新通知から更新すると公式ディレクトリのものに置き換わってしまう、というデメリットがありちょっと公開するのをためらっています。うまい解決方法があれば良いのですがちょっと思い浮かばず…。

どうせコマンドでいろいろやるテーマだし、それなら公式に置かなくても git clone で入れてもらっても良くね?とか、packagist にも公開しているので composer で入れてもらっても良くね?みたいなのがあるので、今回は公式には載せなくても良いかなぁと考えています。ところで僕は composer に詳しくなくどうやって composer で Mimizuku をインストールすれば良いのかわかりません。誰か教えてください…。

WordPress の更新通知の仕組みはフックで変更できるので、GitHub をリポジトリとして更新通知を出すようにしようかなぁとは考えています。

で、本当に超効率的に開発できるのか

ということでいろいろ考えて設計して開発しそれを説明してきましたが、前回の記事と同様、普通のテーマとは仕組みが違うので未だ実戦投入できていません(白目
10月はわりと時間があるので、どうにでも自由がきく自分のサイトくらいは置き換えようと思っています。使ってみたよという方がいらっしゃいましたら、ぜひレビューや issue、プルリク等々お待ちしております。

MW WP Form

MW WP Form はショートコードベースのフォームプラグインです。多くの機能を持っており、例えば、多くのバリデーションルール、問い合わせデータの保存、そしてグラフ機能集計などを使用することができます。

さらに詳しく
Habakiri

Habakiri

Bootstrap ベースのシンプルな WordPress テーマ。レスポンシブ、多くのカスタマイズ機能。圧縮された CSS・JS を使用する高速化対策。Microformats 対応。Sass、クラスベースの functions.php。

さらに詳しく
basis-stylus

Basis

軽量なレスポンシブ Stylus/CSS フレームワーク。Flexbox ベースのグリッドシステム、疎結合なコンポーネント、バーティカルリズム。

さらに詳しく