はじめに
最近、急に Nintendo Switch が手に入るようになったので、子ども(6才、男の子)に買い与えました。あつまれどうぶつの森を攻略本とともに買ってみたのですが、1000ページ以上もある攻略本をどこに行くのにも持ち歩いています。 どんなに好きでも大人でもそんな重い本持ち歩く人はいないと思うんだけど、子どもってすごい。
背景
ENECHANGE では、Wordpress から Ruby on Rails で生成された静的アセットを参照している箇所がたくさんあります。
初期構築のとき、サイトデザインを統一したい、Rails が持つアセットパイプラインの仕組みを利用して SCSS で CSS を書きたいなどのニーズがあり、当時の最適解として、そのような構成になり、そのままになっていました。
しかしながら、この構成には多くの問題点があります。
- ローカルの開発環境で Wordpress の修正・動作確認をしたいだけなのにも関わらず、Rails の環境構築、サーバーの起動が必要となる
- Wordpress 側から Rails の静的アセットを参照するとき、digest (ファイル名に自動的に付加されるコンテンツ内容のハッシュ値)のない URL でアクセスする必要があり、Rails 側でそれに応答するための特別な対応が必要となる。
- 必然的に Wordpress と Ruby on Rails が同一のサーバであることが前提の設計となってしまい、分離する上での障壁となる。
- Ruby on Rails と Wordpress が密結合となり、見通しが悪くなる。
特に、digest なしでのアクセスを可能とするための仕組みが複雑で、具体的には下記のようなシェルスクリプトを毎回、デプロイ時に実行していました。
cat $(ls -1t public/assets/.sprockets-manifest-*.json | head -1 ) | jp.py assets | perl -nE ' if(/"(.+)": "(.+)"/ && $1 ne $2) { say "$1 $2" if(-f "public/assets/${2}"); say "${1}.gz ${2}.gz" if(-f "public/assets/${2}.gz"); } ' | awk '{ print "ln -f -r -s public/assets/" $2 " public/assets/" $1 }' | bash
このスクリプトを利用することで、 たとえばarticles-95eed991528cc4267a41ec89a571842f67e99f9e0020564339b776933a0889b4.js
というファイルから articles.js
にシンボリックリンクが設定されます。
上記のシェルスクリプトは本題ではないので、詳しくは解説しませんが、 manifest の JSON の内容をもとにダイジェスト付のファイル名があれば、ダイジェストがないファイル名に対してシンボリックリンクを作成します。
Rails 側で SCSS を使って生成している CSS 群をどうするか
Wordpress 内に CSS ファイルを持たせようとしている一報、SCSS を使いたいというニーズがあり、下記の 2案を検討しました。
- これまでどおり、Ruby on Rails 側で SCSS から CSS を生成する。修正があれば、都度、Wordpress 側にコピーする
- Wordpress(PHP)側に SCSS から CSS を生成する機構を新たに構築し、Wordpress で利用する CSS は移行する。
今回は、
- 比較的少ない工数でライトに素早く進めたかった
- そもそも Wordpress 側の CSS の修正頻度は非常に低く、修正のたびに手間が増えたとしても許容される頻度であった
という理由から、これまでどおり Rails 側で SCSS から CSS を生成し、それを Wordpress 側にコピーする方式を採用することとなりました。
つまり、Wordpress 側の CSS を修正するときは
- Rails 側に存在する対応する SCSS を修正する
- assets:precompile を実行して、 CSS を生成する
- 生成した CSS を wordpress のディレクトリにコピーする
という手順を実施する流れになります。
Wordpress 側の URL 書き換え
解決策として、下記の対応を実施しました。
- Wordpress のプロジェクトルート( /articles )に enechange-rails ディレクトリを作成
- Rails の階層構造をそのまま再現する形で enechange-rails 以下にファイルを配置。
(たとえば
/assets/v2/pc/articles.js
というファイルへの参照は/articles/enechange-rails/assets/v2/pc/articles.js
というファイルへの参照に置き換え) - nginx の設定を修正し、 /articles/enechange-rails へのアクセスは、CloudFront でキャッシュするなど、静的ファイルであることを前提とした設定とする
- Wordpress のテーマなどで使われている Rails 側の静的アセットへのリンクは、機械的に 先頭に
/articles/enechange-rails/
を付ける。 - モレがないように grep 等で確認する
具体的な nginx 設定として、下記のような記述をしました。
location /articles/enechange-rails/ { expires 1d; gzip_static on; add_header Cache-Control public; }
終わりに
上記の変更により、Wordpress の機能追加、修正等の開発を Wordpress だけに閉じて実施できるようになりました。
この作業を事前にすることで、その後に予定している Ruby on Rails と Wordpress のサーバ分離をより円滑に実施できる準備が整いました。