Snow Monkey アドベントカレンダー4日目の記事です。昨日は「WordPress 有料テーマ Snow Monkey の基本的な構造について – Composer 編」として Snow Monkey と Composer について書きました。今日はディレクトリ構成がどうなっているかを書きたいと思います。
WordPress テーマのディレクトリ構成
早速ですが、ディレクトリ構成って結構悩みませんか?例えばよくあるのは画像用のディレクトリをどう配置するのかとか。あと functions.php
に何でもかんでも書き込むと10,000行とかえらいことになるので当然分割すると思いますが、そういったファイル群をどう配置するのかとか。また、WordPress のテーマディレクトリって仕組み上散らかりやすいようになっているんですよね。例えば各ページごとのテンプレートとかも全部直下に置かないといけないので page-11.php
、page-12.php
みたいなファイルがすごい数になると同じ階層にバーっと色々な種類のファイルが混ざって把握するのが難しくなってしまいます。
どう構成するのがわかりやすいか日々悩んでいたのですが、Mimizuku、Snow Monkey と開発する中である程度自分なりの形が見えてきました。
開発中のディレクトリ構成
全部書くとかなり長くなっちゃうので一部省略していますが、おおよそ下記のような構成としています。
snow-monkey/ ├ bin/ # 便利シェルスクリプト用ディレクトリ │ ├ phpunit.sh # phpunit を実行するシェルスクリプト │ ├ server.sh # ローカルサーバーを起動するシェルスクリプト │ ├ ... ├ resources/ # 一般的なテーマのディレクトリ直下に相当するディレクトリ │ ├ app/ # functions.php を分割させたファイルを配置するディレクトリ │ ├ src/ # css、js のソースファイル(Sass、ES6) │ ├ templates/ │ ├ ... │ ├ front-page.php │ ├ functions.php │ ├ index.php │ ├ screenshot.png │ └ style.css ├ tests/ ├ .editorconfig # エディタの設定ファイル ├ .gitignore ├ README.md ├ codesniffer.ruleset.xml # CodeSniffer の設定ファイル ├ composer.json # Composer の設定ファイル ├ composer.lock ├ gulpfile.js # Gulp の設定ファイル ├ license.txt ├ package.json # npm の設定ファイル ├ phpmd.ruleset.xml # PHPMD の設定ファイル ├ phpunit.xml # phpunit の設定ファイル └ yarn.lock
これは開発時のディレクトリ構成なのですが、開発時って .composer.json
とか gulpfile.js
とかの設定ファイルがたくさん必要じゃないですか。現代では Sass 使わないとか無いので。ただ、こういう設定ファイルは基本的にプロジェクト(今回で言えばテーマ)のルートに置くので、テーマに必要な PHP ファイルとまざって余計ごちゃごちゃうになっちゃうんですよね。
なので僕はテーマに必要なファイル群を全部 resources/
というディレクトリの中にいれています。もちろん style.css
もです。実はこういう配置にしても WordPress はちゃんとテーマを認識してくれるんですよね。WordPress は style.css
があるディレクトリをテーマと認識します。 /themes/snow-monkey/style.css
なら、WordPress はテーマを snow-monkey
と認識しますが、/themes/snow-monkey/resources/style.css
と配置すれば WordPress はテーマを /snow-monkey/resources
と認識します。こうすればテーマディレクトリ直下ごちゃごちゃ問題解決できて超良いですよね!素晴らしい!
ただ、1つだけ問題があるのです。これは WordPress コアのバグといっても過言ではないと思うのですが、アップデートのときにうまくディレクトリを認識してくれず、アップデートに失敗してしまうのです。本来であればテーマのワンクリックアップデートは公式ディレクトリ掲載テーマの専売特許ですが、Snow Monkey は公式ディレクトリ掲載テーマと同じようにアップデート機能を提供しているので、これが問題になってしまうんですよね…。
なので一般的な WordPress でサイト制作な仕事であれば、アップデート機能を仕込むということはあまり無いと思いますので、こういう風に一段落としてそのまま運用もするというのはなかなか良いかもしれませんね。
リリース版のディレクトリ構成
というところで、一般的なテーマのディレクトリ直下に相当する resources/
の中の構成も解説したいと思います。ですが、前述したように /snow-monkey/resources/style.css
な構成のままだとアップデートが失敗するので、このままでリリース(配布)することはできません。そこで、Snow Monkey は GitHub へのプッシュ時に、連携させた Travis CI で一般的なテーマと同じ階層を持った、リリース版の Snow Monkey をつくるようにしています。そのリリース版のディレクトリ構成はこちら。
snow-monkey/ ├ app/ │ ├ customizer/ │ │ ├ static-front-page.php │ │ ├ title-tagline.php │ │ └ ... │ └ setup/ │ ├ assets.php │ ├ editor-style.php │ ├ nav-menus.php │ └ ... ├ assets/ │ ├ css/ │ │ ├ ... │ │ ├ object/ │ │ │ ├ component/ │ │ │ ├ _btn/_btn.php │ │ │ ├ ... │ │ ├ editor-style.css │ │ ├ editor-style.min.css │ │ ├ style.css │ │ └ style.min.css │ ├ js/ │ │ ├ app.js │ │ └ app.min.js │ └ packages/ │ ├ font-awesome/ │ ├ slick-carousel │ ├ ... ├ languages/ ├ page-templates/ │ ├ left-sidebar.php │ ├ ... ├ src/ │ ├ css/ │ └ js/ ├ template-parts/ │ ├ breadcrumbs.php │ ├ copyright.php │ ├ ... ├ templates/ │ ├ layout/ │ │ ├ footer/ │ │ ├ header/ │ │ ├ sidebar/ │ │ └ wrapper/ │ ├ view/ │ │ ├ 404.php │ │ ├ archive.php │ │ ├ content.php │ │ ├ ... │ └ widget/ ├ vendor/ │ ├ inc2734/ │ │ ├ mimizuku-core │ │ ├ wp-breadcrumbs/ │ │ ├ ... │ ├ ... ├ comments.php ├ front-page.php ├ functions.php ├ index.php ├ screenshot.png └ style.css
書き出すとめっちゃ長い…。
/app/
/app/
の中には functions.php
に書くようなコードを、機能・役割ごとに分割して配置しています。さらに、Snow Monkey はカスタマイザーが多機能なので、カスタマイザー系のコードを /app/customizer/
にまとめ、それ以外を /app/setup/
の中にまとめるようにしています。
/assets/
実際に読み込まれる CSS や JS 用のディレクトリです。ちょっと特徴的なのは、/assets/css/object/component/_btn/_btn.php
のように PHP ファイルも配置していることです。「assets なのに PHP とはどういうこと?」と思われる方もいらっしゃるかもしれません。これはカスタマイザーが出力するスタイルを定義したファイルになります。例えば Snow Monkey はカスタマイザーでメインカラーの設定ができるようになっているのですが、メインカラーは色々な箇所で利用されます。例えばリンク色とか、見出しの装飾の色とか。それらは最初は /app/setup/
の中に書いてたりしていたのですが、CSS もきちんとコンポーネント毎に整理して書いているのだから、それにあわせてカスタマイザーが出力するスタイルを定義したファイルも配置したほうがわかりやすいんじゃない?ということでこのような配置にしました。
あとは/assets/packages/
ですね。ここには本来 npm でインストールして /node_modules/
に配置されるファイルを配置しています。なんか /node_modules/
を直接参照するのがどうなのかなぁというのがあって。
/template-parts/
このディレクトリにはページネーションとかロゴとか記事一覧とかのコンポーネントを切り出して入れています。別に普通にページテンプレートに書けばよくね?という方もいらっしゃると思いますが、切り出しておくことで使いまわしもしやすくなりますし(get_template_part()
で簡単に呼び出せる)、子テーマで「この部分だけ上書きしたい」というときに上書きする対象を最小限に抑えられるというメリットもあります。もしページテンプレートに直接記述している場合は子テーマでページテンプレートをまるごと上書きするしか方法がなく、上書きの影響範囲がものすごく大きくなってしまいます。そうすると親テーマがアップデートして HTML 構造が変わったりしたときにもろに影響を受けてしまうことがあるので、なるべく細かく切り出したほうが良いと僕は考えています。
/templates/
特徴的なのはこのディレクトリですね。
/templates/layout/、/templates/view/
このディレクトリ内にはさらに「header」「footer」「sidebar」「wrapper」というディレクトリがあります。WordPress は page.php
や single.php
のようなテンプレートがそのページ全体のビューとなるような仕組みになっています。ですがそれだと、header.php
や footer.php
で共通部分を切り出しているとはいえ、どうしても重複する部分がでたり、レイアウトの切り替えをしようとすると煩雑になったりしてしまいます。そこで Snow Monkey ではpage.php
や single.php
をビューコントローラーとして使用し、レイアウトファイルとビューファイルを指定してページをレンダリングする、という方法をとっています。そして、レイアウトファイルを /templates/layout/wrapper/
、ビューファイルを /templates/view/
の中に配置するようにしています。
ヘッダーやフッターのバリエーションも本来であれば header-xxx.php
とか header-yyy.php
のような名前でテーマディレクトリ直下にざーっと配置しなければいけないのですが、Snow Monkey ではファイルが散らばらないように /templates/layout/header/
や /templates/layout/footer/
の中にバリエーションを配置して切り替えられるようにしています。
/templates/widget/
Snow Monkye では様々なオリジナルウィジェットを用意していますが、そのウィジェットのビュー(実際に画面に表示される HTML)を /templates/widget/
の中にファイルを置くことで上書きできるようにしています。
/
テーマディレクトリ直下も特徴的です。↑のほうに書いたディレクトリツリーで、ディレクトリ直下の PHP ファイルは省略せずに書いています。と考えると、存在するファイルは
├ comments.php ├ front-page.php ├ functions.php ├ index.php
だけしかありません。header.php
や footer.php
、home.php
などはどこにあるのでしょうか?通常、WordPress は「子テーマ → 親テーマ」という順にテンプレートを読み込んで、子テーマにあれば個テーマのテンプレートを、親テーマにあれば親テーマのテンプレートを利用する、という仕組みになっていますが、Snow Monkey はもう1工夫して「子テーマ → 親テーマ → mimizuku-core(composer のライブラリ)」という順にテンプレートを読むようになっているのです。これもテーマディレクトリ直下をきれいに保つための仕組みです。mimizuku-core に入っているテンプレートはすごくシンプルなものなので、もし上書きしたいという場合があれば、それだけテーマディレクトリ直下にファイルを置いて上書きすれば良い、というわけです。
最後に
Snow Monkey ではいかにテーマディレクトリ直下が散らからないようにするか、そして、機能や役割ごとにファイルを正しく分割・配置して、あの機能についてのファイルならここにあるだろうなということが直感的にわかるようにする、というところに力を入れてディレクトリ構成を設計しました。意外にあまりスタンダードが無い部分だと思うので、よろしければみなさんがどうしてるかもきかせてもらえると嬉しいです!
明日は
明日は福岡のさとうさんが参加してくれています!なんと12/12、12/20も登録してありますね。3記事!ご無理なさらずに…笑