Webサイト最適化に関する初心者のガイド

ホームページの高速化は至上命題です。
ということで以下は[A beginner's guide to website optimization](https://medium.freecodecamp.org/a-beginners-guide-to-website-optimization-2185edca0b72)という記事の日本語訳です。

[彼の作ったサイト](https://www.hasslefreebeats.com/)はGoogle PageSpeed Toolsで99点を取ったそうです。
一時期流行った[dev.to](https://dev.to/)、[阿部 寛のホームページ](http://abehiroshi.la.coocan.jp/)も共に99点なので、それらと同レベルの速度です。
いったいどのような技術を使ったのでしょうか。


# A beginner’s guide to website optimization

私は初心者なのですが、Googleの最適化ランキングで100点中99点を取ることができました。
私にできるくらいだから、あなたにも当然できるでしょう。

証拠をお見せしましょう。
Googleの[PageSpeed Insights](https://developers.google.com/speed/pagespeed/insights/)を開いて[hasslefreebeats](https://www.hasslefreebeats.com/)を入れてください。
ここは私がメンテを行っていて、最近になって最適化のために手を入れたWebサイトです。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/26088/36f0956d-6067-91d3-7fb3-102282a73397.png)

私はこの結果に対して誇りを持っていますが、実はつい数週間前までWebサイト最適化に関して全く何の知見も持っていなかったことを強調しておきます。
私が行ったことは、単にひたすらググっては試行錯誤を繰り返しただけということです。

私は決して専門家ではありませんが、あなたが以下のテクニックを活用すれば、めざましい結果がを得ることができると確信しています。

## Images

私は初心者Webデザイナーらしく、これまで画像について関心を払ったことがありませんでした。
高品質の画像をWebサイトに配置すればよりプロフェッショナルに見えるようになることは知っていましたが、ページの読み込み時間に悪影響を与えることについては考えていませんでした。

画像の最適化のために主に行ったことは、画像を圧縮することでした。

後から振り返ってみると、これは実に当然のことかもしれませんが、私にとってはそうではありませんでした。
従って貴方には役に立たない話かもしれません。

画像圧縮に使ったサービスは[Optimizilla](http://optimizilla.com/)で、使い方はとても簡単です。
画像をアップロードし、適切な圧縮レベルを選択し、圧縮された画像をダウンロードするだけです。

中にはサイズが70%以上減少した画像もありました。
そしてこれが、高速化への長い長い道のりの第一歩でした。

Optimizillaは画像圧縮の唯一の手段ではありません。
Macの[ImageOptim](https://imageoptim.com/mac)やWindowsの[FileOptimizer](https://sourceforge.net/projects/nikkhokkho/files/FileOptimizer/)など、スタンドアロンのOSSもあります。
ビルドツールでビルドするときに圧縮を行う[Gulp](https://www.npmjs.com/package/gulp-imagemin)や[Webpack](https://github.com/Klathmon/imagemin-webpack-plugin)のプラグインもあります。
画像圧縮をしてさえいれば、その手段はさして重要ではありません。
最小限の労力でパフォーマンスを向上させる方法を選びましょう。

場合によってはファイルフォーマットを調べる価値があるかもしれません。
一般的に、jpgはpngよりファイルサイズが小さくなります。
私がどちらを使うかの選択基準は、画像に透明度が必要かどうかです。
透明度が必要であればpngを使用し、そうでなければjpgを使っています。
両形式の長所と短所は、[こちら](https://www.digitaltrends.com/photography/jpeg-vs-png-photo-format/)でもっと深く掘り下げられています。

また、Googleはスイートでナイスなwebpフォーマットを出してきましたが、しかしこれらは未だ全てのブラウザでサポートされているわけではありません。
将来的にサポートが進めば別ですが、今のところwebpは採用しないことにしています。

私は画像を圧縮する以上のことは行いませんでしたが、さらに最適化を詰めたい場合は[素晴らしい記事](https://www.frontamentals.com/practical-guide-to-images)があります。

## Video

現在のプロジェクトで動画を使用していないため、あまり参考にならないと思いますが、軽く触れておきます。

動画については、プロに頼むような仕事のひとつだと思います。
Vimeoは動画配信に最適なプラットフォームを提供し、低速回線には画質を落とした動画を配信し、動画を圧縮することでパフォーマンスを改善します。

もしくはYoutubeで動画をホストし、[youtube-dl](https://rg3.github.io/youtube-dl/)でダウンロードし、自サイトのニーズに合わせて動画の設定を見直すこともできます。

その他の改善方法については、[Brightcove](https://www.brightcove.com/en/)や[Sprout](https://sproutvideo.com/)、[Wistia](https://wistia.com/)などを参照してください。

## Gzip

最初にWebサイトをデプロイしたとき、gzipが何のことなのか全くわかりませんでした。

簡単に言うと、gzipはファイル圧縮フォーマットで、そしてほとんどのブラウザが対応しています。
ユーザはgzip圧縮が起きているかどうかを知ることすらなく、全てがバックエンドで動作します。

対応方法はアプリをホストしているサーバによって異なりますが、アプリをデプロイする際にgzip圧縮するよう指定するのが簡単です。
ただ私はHerokuを使っていますが、Herokuはそのオプションに対応していません。

コードに明示的に[圧縮を指定するパッケージ](https://github.com/expressjs/compression)が存在します。
わずか数行のコードと引き替えに、gzip圧縮の恩恵を受けることができます。
このパッケージを利用して、私はJavaScriptとCSSのサイズを[75%減らす](https://codeburst.io/how-i-decreased-the-size-of-my-heroku-app-by-75-1a4cf329b0ab)ことに成功しました。

使用しているホスティングサービスがgzipオプションを提供しているか確認してみてください。
対応していない場合は、サーバ側コードにgzipを追加する方法を調べてください。

## Minifying

ミニファイとは、その機能に影響を与えずに、空白や不要な文字をコードから削除する機能です。
これにより、インターネットで送信するファイルサイズを小さくすることができます。
また、コードの難読化にも役立ちます。
クラッカーがセキュリティ上の問題点を発見するのをより困難にします。

最近では、WebpackやGulpなどのビルドプロセスの一環としてミニファイが行われることも普通になっています。
ただ、これらビルドツールを使うにあたっては学習コストが必要になります。
より簡単な代替案としては、[HTML-Minifier for HTML](https://github.com/kangax/html-minifier)、[CSSNano for CSS](https://github.com/ben-eb/cssnano)、[UglifyJS for Javascript](https://github.com/mishoo/UglifyJS2)などをお勧めします。

## Browser-Caching

静的ファイルをブラウザキャッシュに保存することは、特に一人が複数回アクセスするときには非常に効率的な高速化手段です。
HTTPレスポンスヘッダを正しく返していないせいで同じデータを毎回取りに行っているということを、Googleが教えてくれるまで私は全く気付くきませんでした。

ホームページを開くと、音楽プレーヤーに表示する楽曲情報を取得するリクエストが大量にやってきます。
楽曲リストはそう頻繁には更新されないので、ページの負荷を軽減するために前回訪問時と同じ楽曲を表示しても特に問題はありません。

パフォーマンス向上のため、次のコードをレスポンスオブジェクトに追加しました。

```js
	res.append("Cache-Control", "max-age=604800000");
	res.status(200).json(response);
```

ここで行ったのは、レスポンスにCache-Controlヘッダを追加したことです。
値をミリセカンドで指定することによって一週間はリソースを再ダウンロードする必要がなくなります。
ファイルをより頻繁に更新する場合は、`max-age`をより短くするといいと思います。

## Content Distribution Network

コンテンツデリバリネットワーク(CDN)は、コンテンツを世界中のユーザに対して物理的に近づけるネットワークです。
日本から大きな画像をロードする場合、サーバが東京にあるよりサーバがアメリカにあるほうが時間がかかります。

CDNは世界中至る所にプロキシサーバを配置し、エンドユーザがどこにいようとも一番近くのサーバからコンテンツを迅速に配信することができます。

実はCDNを使う前に上記目標を達成してしまいました。
従って特にCDNの話をする必要もなかったのですが、言及しておきたかったので話に出しました。
ワールドワイドなサービスを行う予定があるのであれば、CDNを使う必要があるでしょう。

有名どころとしては[CloudFront](https://aws.amazon.com/cloudfront/)や[CloudFlare](https://www.cloudflare.com/)があります。

## Miscellaneous

その他のヒントをいくつか紹介します。

・まず、ページをロードしたとき最初に表示される領域(Above the fold)を表示することに最適化し、体感的なパフォーマンスを向上させます。これの一般的な方法は、最初から表示されないところは後で描画する[Lazy loading](https://en.wikipedia.org/wiki/Lazy_loading)という技術です。

・HTMLレンダリングをAngularやReact等を使ってJavaScriptで行っているわけではないのであれば、scriptタグは最後尾の、body終了タグの直前に書いても問題ありません。ただし操作可能になるタイミングには影響することがあるので、あらゆる状況でお勧めできる技ではありません。

## In Conclusion

Webサイト最適化に関して、この記事は氷山の一角に過ぎません。
提供するサービスの種類とトラフィック量によって、様々な箇所でパフォーマンス上のボトルネックが発生する可能性があります。
もしかしたらもっと多くのサーバが必要になるかもしれません。
もっと多くのメモリが必要になるかもしれません。
三重forループが致命的問題を引き起こすかもしれません。

サイトのレスポンスを向上させるたったひとつの冴えたやりかた等は存在せず、最終的には測定値に基づいて最適化する適切な方法を探る必要があります。
最適化の必要がないところを最適化するような無駄はしないでください。
パフォーマンスを解析してボトルネックを探しだし、その部分を集中的に対策します。

-----

この記事が役に立つことを願っています。
最初にも言いましたが、この分野で私はまだまだ学ぶ必要があります。
ヒントやお勧めがあるなら、コメントで教えてください。

この記事が気に入ったら、こちらの記事も読んでみてください。
・[Tools I wish I had known about when I started coding](https://medium.freecodecamp.org/tools-i-wish-i-had-known-about-when-i-started-coding-57849efd9248)
・[Tools I wish I had known about when I started coding: Revisited](https://medium.freecodecamp.org/tools-i-wish-i-had-known-about-when-i-started-coding-revisited-ffb715ffd23f)

また[Twitterはこちら](https://twitter.com/marioahoyos)です。


# 感想

初心者向けガイドではなく、初心者によるガイドだった。
[この分野は素人なのですが案件](https://togetter.com/li/1085998)ではなく、本当の素人案件です。
特に一カ所、そのまま鵜呑みにすると致命的なところが存在します。
コメント欄で指摘されてて『すぐ直すお！』と言ってるのに未だになおってないです。

コメント欄ではさらに『今試してみたら[71点だったぞ](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.hasslefreebeats.com%2F&tab=mobile)どういうことだアァん？』と突っ込まれていて、理由としては『最適化後に機能を追加たら遅くなっちゃってたよHAHAHA』とのことでした。

そして2018/04/25現在では69点まで落ちています。
せっかく一時的に最適化したとしても、テストのサイクルが機能してないと全く意味がないね、という現実を見せてくれる結果でしたとさ。

それでも一時的とはいえ、CDNやらWPAやら何やらといった高等手段を使わずにそこまで点数を上げたことは立派と言っていいでしょう。
今後の成長を生暖かい目で見守っていきたいところです。

『I never stopped to consider the effects they would have on my page’s load time.』
ここたぶん本文中の訳とは逆の意味だと思うのだが、そうすると『As a beginner web-developer, images were not something I ever paid much mind to.』との繋がらなくなってよくわからなかった。