Edited at

Webパフォーマンス改善のために最低限やっておいた方が良い画像最適化 (フロントエンド)

More than 1 year has passed since last update.


はじめに

画像最適化(フロントエンド)に関して説明する機会があったため、それらに関してまとめました。


  • 画像最適化とは何か理解する。

  • なぜ画像最適化をするのか理解する。

  • とりあえず最低限やっておいた方が良い画像最適化手段を理解する。

ことを目的としています。

解説に利用している環境はGitHub上にありますので、クローンかダウンロードしてご利用ください。

hira777/image-optimization-minimum-kit


前提・注意点


  • 入門なので「とりあえず最低限やっておいた方が良い」レベルのことだけ記載しています。preload、LazyLoad や新しめな画像フォーマットなどに関しては触れておりませんので、初学者以外の方には物足りない内容になっています。

  • 画像圧縮に gulp を利用しますが、gulp や npm 自体の説明は省きます。


画像最適化とは

画像のファイルサイズや転送量をできる限り減らす(抑える)こと(簡潔に言ってしまえば)。


なぜ画像最適化をするのか


  • Webサイトのパフォーマンス改善につながるため

  • 最低限の画像最適化であれば、すぐに導入できるため


画像最適化のモチベーション

なぜ画像最適化をするのかはわかっても


  • どれぐらいの改善がされているのか(意味があるのか)わからない

  • 画像最適化を行っても評価される環境ではない

などの理由でなかなかやる気が出ないかもしれない。


どれぐらいの改善がされているのか(意味があるのか)わからない

ファイルサイズを削減しても、正しい計測をしないと何がどれぐらいの改善がされたのかわからない。

そのため、まずはファイルサイズの削減量を見ていけば良い。

ファイルサイズを50%削減すれば、純粋な転送量(コスト)を50%削減したことになるため、どれぐらいの改善がされたかは分かり易い。


画像最適化を行っても評価される環境ではない

前述のコストダウンのように、パフォーマンス改善が自社のビジネスに寄与することをアピールすれば、パフォーマンス改善の関心は高まるし、自身の取り組みが評価につながる可能性は大いにあると思う。

また最近は、最低限の画像最適化は「やった方が良い」ではなく「やることが当たり前」になりつつあるため、パートナーやクライアントに「なんで画像の最適化してないの?」と突っ込まれる可能性もある

後述するが、最低限の画像最適化は簡単にできるため、それすらやっていないのは印象が悪いし、信頼を失う可能性がある。そうなる前にやっておいた方が良い。


画像最適化を行う

画像最適化の手段は様々だが、今回は以下の手段で最適化を行う。


  • 適切なフォーマットで画像を書き出す

  • 画像を圧縮する


適切なフォーマットで画像を書き出す

画像によって適切なフォーマットが異なる。

例えば、写真などの色数が多い画像を jpg ではなく png で書き出してしまうと、見た目はほぼ同じでもサイズが数倍大きい画像が出力されてしまうため、理由がない限りは避ける

適切なフォーマットで書き出しができてないと、画像圧縮をしてもあまり効果がないため、フォーマットの選択は非常に重要である。


書き出しするフォーマットの基準

透過が必要なければ jpg、透過が必要であれば png を書き出す(最低限なので svg は除外)。

全ての画像にこの基準が当てはまるわけではないが、無駄に大きなサイズの画像を出力してしまうことは大体防げる(色数が少ない画像の場合、透過が必要なくても png を選択した方がファイルサイズを抑えられる時もある)。


デザインの都合上、写真を png(透過)で書き出す必要がありそうな場合はどうするのか

画像が斜めに切れているなどのデザインを対応する場合、写真を png(透過)で書き出す前に以下の手段も検討する。


  • デザイナーにデザインを変更できないか相談する。

  • svg を利用する(斜めの線を画像に重ねる)。


画像を圧縮する

以下のような画像圧縮手段がある。


  • ImageOptim を利用する

  • gulp で画像圧縮のタスクを実行する

今回は gulp を利用して画像圧縮をする。


gulp を利用した画像圧縮


  • gulp を利用した画像圧縮

  • 圧縮した画像と未圧縮画像の比較

ができる環境を用意したため、こちらを元に説明をしていく(以下のURLからクローンかダウンロードしてください)。

hira777/image-optimization-minimum-kit

ディレクトリ構成は以下の通り(一部省略)。

.

├── docs
│ ├── images
│ │ ├── compressed
│ │ │ ├── olives.jpg
│ │ │ ├── twitter.png
│ │ │ └── validate.svg
│ │ └── uncompressed
│ │ ├── olives.jpg
│ │ ├── twitter.png
│ │ └── validate.svg
│ └── index.html
├── gulpfile.js
├── package.json
└── src
└── images
└── compressed
├── olives.jpg
├── twitter.png
└── validate.svg

gulp を実行すると、src/image/compressed 配下の画像を圧縮してdocs/images/compressed配下に出力する仕組みになっている。

docs/index.htmlを開けば、圧縮した画像と未圧縮画像の比較ができる。


gulp を利用する準備

package.jsonがある階層で、以下のコマンドで必要なパッケージをインストールできる。

npm i


gulpfile.js

今回の gulp の設定は以下の通り。

const gulp = require('gulp');

const imagemin = require('gulp-imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const imageminPngquant = require('imagemin-pngquant');

gulp.task('default', () =>
gulp
.src('src/images/**/*')
.pipe(
imagemin([
imageminMozjpeg({
quality: 85,
}),
imageminPngquant({
quality: '60-80',
speed: 1,
}),
imagemin.svgo(),
imagemin.gifsicle(),
])
)
// imageminPngquant()で付与されたガンマ情報をimageminのoptipngで除去する
.pipe(imagemin())
.pipe(gulp.dest('docs/images'))
);

画像圧縮にはimagemin(画像圧縮ツール)を利用する。

imagemin-pngquantで png を圧縮すると、ガンマ情報が付与されて画像が少し暗くなってしまう。そのため、付与されたガンマ情報を除去するために、最後に.pipe(imagemin())を通している。

もし、明らかに画質が悪い画像が出力された場合、quality: 85などのqualityの値を調整する。


画像を圧縮する

以下のコマンドで圧縮された画像が出力される。

npm start

今回は jpg、png、svg を用意したが、それぞれの圧縮結果を以下の通り。

olives.jpg

圧縮前
圧縮後
削減サイズ
削減率

512 KB
344 KB
169 KB
32.9%

twitter.png

圧縮前
圧縮後
削減サイズ
削減率

298 KB
69 KB
228 KB
76.7%

validate.svg

圧縮前
圧縮後
削減サイズ
削減率

691 B
503B
188 B
27.2%

大幅なサイズ削減ができた。


圧縮した画像と未圧縮画像を比較してみる

docs/index.htmlか以下のページで今回利用している画像の比較ができる。

https://hira777.github.io/image-optimization-minimum-kit/

「 未圧縮」ボタンを押すと、 未圧縮の画像が表示され、「圧縮」ボタンを押すと圧縮された画像が表示される。

見比べてみると、ほとんど違いはわからない

ということで、過度な圧縮をしない限り、見た目にはほとんど影響ないことがわかる。


画像圧縮の注意点

圧縮後の画像を圧縮をすると、大幅な画質の劣化や作業者によって差分が出る可能性がある。

そのため、今回のサンプルのように圧縮前のオリジナルの画像は必ず残しておき、圧縮後の画像は圧縮しない方が良い。

また、 オリジナルの画像が必要になった際に、再度書き出す手間もなくなる。


終わり

画像最適化に関してより詳しく知りたい方は以下をご覧ください。