Discourse で使用されているすべての静的アセット(js、css)を収集する方法

フォーラムに CDN を設定しようとしています。中国で Fastly や多くの CDN サーバーが禁止されているため、それらを使ってフォーラムを高速化することができません。いくつか調査した結果、npm や GitHub リポジトリから静的ファイルを配信できる Jsdelivr に頼ることにしました。

app.yml で DISCOURSE_CDN_URL を設定して URL を指定できることは理解しています。しかし、その前に、フォーラムからすべての静的ファイル(js、CSS)を収集し、Jsdelivr がアクセスできるように GitHub にアップロードする必要があります。静的ファイルは実際には Docker コンテナ内の以下のパスに存在することを見つけました:

/var/www/discourse/app/assets

そのため、アプリを再構築するたびにこのパスからすべてのファイルをコピーし、GitHub にアップロードしようと考えています。このアイデアは機能すると思いますが、実際のリクエストには長いハッシュ名が含まれており、それを取得する方法がわかりません。例えば、

ember_jquery.js は
ember_jquery-8ef4e572f0bf9485e6ef9a35f088729735f82434cf495fbcd5acedefbcddb363.js
のようになります。

そこで質問です。

  1. ハッシュ付きファイル名を生成する方法は?
  2. 静的アセットを収集する他の方法はありますか?

ファイル内容の SHA1 ハッシュです。以下で生成されます:

使用されるコンパイル済みバージョンは /var/www/discourse/public/assets/ に配置されます。

app.yml に節を追加すると、コンテナが再構築された後にアクションを実行できます。例えば、S3 へのアップロードには以下に似た設定を使用します:

hooks:
  after_assets_precompile:
    - exec:
        cd: $home
        cmd:
          - sudo -E -u discourse bundle exec rake s3:upload_assets

あなたのケースでは、コンテナがビルドされたときにコンパイル済みアセットを GitHub にプッシュするために実行するコマンドに、rake タスクを置き換えてください。

@schleifer さん、ありがとうございます。大変参考になりました。ただ、いくつか追加の質問があります:

  1. after_assets_precompile のようなフックに関するドキュメントはどこで見つけることができますか?Docker のドキュメントや Discourse の GitHub リポジトリを検索しましたが、それに関する情報は見つかりませんでした。after_assets_precompile という名前のフックを自分で設定する必要があるのでしょうか(その場合、どのように設定すればよいですか?)、それとも after_code のように Discourse 側で既に設定されているのでしょうか?

  2. 私の理解では、擬似コードは以下のようになります:

     hooks:
       after_assets_precompile:
         - exec:
             cd: $home
             cmd:
               - Docker コンテナに入室
               - `/var/www/discourse/public/assets/` に移動
               - git add、commit、そして GitHub リポジトリに push
    

よろしくお願いいたします。

それは良い質問ですが、残念ながら明確な回答はありません。

コンテナ内で使用されている設定システムは以下の通りです:

その README には、フックの一般的な仕組みについて説明されています。利用可能な特定のフックは、インスタンスのセットアップ方法によって異なります。主な app.yml には、1 つ以上のテンプレートが含まれています。多くの場合、その中の 1 つは web.template.yml です:

assets_precompile フックは、私がこの文章を書いている時点では [L159] で定義されています。pups のドキュメントによると、before_assets_precompile および after_assets_precompile を使用して、その完了前または後に他のコマンドを実行できます。

コマンドは Docker コンテナ内で実行されるため、それを行うための特別な手順は不要です。

cd: ディレクティブは /var/www/discourse/public/assets/ に直接指し示すことができ、cmd の各行はそのディレクトリから実行されます。(注意:cmd 配列内の各行は、Makefile のように個別のシェルで実行されます)。

/var/www/discourse/public/assets/ の内容がビルド間で永続化されるかどうかはわかりません。そのため、毎回ローカルの Git リポジトリを作成して強制プッシュする必要があるかもしれません。より「正しい」解決策としては、app.yml でアセットディレクトリ用の Docker ボリュームを定義し、それを app.yml で定義された他のボリュームと同様にコンテナ外で永続化することかもしれません(参照)。

どうもありがとうございます。また、静的アセット(CSS など)が /var/www/discourse/tmp/stylesheet-cache に配置されていることも確認しました。しかし、他にも 2 つの問題があります:

  1. DISCOURSE_CDN_URL を設定した後、ユーザーがアップロードしたアセット(アバターなど)も CDN で提供されます。しかし、ユーザーがアップロードするたびにアップロードされたアセットを GitHub にプッシュするのは、あまり良い解決策ではないように思われます。
  2. Discourse が 2_2.png のようなユーザーアバターを要求する際、1) ファイル名を分割し、2) いくつかのチェックを行い、3) ハッシュを使用して実際のファイル名を計算します。ユーザーアバターを提供する必要がある場合、2_2.png という名前のファイルが存在しないため、同じロジックを自分で実装しなければなりません。

私の最終的な解決策はシンプルです。1) フォーラムの前に Nginx を追加します(こちらの投稿のように)。2) 上記のパスからすべての静的アセットを収集し、GitHub にプッシュします。3) Nginx の設定ファイルに、以下のようなルールを追加します。

location ~/(stylesheets|assets) {
    return 301 https://cdn.jsdelivr.net/gh/my_github/my_repo/$request_uri;
}

@schleifer、再度ありがとうございます。