Posted at

PhoenixでS3 + CloudFrontでアセットを配信する

More than 1 year has passed since last update.


やりたいこと

priv/static以下の静的ファイルをmixのタスクからS3にアップロードし、CloudFrontからアセットを配信したい


やったこと

PHPでLaravel向けにvinelab/cdnというアセットライブラリがあるのだけどElixirに似たようなライブラリがなかったのでポートしたのを作ってS3 + CloudFrontで配信出来るようにした

cdn | Hex (GitHub)


Installation


  • mix.exsに依存を追加

{:cdn, "~> 0.0.4"}


  • 依存更新

mix deps.get


  • configを追加

config/config.exs

config :cdn,  include: [

directories: ["priv/static"],
patterns: ["**/*"],
hidden: true
],
exclude: [
directories: [],
patterns: [],
hidden: true
],
acl: :public_read,
bypass: true,
cache_control: "max-age=#{86400 * 30}",
expires_after: 86400 * 30

項目
説明

include

directories: アップロード対象のディレクトリ
patterns: Glob patternでアップロード対象の絞込。複数指定可。
hidden: 隠しファイルを含めるかどうかをtrue, falseで指定

exclude
除外対象のファイル。includeと同じようにディレクトリとパターンを指定。

acl
アップロードしたオブジェクトの権限。アセットとして公開されるので通常はpublic_readにする。

cache_control

Cache-Controlヘッダに指定する値

expires_after

Expiresヘッダに指定するキャッシュ期限切れまでの秒数

config/dev.exs

config :cdn, bucket: "foobar.assets",

cloudfront_url: "https://foobar.cloudfront.net",
bypass: true

項目
説明

bucket
アップロード対象のS3バケット

cloudfront_url
S3と紐付けられているCloudFrontのURL

bypass

trueの場合ビュー用のヘルパーでURLを補完しない。
e.g. cdn("/css/app.css") => "/css/app.css"

config/prod.exs

config :cdn,  bucket: System.get_env("ASSET_BUCKET") || "foobar.production.assets",

cloudfront_url: System.get_env("ASSET_HOST") || "https://foobar.cloudfront.net",
bypass: false

項目
説明

bypass

falseの場合ビュー用ヘルパーでURLを補完する。
e.g. cdn("/css/app.css") => "https://foobar.cloudfront.net/css/app.css"


  • AWSのアクセスキーを環境変数にセット

export AWS_ACCESS_KEY_ID=foo

export AWS_SECRET_ACCESS_KEY=bar


Usage


  • アセットアップロード

mix cdn.push


  • 削除

mix cdn.empty

image


  • テンプレートで静的ファイルの読み込み

web/web.ex

def view do

~中略~
# 追加
import Cdn.Helpers

end

app.html.eex

<script src="<%= cdn static_path(@conn, "/js/vendor.js") %>"></script>

# bypass=trueの場合
#=> "<script src="/js/vendor.js"></script>"

# bypass=falseの場合
#=> "<script src="https://foobar.cloudfront.net/js/vendor.js"></script>"


まとめ


  • PhoenixでS3 + CloudFrontでアセットを配信出来るようにした

  • Elixir内で完結するので他のツール使いたくない場合はいいかも

  • 今気づいたけどasset_syncって似たようなライブラリが既にありますね(遅)