gulpで画像の最適化
更新日:2021.01.30
作成日:2017.04.09
完全に自己満足かもしれませんが、以下の理由で画像の最適化に取り組みました。
- Google PageSpeed Insightsで毎回画像サイズが最適化されていないと毎回怒られる
- 画像ファイルのサイズが無駄に大きいため、iPhoneからアクセスした時に余計なパケットを消費するのが悔しい
画像の最適化を全て手動でやると挫折してしまうので、タスクランナーであるgulpで自動化を行いました。
やりたいこと
- Markdown形式のファイルに対して画像ファイルをドラッグ&ドロップで画像リンク生成
- 画像ファイルをレスポンス対応(srcsets)させるため、数種類のサイズにリサイズ
- リサイズ後の画像ファイルを最適化(圧縮)
「1.」のドラッグ&ドロップで画像リンク生成は、エディタのプラグインで実現することにし、「2.」「3.」をgulpのタスクで実現を目指しました。
画像のresponsive対応
なんとなく、320px,640px,1280px,オリジナルファイルという4種類にリサイズするようにしてみました。
gulp.task('responsive', function(){
  return gulp.src(['src/images/**/*.jpg','src/images/**/*.png'], { base: 'src'})
        .pipe(responsive({
          // Resize all JPG images to three different sizes: 200, 500, and 630 pixels
          'images/**/*.jpg': [{
            width: 320,
            rename: { suffix: '-320x' },
          }, {
            width: 640,
            rename: { suffix: '-640x' },
          }, {
            width: 1280,
            rename: { suffix: '-1280x' },
          }, {
            // Compress, strip metadata, and rename original image
            rename: { suffix: '-o' },
          }],
          // Resize all PNG images to be retina ready
          'images/**/*.png': [{
            width: 250,
          }, {
            width: 250 * 2,
            rename: { suffix: '@2x' },
          }],
        }, {
          // Global configuration for all images
          // The output quality for JPEG, WebP and TIFF output formats
          quality: 70,
          // Use progressive (interlace) scan for JPEG and PNG output
          progressive: true,
          // Strip all metadata
          withMetadata: false,
      }))
      .pipe(gulp.dest('static/'));
});gulp-responsive/multiple-resolutions.md at master · mahnunchik/gulp-responsive
Tips 出力処理
gulp.srcにbaseというオプションがあり、これを指定するとディレクトリ構造を維持して出力することができます。
var gulp = require('gulp');
gulp.task('copy', function() {
    return gulp.src(
        ['src/images/**/.jpg', 'src/images/**/.png'],
        { base: 'src' }
    )
    .pipe(gulp.dest('static/'));
} );画像の最適化
画像の最適化には、gulp-imageminを利用しました。
var imagemin = require('gulp-imagemin');
gulp.task('imagemin', function() {
  return gulp.src('src/images/**/*.jpg')
      .pipe(imagemin())
      .pipe(gulp.dest('static/'));
});組み合わせた結果
Hugoのルートディレクトリでgulpを叩けば、jpg, pngを監視し、ファイルが追加されれば、画像フォルダに変換後の画像が作成されるようになります。
gulp.task('default', function(cb) {
  var watcher = gulp.watch('src/images/**/*.{jpg,png}');
  watcher.on('change', function(event) {
    console.log(event);
    console.log('File ' + event.path + ' was ' + event.type + ', running tasks...');
    const extname = event.path.split(".").pop(); // TODO error handle
    console.log(extname);
    if (extname === "jpg") {
      gulp.src(event.path, { base: 'src'})
          .pipe(responsive({
            // Resize all JPG images to three different sizes: 200, 500, and 630 pixels
            'images/**/*.jpg': [{
              width: 640,
            }, {
              width: 64,
              rename: { suffix: '-64x'},
            }, {
              width: 320,
              rename: { suffix: '-320x' },
            }, {
              width: 640,
              rename: { suffix: '-640x' },
            }, {
              width: 1280,
              rename: { suffix: '-1280x' },
            }, {
              // Compress, strip metadata, and rename original image
              rename: { suffix: '-o' },
            }],
          }))
        .pipe(imagemin())
        .pipe(gulp.dest('static/'));
    } else if (extname === "png") {
      gulp.src(event.path, { base: 'src'})
          .pipe(responsive({
            // Resize all PNG images to be retina ready TODO
            'images/**/*.png': [{
              width: 64,
              rename: { suffix: '-64x'}
            }, {
              width: 640,
            }, {
              width: 640 * 2,
              rename: { suffix: '@2x' },
            }],
          }, {
            // Global configuration for all images
            // The output quality for JPEG, WebP and TIFF output formats
            quality: 70,
            // Use progressive (interlace) scan for JPEG and PNG output
            progressive: true,
            // Strip all metadata
            withMetadata: false,
        }))
        .pipe(imagemin())
        .pipe(gulp.dest('static/'));
    } else {
      console.log("not jpg or png");
    }
  });
  // hugo
  exec('hugo server -t hugo-zen', function(err, stdout, stderr) {
    console.log(stdout);
    console.log(stderr);
    if (err) return cb(err); // return error
    cb(); // finished task
  });
});まとめ
画像の最適化は、手動だとめんどくさくてなかなか出来ないが、一度自動化してしまえば後は楽です。 少しずつメンテナンスを加えて使い勝手を良くしていきたいと思います。
参考
- gulp でディレクトリ構造を維持したコピー – アカベコマイリ
- Gulpでディレクトリ構造を維持して出力する方法 | Glatch(グラッチ) – 夫婦で活動するフリーランスWeb制作ユニット
- Gruntとgulp.jsでサイトパフォーマンスを向上させる - ワザノバ | wazanova
- これからはじめるGulp #12:gulp-imageminプラグインを使ったJPEG,PNG,GIF,SVGの最適化 | Developers.IO
- レスポンシブイメージで画像の表示を最適化 〜CSSもJSもいらないHTML 5.1の新機能 - ICS MEDIA
- gulpで画像のロスレス圧縮を自動化する - satoyan419.com
- Gulpを使って特定のファイルが変更されたら自動的にタスクを実行する方法 | 今村だけがよくわかるブログ
- HugoとGulpを共存させて、ブランドデザインを刷新した | Timegraphy
- 【追記あり】Gulpを利用して画像をロスレス圧縮する - takedajs ログ
- srcset属性について - Qiita
- scalableminds/gulp-image-resize: Resizing images made easy - thanks to imagemagick.
Related contents

TECH
2017.12.22
はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました

TECH
2017.10.14
HugoでのシンタックスハイライトにPython Pygmentsが不要となった

TECH
2017.10.07
HugoのRelated Contentを利用して関連記事を表示する

TECH
2017.08.31
Hugo Shortcodesの作り方

TECH
2017.03.19
Hugoで生成した静的サイトのホスト先をさくらVPSからNetlifyに変更する

TECH
2017.02.25
HugoのMarkdownでtarget='_blank'を実現する方法

TECH
2017.02.18
HugoのShortcodesを利用してAmazon紹介リンクタグを作成

TECH
2017.01.14
CircleCIでMeCabを利用してHugoビルドする
