Drupal8のTomeモジュールで静的サイトを生成する

Drupalのサムネイル
目次

はじめに

公開サイトのセキュリティの向上とスケーラビリティの観点から、CMSで構築したサイトをCDN上の静的サイトとしてデプロイするサイト運用が昨今非常に注目されています。そのツールとしてのSSGも老舗のJekyll, Hugoから最近急成長のGatsbyまで多種多様です。

SSGによるサイト公開までの流れは、

  1. コンテンツのソースとなるMarkdownファイルやHTMLファイルの作成
  2. サイト生成のための設定ファイル、テンプレート、CSS、画像などの準備
  3. これらのデータからSSGがデプロイ用のディレクトリに静的サイトを生成
  4. デプロイ用のディレクトリをCDNや公開用サーバーにアップロード

が基本です。さらに最近ではソースとなるMarkdownファイルなどの代わりにDrupalやWordPressのコンテンツをソースとするSSG用のプラグインも提供されています。

一方Drupal本体にSSGの機能を持たせるというアイデアもあり、その実装としてTomeというモジュールがまだベータ版ですが公開されています。静的サイト生成については Static Generator というモジュールもありますがDrupal8に対応していないためその代替としてTomeがどこまで使えるか検証しました。

テスト用のサイトとしては最近のDrupal8のインストレーションプロファイルにあるUmamiというプロファイルで生成されるレシピ集のデモサイトを使いました。Umamiについては「ANNAIマガジン」の記事「 Drupal 8のデモ用インストールプロファイルUmami を日本語化してみた 」に詳しい解説があり、日本語化した画面も紹介されていますが、その画面とTomeで生成した静的サイトとして今回公開したデモサイト https://umami-static.work/ を比較するとかなり忠実に生成されており十分実用に耐えるものとなっています。

インストレーション

Tome モジュールは2018/12/23公開の https://www.drupal.org/project/tome/releases/8.x-1.0-beta2/ を使用しました。 
https://dev.acquia.com/downloads/ からダウンロードしたAcquia Dev Desktopをインストールした以下の環境を用いてテストしました。

  • OS macOS Mojave 10.14.2
  • Drupal 8.6.2
  • MySQL 5.6.41
  • PHP 7.2.9
  • Apache 2.4.29

モジュールのインストールは機能拡張のページから通常の手順で行いました。 
モジュールの有効化後は以下の機能拡張が追加されます。

Tome after Install

静的サイトの生成

サイトの生成はとっても簡単です。 
環境設定に追加された以下のメニューから「Generate static site」を選択します。

Tome Static Menu.

選択後表示される以下の画面で送信ボタンをクリックするとあらかじめ設定されたディレクトリに静的サイトに必要な全てのファイルが書き出されます。

Tome submit generation

デフォルトでは../htmlというドキュメントルートの外のディレクトリに出力されます。(このディレクトリはsettings.phpで変更出来ますが、ドキュメントルートの下のディレクトリを指定するとそのディレクトリからさらに静的サイトを作成しようとしてループ状態になり、エラーが発生するので注意してください)

なお、同じことは 
drush tome:static 
コマンドでも実行できるので、コンテンツ更新をトリガーにこのコマンドで静的ファイルを生成し、さらにそれを公開用サイトにデプロイするスクリプトを実行することも可能です。( https://tome.fyi/docs/sub-modules/ によれば将来的には tome:static:watch というオプションが追加されサイトの変更を監視してバックグラウンドで自動的に静的サイト生成を行えるようになる可能性があります)

サイト生成処理は差分更新ではなく全サイト生成なので大規模サイトでは相応の時間が必要となりそうです。生成時間を重視するならば同じ全サイト生成でもかなり高速なGatsbyと連携するというアイデアもあり、後でもう少し詳しく説明します。

静的サイトの特徴と制約

Umamiのようなカスタムコンテンツタイプやそのビューを含むサイトであってもかなり忠実に再現されています。レスポンシブデザインも維持されていますし、タクソノミーのターム別ページも再現されています。デモ用に生成した https://umami-static.work/ のサイトで確認することができます。またページネーションや多言語サイトでの言語切替が動作することも別のテストサイトで確認しました。下図は日英の言語別コンテンツ切り替えのサンプルです。

多言語サイトサンプル

ただし変換が忠実すぎて静的サイトでは実行できないフォームを持つブロックやそのフォームへのリンクまで生成されます。従って静的サイトを意識して以下のような要素とそれらに関連するブロックやリンクなどを、生成前に非表示または無効にしておくことが必要です。

  • ログインフォーム
  • 検索フォーム
  • メール問合せフォーム
  • ビューの持つフィルターやソート機能

なお、これらの制約にどのように対応するかは後述します。

Tomeモジュールの詳細なドキュメントは https://tome.fyi/docs/ に公開されておりその中の https://tome.fyi/docs/technical/static/ にサイト生成のロジックが解説されています。概略は以下のとおりです。

1. 匿名ユーザーからアクセスできる全てのルート(route)及び全エンティティ(さらにそれらの翻訳)の標準化されたパスで、パラメーターを使用していないものを収集します。 
2. パスについては以下のように処理します。 
a. パスが静的ファイルの場合はそのままコピーします。 
b. 静的ファイルでないパスについてはDrupalのhttp.kernelサービスを呼び出します。 
c. レスポンスがHTMLの場合はそれをファイルとして保存します。 
さらにその中で参照する種々のアセットのパスを収集します。 
現在のバージョンではViewsのpager link、イメージ、CSS、JavaScript、faviconが対象になります。 
CSSの場合はさらにその中のurl()で参照されているURLもアセットのパスに追加します。 
3. 新たに追加されたアセットのパスについて上記2.の処理を行います。これを新たなアセットがなくなるまで繰り返します。

このロジックにより多言語サイトや任意のコンテンツタイプやビューにも対応できることが理解できます。

Drushを使ったインストレーション

https://tome.fyi/docs/getting-started/ には「Tomeは既存のサイトにもインストールできるが、専用のDrupalコンフィグレーションを用いてインストールするのがベストである」という記述があり、ComposerとDrushを用いてTomeがインストールされた新規サイトを作成する手順が解説されています。 
そこでこのページにあるスクリプトをUbuntu 18.04の環境で以下のように実行して動作を確認しました。

Tome Drush Installation.png

インストール後にUmamiサイトのテストに用いたAcquia Dev Desktopのサイトのsettings.phpとこのDrushでインストールしたサイトのsettings.phpを比較したところ、後者のサイトはデフォルトでSQLite3のデータベースを用いる設定が追加されている以外は違いが見当たりませんでした。さらに管理>>Reports>>Status reportを比較したところ後者のPHPメモリ制限が無制限になっているところが目立った違いでした。もしこのメモリ無制限の設定がTome用の最適な設定の主要な部分ということであれば、Drushを使用せずに通常の方法でTomeモジュールをインストールしてからメモリ無制限の設定に変更するだけでも大差はないとも考えられます。

Gatsbyとの連携

ReactベースのSSGとして急成長している Gatsby とTomeとの 連携のサンプル が公開されています。このページの手順に従ってUbuntu 18.04上に新たにDrupalとGatsbyのプロジェクトを作成してDrupalをソースとしてGatsbyで静的サイトを生成しました。サイトのサンプルは https://tome-gatsby-sample.now.sh/ にあります。

通常GatsbyとDrupalの連携には、DrupalのJSON:APIモジュールを経由してコンテンツを取得する gatsby-source-drupal というGatsbyのSource pluginを使用します。しかし、このサンプルはTomeモジュールでDrupalコンテンツを一旦JSONファイルに変換して保存し、そのファイルを gatsby-transformer-json という別のプラグインによって静的コンテンツに変換しています。この外部APIを呼び出す代わりにファイルから読み込む手法を採ることで、「gatsby develop」コマンドでGatsbyを開発モードで実行している場合はDrupalコンテンツの更新が即座にGatsbyに反映され、ページが自動リロードされます。また静的サイト生成時にはDrupalが実行されていなくてもよいので、フロントエンドとバックエンドの開発チームや環境を独立させることもできます。

制約事項としては

  • DrupalはあくまでGatsbyへのソース提供サーバーとしてのHeadless CMSとして動作するのでGatsbyフロントエンドのテーマやリスト表示、ページネーションなどはGatsby側で実装する必要があります。
  • サンプル内のGraphQLは特定コンテンツタイプのみ対応しており、かつ取得している全てのフィールドにデータがないとコンテンツが生成されません。したがって複数コンテンツタイプに対応し、かつデータのないフィールドも考慮するとより複雑な処理が必要となります。

などがあります。 
数千ページから数万ページ規模のサイトではGatsbyの持つ高速なサイト生成とレンダリング時のページプリロードなどの高速化機能が活用できるので、大規模サイト構築の場合は考慮すべきオプションになると思います。

静的サイトの制約への対応

静的サイトであっても外部サービスのAPIなどを使って動的な動作を可能にする JAMstack というアプローチを参考にして「ANNAIマガジン」の記事「 Drupalサイトを静的HTML(Static HTML)に変換する方法 」の「 静的HTMLで難しいこと 」の章に列挙された制約にどこまで対応可能かを考えてみました。

  • ユーザー登録とログイン 
    Basic認証によるログイン制限であればサイト生成後に.htaccessファイルを適宜設置するようにしておくという対応が考えられます。Netlifyでは デプロイした静的サイト用の認証サービス などもあります。これにはOAuthを利用した認証機能などもあるようです。
  • コメント機能 
    静的サイトを閲覧した人がその場でコメントするのはコメントの入力・表示などのAPIの開発にある程度の工数が必要です。
  • コンタクトフォーム 
    メール送信フォームの場合は、デプロイしたサイトでSMTPサーバーが稼働していれば作り込むことは可能でしょう。Netlifyでは フォーム処理サービス も提供されています。
  • 検索機能 
    静的サイトにしたときに一番の課題となる検索機能の実装についてはいくつかのアイデアがありますが詳細は別の機会に考察したいと思います。
  • ビューのフィルターやソート 
    これは難易度が高い課題です。Drupal側でフィルタリングやソートを処理するAPIを準備しておき、フロントエンドでは例えば https://handsontable.com/docs/6.2.2/demo-filtering.html のようなJavaScriptのGridライブラリを使ってフィルタリングやソートのUIを提供する必要があります。 
    またフィルタリングの条件が性別や過去数年の西暦年などの比較的固定的なものであればJavaScriptで作り込むことでも一応対応できるでしょう。
  • ロールあるいはユーザー単位のコンテンツやブロックの表示制御 
    ​​​​​​​Basic認証を用いたユーザーに対するディレクトリ単位でのアクセス制限であれば各ディレクトリへの.htaccessの配置で対応できますが、ロールベースの制御やブロックレベルの表示・非表示などの細かい制御は難易度が高くなるでしょう。
  • リアルタイムでのコンテンツ更新 
    ​​​​​​​一般的には難易度が高い機能です。しかしながらトランザクション処理が必要で難しそうなeコマース機能については、eコマースAPIのサービスが複数のベンダーから提供されていて Gatsbyベースのeコマースサイトの解説記事 もあります。商品の詳細な解説やプロモーション及びブログやヘルプ機能だけはDrupalで作成し、eコマース機能は外部API使用というようなサイトをGatsbyと連携して実現することは可能でしょう。
  • スケジュール公開 
    ​​​​​​​Schedulerモジュールにより公開日時を設定した場合そのノードは公開日時までは匿名ユーザーからアクセスできないので、公開日時の制御が1時間単位でよければ1時間おきに、1日単位で問題なければ毎日サイト生成すれば対応できます。

まとめ

  • Drupalのサイトをかなり忠実に静的サイトに再現できることを確認できました。UmamiのようなカスタムコンテンツタイプやそのViewを含むサイトにも対応できます。
  • 静的サイトでは無意味なDrupalへのログインフォームまで再現するので静的サイトを意識した若干の手直しは必要になります。
  • SSGであるGatsbyとの連携のサンプルも動作が確認できました。Drupalコンテンツの迅速な反映や大規模サイトの高速レンダリングが必要な場合はGatsbyとの連携も選択肢になります。
  • CMSのStatic Site化は今後のトレンドになると思うので、そのツールとしてTomeは極めて有効なモジュールであることが検証できました。従来はGatsbyやHugoなどのSSGとの組み合わせが必須だと考えていましたが、サイトの再現性を確保するにはある程度の工数が必要であり、Tomeはこの点でも明らかに優れています。

 

カテゴリ