paranitips

Never stop learning! がモットーのゆるふわエンジニアブログ

Amazon CloudFront & Lambda@Edge でリクエストに応じて自動で画像リサイズする仕組みを試してみた

Webページをすばやく表示するにはページ内画像のlazyloadや圧縮は不可欠。
けど、毎回画像を圧縮するのは手間だし自動化したい。
そして、なんかモダンな方法でやってみたい。

ってことで、調べていたらこの記事を見つけました。
Amazon CloudFront & Lambda@Edge で画像をリサイズする | Amazon Web Services ブログ

参照記事によると、

  1. リクエストのクエリパラメータに応じて画像をリサイズしてレスポンスを返す
  2. 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を使います。

f:id:paranishian:20181115180417p:plain

yamlファイルの作成

これも参照記事のままです。
cloudformation.yamlとして保存しました。
テンプレート内の<code-bucket>は上記で作成したS3バケット名を設定してください。

スタックの作成

リージョンをus-east-1に切り替えて、CloudFormationを実行します。

スタックの作成 > テンプレートを Amazon S3にアップロード で、先ほどのyamlファイルを指定します。

f:id:paranishian:20181115180451p:plain

スタックがじゃんじゃん作成されて、完了。

f:id:paranishian:20181115180511p:plain

あとは、作成されたS3バケットimage-resize-${AWS::AccountId}-${AWS::Region})に画像をUPLOADして、CloudFront経由でアクセスすればOKです。

https://{cloudfront-domain}/images/image.jpg?d=100x100

アクセスすると、画像が表示されるのと、S3にフォルダが作成されて、リサイズ後の画像が保存されています。

f:id:paranishian:20181115182206p:plain

・・・

なんか急に説明が雑になってしまった 😇

考えないといけないこと

ステキな仕組みやけど考えないといけないこと。

初回アクセスが遅い

まあわかってはいたけど。。画像処理してるわけですし 🍣 クローラーつくってクロールさせるとか、なんかシステムで自動化したいところ。

S3への画像UPLOADが遅い

バケットus-east-1になっているのでしゃあないけど実際運用するとなるとひと手間必要かなぁ。
UPLOAD用のバケットは東京Regionに作成して、us-east-1バケットにsyncするとかかなぁ 🤔

ってことで、いろいろやるべきことが多そうだし今回は見送りました。

はじめてLambda@EdgeやCloudFormationを使ったので良い勉強になりました。
実際運用できる仕組みを作ったらまた記事にします 😋

おしまい。

Resource Hintsの対応をしてWebPageTestの点数を改善した

f:id:paranishian:20181102183456j:plain Photo by rawpixel on Unsplash

はじめに

いま開発チームでサイト速度改善に取り組んでいて、 その一環でResource Hintsの対応をしたので、調べたこととリリース後の効果をまとめます🙌

調べたこと

まずはResource Hintsについて
Resource Hints

ふむふむ。いろんな種類があるなぁ。🤔

DNS プリフェッチの制御 | MDN

特にモバイル環境においては、 DNS プリフェッチによりページの読み込みにかかる時間が劇的に改善されます。例えば、多数の画像が表示されるページにおいて、画像が要求される前に名前解決が行われている場合では読み込み時間が 5% 以上削減されるでしょう。

ほうほう、すばらしい!😆

DNS Prefetching - The Chromium Projects

注意点として、dns-prefetchは、HTTPSページではデフォルトで機能しない😇 けど、<meta http-equiv="x-dns-prefetch-control" content="on">と記述することでHTTPSページでも使えるようになるとのこと。

他ではどういう対応をしているのか見てみよう。

日経

preconnectを使っている。 2018-10-30 14 32 00

twitter

preconnect, dns-prefetchを併用している 👀 preloadも使ってるなぁ。 image

amazon

dns-prefetchのみ 2018-10-30 14 31 05

この記事によるとpreconnectdns-prefetchを併記したほうが良さそう👇
html - DNS-Prefetch and Preconnect - One, or Both? Fallback? - Stack Overflow

なるほどなるほど。

やったこと

いろいろ調べた結果、

  • 確実に必要なものにはpreconnect, dns-prefetchを併記
  • そうでないものにはdns-prefetchのみ記述
    • 広告系のタグとか

という方針で実装しました。

こんなかんじ。slimファイルです

head
  meta http-equiv='x-dns-prefetch-control' content='on'
  link rel='preconnect dns-prefetch' href='//cdn.sotoasobi.net'
  link rel='preconnect dns-prefetch' href='//www.googletagmanager.com'
  link rel='preconnect dns-prefetch' href='//www.google-analytics.com'
  link rel='dns-prefetch' href='//maps.google.com'
  link rel='dns-prefetch' href='//www.googleadservices.com'
  link rel='dns-prefetch' href='//googleads.g.doubleclick.net'
  ...

リリース後の効果

WebPageTestの点数が改善しました!🎉

start render speed index
1.900s → 1.500s 2.080s → 1.818s

dns lookup (緑の部分)が飛び飛びで先読みしていることがわかります😙

before after
2018-10-30 16 25 33 2018-10-30 16 24 18

この他にも、

  • アセットの軽量化
    • 画像の圧縮
      • lambdaでの自動化も考えている
    • css, jsの不要部分削除
      • 地味にしんどいやつ
  • 画像のlazyload

あたりを地道にやっていって、さらに改善中です😋

f:id:paranishian:20181101163913p:plain

まだまだこれから!チームでがんばるでぃ💪

iOSショートカットでちょっとしたライフハックをしてる話

f:id:paranishian:20181024100856p:plain

iOS12から登場したショートカットをつくるのが楽しすぎて時間が溶ける・・・🤤
自分は最近Google Mapを使うことが多いので、そのときに使えるショートカットをつくりました。

iCloudの共有リンクも置いてるので良ければ使ってみてください🙌

※ショートカットAppはプリインストールではないのでAppStoreからインストールする必要があります
ショートカットの使い方はこの記事が詳しいです👇
iOS 12で「ショートカット」アプリを使ってみよう:iPhone Tips - Engadget 日本版

お店の他の口コミを調べる

Google Mapでお店を見つけて、
Google以外の他のサイトの口コミも見てみたいなー🧐」
そんなときに使います。

Google Mapで、
共有 > ショートカット > 〇〇で調べる
で検索できます。

f:id:paranishian:20181023112237g:plain

ページを直接開くショートカットも作ってみたのですが、速度がなんとも遅かったのでシンプルにGoogle検索するだけにしました💡

バス停の場所を調べる

例えば渋谷駅。
「乗り換え案内でバス経由で表示されてもバス停の場所がわからん。。。🤮」
そんなときに使います。

f:id:paranishian:20181023112219g:plain

バス停の場所を調べる

ウィジェットからワンタップで

ウィジェットに表示するとさらに捗る。
いまんとここの2つを重宝してます😎 f:id:paranishian:20181023191202p:plain

目覚ましをセットする 嫁にLINE電話する
f:id:paranishian:20181023185520j:plain f:id:paranishian:20181023185525p:plain

LINE電話をショートカットに表示するには、まず一度LINEで電話すればショートカットAppに表示されるようになります👌

もっといろいろ種類が出てくるとおもしろいなぁ〜。

おしまい🤗