Amazon CloudFront & Lambda@Edge でリクエストに応じて自動で画像リサイズする仕組みを試してみた
Webページをすばやく表示するにはページ内画像のlazyloadや圧縮は不可欠。
けど、毎回画像を圧縮するのは手間だし自動化したい。
そして、なんかモダンな方法でやってみたい。
ってことで、調べていたらこの記事を見つけました。
Amazon CloudFront & Lambda@Edge で画像をリサイズする | Amazon Web Services ブログ
参照記事によると、
- リクエストのクエリパラメータに応じて画像をリサイズしてレスポンスを返す
- webp対応のブラウザには画像をwebpに変換してレスポンスを返す
が実現できるとのこと。
お、これ使えば画像の圧縮も簡単にできそう!!
しかもS3にオリジナルファイルを残した上で実現できるやーん 😆
さらに動的にリサイズできるからサイズ変更とか追加も簡単そう 💪
ひとまず動作検証したかったので、カスタマイズせずに記事通りにやってみました。
(画像の圧縮はOrigin-Response関数に手を加えればできるはず)
Lambda@EdgeやCloudFrontの細かい説明は参照記事におまかせするとして、参照記事では詳細な実装手順がわからなかったりつまづくポイントがあったので流れをまとめます。
Dockerで環境構築
まずはDockerでLambda@Edge関数をコンパイルするための環境を構築します。
Dockerfileを作成する
参照記事のままのDockerfileだとさっそくコケるので注意 😂
tar
, gzip
がなくてbuildが通らないので追加しています。
FROM amazonlinux WORKDIR /tmp #install the dependencies RUN yum -y install gcc-c++ findutils tar gzip RUN touch ~/.bashrc && chmod +x ~/.bashrc RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.5/install.sh | bash RUN source ~/.bashrc && nvm install 6.10 WORKDIR /build
docker buildする
docker build --tag amazonlinux:nodejs .
Lambda@Edge関数の作成
View-Request関数をつくる
これは参照記事のままでOK。
lambda/viewer-request-function/index.js
に保存しました。
Origin-Request関数を作る
これも参照記事のままでOK。
lambda/origin-response-function/index.js
に保存しました。
関数のコンパイル&パッケージング
Origin-Response 関数
$ docker run --rm --volume ${PWD}/lambda/origin-response-function:/build amazonlinux:nodejs /bin/bash -c "source ~/.bashrc; npm init -f -y; npm install sharp --save; npm install querystring --save; npm install --only=prod" $ mkdir -p dist && cd lambda/origin-response-function && zip -FS -q -r ../../dist/origin-response-function.zip * && cd ../..
Viewer-Request 関数
$ docker run --rm --volume ${PWD}/lambda/viewer-request-function:/build amazonlinux:nodejs /bin/bash -c "source ~/.bashrc; npm init -f -y; npm install querystring --save; npm install --only=prod" $ mkdir -p dist && cd lambda/viewer-request-function && zip -FS -q -r ../../dist/viewer-request-function.zip * && cd ../..
CloudFormationの実行
zipファイルのUPLOAD
まずはS3バケットを作成し、先ほど作成したzipファイルをUPLOADします。
Lambda 関数の要件と制限 - Amazon CloudFront
トリガーを追加できるのは、米国東部(バージニア北部) リージョンの関数のみです。
とあるので、このバケットのRegionもus-east-1
を使います。
yamlファイルの作成
これも参照記事のままです。
cloudformation.yaml
として保存しました。
テンプレート内の<code-bucket>
は上記で作成したS3バケット名を設定してください。
スタックの作成
リージョンをus-east-1
に切り替えて、CloudFormationを実行します。
スタックの作成 > テンプレートを Amazon S3にアップロード で、先ほどのyamlファイルを指定します。
スタックがじゃんじゃん作成されて、完了。
あとは、作成されたS3バケット(image-resize-${AWS::AccountId}-${AWS::Region}
)に画像をUPLOADして、CloudFront経由でアクセスすればOKです。
https://{cloudfront-domain}/images/image.jpg?d=100x100
アクセスすると、画像が表示されるのと、S3にフォルダが作成されて、リサイズ後の画像が保存されています。
・・・
なんか急に説明が雑になってしまった 😇
考えないといけないこと
ステキな仕組みやけど考えないといけないこと。
初回アクセスが遅い
まあわかってはいたけど。。画像処理してるわけですし 🍣 クローラーつくってクロールさせるとか、なんかシステムで自動化したいところ。
S3への画像UPLOADが遅い
バケットがus-east-1
になっているのでしゃあないけど実際運用するとなるとひと手間必要かなぁ。
UPLOAD用のバケットは東京Regionに作成して、us-east-1
のバケットにsyncするとかかなぁ 🤔
ってことで、いろいろやるべきことが多そうだし今回は見送りました。
はじめてLambda@EdgeやCloudFormationを使ったので良い勉強になりました。
実際運用できる仕組みを作ったらまた記事にします 😋
おしまい。