パフォーマンス・チューニング
Drupalのキャッシュ、構築時に見直したい設定
WordPressのようにオープンソースでありながら、カスタマイズ機能に特化したCMS「Drupal」のキャッシュについて解説します。
はじめに
LYZONエンジニアの齊藤です。
Drupal はキャッシュの仕組みが充実した CMS で、インストールしただけでもある程度速く表示されます。一方で、「デフォルトのまま」では活かしきれていない設定や、開発中に「修正したのに反映されない」と戸惑う原因になる設定もあります。
この記事では、Drupal にどんなキャッシュがあるのか、デフォルトではどう設定されているのか、構築時にどう見直すとよいのかを順番に紹介します。
※ 記事内の設定値は Drupal バージョン 11.4、標準インストールプロファイル(standard)で確認したものです。
Drupal にはどんなキャッシュがあるか
Drupalで使われる主なキャッシュは次のとおりです。
| キャッシュ | ひとことで言うと |
|---|---|
| Internal Page Cache | 匿名ユーザー(未ログイン)向けに、ページ丸ごとを保存して返す |
| Dynamic Page Cache | ログインユーザーも対象。人によって変わらない部分を保存する |
| BigPipe | 人によって変わる部分(ユーザー名など)だけを後から送り、体感速度を上げる |
| Render Cache | ブロックや記事など、ページを構成する部品の単位で保存する |
| Views のキャッシュ | 一覧ページの検索結果や表示内容を保存する |
| CSS/JS の集約 | 複数の CSS/JS ファイルを1つにまとめ、読み込み回数を減らす |
| Twig のキャッシュ | テンプレートを PHP に変換して保存し、毎回の変換を省く |
| ブラウザ/CDN のキャッシュ | Drupal の外側でページや画像を保存する |
リクエストは外側から順番にキャッシュを確認し、見つかった時点で結果を返します。外側でヒットするほど速く、サーバーの負荷も軽くなります。
キャッシュが古くならない仕組み
「キャッシュすると、更新しても古いページが出るのでは?」と心配になるかもしれません。Drupal はキャッシュタグという仕組みで、この問題に対処しています。
たとえば記事ページのキャッシュには「この記事(node:1)を使っている」という目印が付きます。記事を更新すると、その目印が付いたキャッシュだけが自動的に消えます。サイト全体のキャッシュを消さなくても、必要な部分だけが新しくなるわけです。
デフォルトではどうなっているか
標準インストールプロファイルでインストールした直後の状態は次のとおりです。
| 項目 | デフォルト | 設定場所 |
|---|---|---|
| Internal Page Cache/Dynamic Page Cache/BigPipe | 有効 | 拡張機能 |
| ブラウザおよびプロキシのキャッシュの最大有効期間 | キャッシュなし | 環境設定 > 開発 > パフォーマンス |
| CSS/JS ファイルの集約 | 有効 | 環境設定 > 開発 > パフォーマンス |
| キャッシュの保存先 | データベース | settings.php |
| Views のキャッシュ | タグベース(ウィザードで作成した場合) | 各ビューの「詳細」設定 |
| 静的ファイル(画像・CSS など)のブラウザキャッシュ | 1年(Apache の .htaccess) | Web サーバー設定 |
構築時にこうしたほうがいい
1. ページキャッシュの3モジュールは有効のままにする
表示が更新されないとき、Internal Page Cache などのモジュールをアンインストールしたくなるかもしれません。しかし多くの場合、原因は別のところにあり、モジュールを外すとサイトが遅くなるだけです。
会員サイトのようにログインユーザーが中心のサイトでも、Dynamic Page Cache と BigPipe はきちんと効きます。基本的には有効のままにしておきましょう。
2. 「ブラウザおよびプロキシのキャッシュの最大有効期間」を設定する
デフォルトの「キャッシュなし」では、ページを CDN やブラウザにキャッシュさせません。リクエストは毎回 Drupal まで届きます(Drupal 内部のページキャッシュは効きます)。
CDN や Varnish を使う構成なら、15分〜1時間程度に設定するのがおすすめです。値を大きくするほど速くなりますが、更新が反映されるまでの時間も長くなります。ニュースのように更新が多いサイトは短めに、コーポレートサイトなら長めに、というように更新頻度とのバランスで決めましょう。
更新をすぐに反映したい場合は、Purge モジュールなどで「更新時に CDN のキャッシュを消す」仕組みも合わせて検討します。
3. Views のキャッシュ設定を確認する
ウィザードで作ったビューは、最初からタグベースのキャッシュになっています。タグベースなら記事の更新に合わせて一覧のキャッシュも自動で消えるため、基本的にはこのままで問題ありません。
ただし、作業中に「キャッシュなし」へ変えたまま忘れているケースがよくあります。構築の終盤に、アクセスの多い一覧ページのキャッシュ設定を一度見直しておくと安心です。逆に「時間ベース」にすると、更新してもしばらく一覧に反映されないので注意してください。
4. 中〜大規模サイトはキャッシュの保存先を Redis に
Drupal はデフォルトでキャッシュをデータベースに保存します。小規模なサイトならこれで十分ですが、アクセスが多いサイトではキャッシュの読み書き自体がデータベースの負荷になります。
中〜大規模サイトでは、Redis モジュールなどを使ってキャッシュの保存先をメモリ上のストアに切り替えるのがおすすめです。データベースの負荷が下がり、応答も速くなります。
5. CSS/JS の集約は本番で必ず有効に
CSS/JS の集約は、開発中は無効にすることがあります。そのまま本番に出してしまうと、ページごとに大量のファイルを読み込むことになり、表示が遅くなります。リリース前のチェック項目に入れておきましょう。
開発環境と本番環境で設定を分ける
開発中はキャッシュが効いていると、テンプレートや CSS を修正してもすぐに反映されず不便です。開発環境ではキャッシュを無効にしておくと作業がスムーズになります。
管理画面から切り替える(Drupal 10.1 以降)
「環境設定 > 開発 > 開発設定」(/admin/config/development/settings)で、次の項目を切り替えられます。
- Twig development mode(Twig のデバッグとキャッシュの無効化)
- Do not cache markup(レンダーキャッシュ・ページキャッシュの無効化)
この設定は設定ファイル(config)としてエクスポートされないため、うっかり本番に反映される心配が少ないのも利点です。ただし、データベースごと本番に移すような運用では持ち込まれる可能性があるので注意してください。
settings.local.php で切り替える
Drupal に同梱されている sites/example.settings.local.php を settings.local.php としてコピーすると、開発環境だけの設定を書けます。次の行のコメントを外すと、各キャッシュが無効になります。
$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';
settings.local.php は開発環境専用のファイルです。本番環境には置かないようにしましょう。
「更新したのに反映されない」ときの確認ポイント
- キャッシュをクリアする:「環境設定 > 開発 > パフォーマンス」の「すべてのキャッシュをクリア」、または drush cr
- ブラウザや CDN のキャッシュを疑う:シークレットウィンドウや別のブラウザで確認する
- Views のキャッシュ設定を確認する:時間ベースになっていないか
- カスタムテンプレートやカスタムコードを疑う:ここまでで直らない場合、テンプレートやコードでキャッシュの扱いに漏れがある可能性があります
4 については、キャッシュタグなどの仕組みを理解すると原因を特定しやすくなります。次回、開発者向けに詳しく解説する予定です。
まとめ
Drupal のキャッシュは、デフォルトでも基本的な部分はしっかり有効になっています。構築時に見直したいのは次の4点です。
- ✅ ページキャッシュの3モジュールは有効のままにする
- ✅ 「ブラウザおよびプロキシのキャッシュの最大有効期間」を、更新頻度に合わせて設定する
- ✅ Views のキャッシュが「なし」や「時間ベース」になっていないか確認する
- ✅ 中〜大規模サイトはキャッシュの保存先を Redis に切り替える
加えて、開発環境と本番環境でキャッシュ設定を分けておけば、開発のしやすさと本番の速さを両立できます。
※エントリーの内容・画像等は、公開時点での情報に基づきます。
※Drupalのバージョンによって実装されている機能が異なります。