CSS
HTML5
SVG
cdn
パフォーマンス

超高速な静的Webページを作ろう!

まばたきよりも速くしたい!

静的なプロフィールページを高速化する試みを綴ります。
極めている方からしたら止まって見えるほど遅いかもしれませんが...
簡単に、そしてそれなりに高速化できたので共有します:clap:

出来たページ → rigani's profile

最初に計測結果です。

webpagetest

計測結果

Load Time First Byte Start Render Speed Index
0.192s 0.131s 0.233s 233

Document Complete

Time Requests Bytes In
0.192s 1 6KB

Fully Loaded

Time Requests Bytes In
0.107s 1 6KB

PageSpeed Insights

計測結果

モバイル/パソコン 共に100点:grinning:
Good 100/100
速度という点に絞ると信用できるものではないかもしれませんが、100点という数字は単純にうれしい:)

それでは!以下が私のやったことです:airplane:

リクエスト数を極限まで減らす

CSSはstyle属性やstyleタグで設定

複数箇所で使う場合はstyleタグに、要素固有のスタイルはstyle属性で設定してしまいましょう。
style属性で設定する場合はセレクタでの捜索が発生しないので、ごく僅かながら速くなると思います。

<body style="margin:2px 0 0;padding:3vh 0 5vh;background:#fffdfd;font:500 15px 'Yu Gothic',YuGothic,sans-serif;font-feature-settings:'palt';letter-spacing:.08em">

画像はbase64で埋め込む

こことかでデータURIスキームに変換してhtmlに埋め込みます。
base64エンコードすると容量が1.3倍くらいに増加するため大きな画像には向かない方法ですが、小さなアイコン程度ならリクエスト数減らすほうが効果的な場面があります。

複数箇所に使う画像の場合はCSS変数でbackground-imageに設定すればファイルサイズ削減できますね!

あっfaviconもリクエストされてる:tired_face: どうしようこれ...
(svgをbase64化して埋め込みました。対応ブラウザ少ない)
続: svgはbase64化しないでDataURIに埋めました。このほうが断然軽量でした!
Optimizing SVGs in data URIs
@sawadays0118 さん、素敵な情報をありがとうございました。

JSはasync/deferで読み込む

「ていうかjs使うのやめよう!」となってページから取り除きましたが、一応書いておきます。
使うのやめたのは、今回単一ページであり、更にファーストビュー外にコンテンツいっぱい置くつもりなかったためです。
async/deferはどちらもscriptタグで使える非同期での読み込み指定ですが、実行のタイミングが異なります。
詳しくは以下のクールなまとめを見てください:pray:
script タグに async / defer を付けた場合のタイミング

1byteでも軽くする

無駄なコードを削除

minifyしてくれるツール使えばいいと思いますが、いい機会なので手動でやりました。
ツール用意するのがめんどくさかった

CSSの最小化

以下のCSSを最小化してみます。

何もしてないCSS
#l li {
  margin: 0 0.7em;
  list-style: none;
}
  • 最終行のセミコロンを削除
  • コロン後のスペースを削除
  • 小数で整数部が0の場合は削除
  • セレクタとカッコの間のスペースを削除
最小化後
#l li{margin:0 .7em;list-style:none}

HTMLの属性間のスペース削除

W3Cのチェックで怒られたのでちゃんと空けるようにしましたが、一応書いておきます。
htmlは属性間のスペースを取り除いても表示はできます。

<meta name="viewport"content="initial-scale=1">

HTMLの属性値を囲うクォーテーション削除

@jkr_2255 さんより、コメントにて教えていただきました!ありがとうございます:relaxed:
HTMLの属性の値を囲うクォーテーションは、条件を満たせば省略することができます。

name=viewportに注目
<meta name=viewport content="initial-scale=1">

[条件] 値に < > ' " = ` が含まれていない
なんでバッククォート?
IEでバッククオートを区切りに使えてしまうためらしいです。
これも@jkr_2255さんに教えていただきました。IEェ

あとは改行を消したらminify完了!

画像を最適化する

「ていうか普通のラスター使うのやめよう!」となってページから取り除きましたが、一応書いておきます。
GuetzliやMozjpegなどのエンコーダを使います。
見た目にほぼ影響を与えず、画像サイズをごそっと小さくできるかもしれません。
先人がとても良いまとめをしてくださっていたので、共有です。
GuetzliとMozjpegは、どっちが高性能か。

ぼかし画像等は極小サイズで用意して引き伸ばして使う

4x4とかの極小サイズ画像を引き伸ばして使います。
少しぼかすとそれっぽくなるかも

filter: blur(3px);

imgに下記のスタイルを指定すると、ぼかされずにピクセルを保ったまま拡大してくれます。すごいね

image-rendering: pixelated;

私が使ってるのこれ → l.gif

アイコンはSVGで描く

Webページ表示速度において足を引っ張りがちなラスター画像を、ベクター画像に置き換えてみましょう。
SVGでもコードを短く書くことを意識すると、びっくりな軽さになります。
このVueアイコンは167バイトです! やったね:)
(htmlに埋め込む場合はxmlnsが不要なので132バイト!)

Vueのロゴ

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0,0,40,35">
  <path d="M8,0h8l4,7l4-7h8L20,21" fill="#35495d"/>
  <path d="M0,0h8l12,21L32,0h8L20,35" fill="#41b883"/>
</svg>

そこのお前!ラスター画像に含まれるデータ量はベクター画像N枚分だぜ!

この記事が神でした
精度を保ってSVGを1バイトでも小さくする

圧縮して配信する

gz形式で配信することによってファイルサイズを抑えます。
gzipコマンドでgz形式に変換できます。

gzip -c 対象ファイル > 保存ファイル

このまま配置しても正しく読み込んでくれない(と思う)ので、メタデータを設定します。
(以下はAWS S3での設定です)
S3でのメタデータ設定。Content-Encodingをgzipに、Content-Typeをtext/htmlに設定している。

アップするたびに設定するのめんどくさい...
CLI使ったら自動化できるかな?

gzipの他に、高圧縮が可能なZopfliが存在するようです。
Zopfliで高圧縮gzip・PNGほか
@matyapiro31 さんにコメントにて教えていただきました!ありがとうございます:muscle:

CDNを使う

今回はAWSのS3とCloudFrontの組み合わせを使いました。
最も効果があったと思われる点ですが、手順を説明すると非常に長くなってしまうため割愛します:rolling_eyes:
http/https2もCloudFrontで設定しています。
(リクエスト1回だけなので、一番のメリットである並列リクエストの恩恵は受けられていません)

CDNもパフォーマンス比較してみて、これ!ってところを見つけるといいかもです。
CDNPerfで比較できます。
https://www.cdnperf.com/

なんだか日ノ本の外では動的な?マルチCDN?が芽を出してるとかなんとか。
私が知らないだけで日本でも流行ってるのかもしれないですが:flag_jp:

おわりの言葉

という感じで、惜しくもまばたき*には負けてしまいましたが、想定していたよりも簡単に高速なWebページを作ることができました。
そろそろツイフィールから乗り換えてみようかなって方は是非試してみてください:wave:

*1回のまばたきの速さは平均で100 - 150ミリ秒だと言われている。Wikipedia | まばたき

Webフロントエンド表示速度、最速化手法まとめ
↑参考になりました〜!

[雑感]
大洗女子の制服とVue、似過ぎ:thinking: