gulpで画像の最適化

完全に自己満足かもしれませんが、以下の理由で画像の最適化に取り組みました。

  • Google PageSpeed Insightsで毎回画像サイズが最適化されていないと毎回怒られる
  • 画像ファイルのサイズが無駄に大きいため、iPhoneからアクセスした時に余計なパケットを消費するのが悔しい

画像の最適化を全て手動でやると挫折してしまうので、タスクランナーであるgulpで自動化を行いました。

やりたいこと

  1. Markdown形式のファイルに対して画像ファイルをドラッグ&ドロップで画像リンク生成
  2. 画像ファイルをレスポンス対応(srcsets)させるため、数種類のサイズにリサイズ
  3. リサイズ後の画像ファイルを最適化(圧縮)

「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.srcbaseというオプションがあり、これを指定するとディレクトリ構造を維持して出力することができます。

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
  });
});

まとめ

画像の最適化は、手動だとめんどくさくてなかなか出来ないが、一度自動化してしまえば後は楽です。 少しずつメンテナンスを加えて使い勝手を良くしていきたいと思います。

参考

Backlinks

静的サイトジェネレータHugo
Hugo入門 静的サイトジェネレータ「Hugo」でシンプルブログサイトを構築する 静的サイトジェネレータ「Hugo」インストール 静的サイトジェネレータ「Hugo」〜公開方法〜 サイト構築 Hugoのテーマでsubmoduleを使う方法 HugoでのシンタックスハイライトにPython Pygmentsが不要となった HugoのRelated Contentを利用して関連記事を表示する gulpで画像の最適化 Hugoソースコードリーディング〜Taxonomy〜 Render Hooks for Code Blocksを利用してコードブロックにファイル名を表示する Hugoでブログカードを作成する(resources.GetRemote利用) Templates 【Hugo】Partial Templateでは複数returnを記述する早期Returnを使えない 【Hugo】images.TextでOGP画像を生成する Shortcodes Hugo Shortcodesの作り方 HugoのShortcodesを利用してAmazon紹介リンクタグを作成 HugoでAMP対応のブログカードを作る AMP対応 AMP向けのミニマルCSSフレームワーク「1BX」をHugoに導入した AMPページの最適化〜ぼくのAMPサイトがこんなに遅い訳がない〜 AMP OptimizerによるAMPのさらなる最適化 AMP Service WorkerでPrefetch Linksを実現する Data Driven Content Hugoで人気記事を表示するためJSONを返すAPIサーバを作りData-driven Contentを試してみた Tailwind CSS HugoでTailwindCSSを利用しAMP Validなページを生成する ビルド npm-run-allでローカルAPI serverとHugo serverを同時に実行する GitHub Actionsのスケジューラ実行を利用して定期的にビルドする Circle CIでHugoのビルド・デプロイを実行する コンテンツ作成 Git pre-commitフックでFrontmatterの「更新日時」を自動更新する Hugoでブログ記事一覧ページ(ブログアーカイブページ)を作成する 移行 はてなダイアリーからはてなブログ経由で独自ドメインのブログに記事を移行しました JekyllからHugoへの移行ポイント Hugoで生成した静的サイトのホスト先をさくらVPSからNetlifyに変更する 書籍
2017-12-31