これからはじめるGulp #15:gulp-responsiveプラグインを使ったレスポンシブイメージ作成の自動化

2014.12.15

はじめに

前回のこれからはじめるGulp(14):gulp-cachedプラグインで変更されたSCSSファイルだけを処理させるでgulp-cachedプラグインを使ったSassタスクの効率化を試しました。今回はレスポンシブイメージを作るためのプラグインgulp-responsiveを試してみたいと思います。

gulp-responsiveとは

gulp-responsivelibvipsライブラリを使ったNode.js向け画像処理モジュール「Sharp」をラップしたgulpプラグインです。

gulp-responsiveに必要なソフトウェアとライブラリ

gulp-responsiveを使うにはXQuartzとSharpライブラリが必要です。

gulp-responsiveを使えるようにするための準備

必要なソフトウェアとライブラリをインストールします。

XQuartzのインストール

XQuartzはインストーラーを使ってインストールします。 インストーラーの案内に従ってインストールするだけなのでここでは説明を省きます。

libvipsのインストール

libvipsはhomebrewからインストールします。色々とライブラリをインストールするので少し時間がかかります。

$ brew install homebrew/science/vips --with-webp --with-graphicsmagick
==> Installing vips from homebrew/homebrew-science
==> Installing dependencies for vips: readline, sqlite, gdbm, openssl, python, libpng, freetype, fontconfig, gettext, libffi, glib, orc, libgsf, libtiff,
==> Installing vips dependency: readline
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/readline-6.3.8.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring readline-6.3.8.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X provides similar software, and installing this software in
parallel can cause all kinds of trouble.

OS X provides the BSD libedit library, which shadows libreadline.
In order to prevent conflicts when programs look for libreadline we are
defaulting this GNU Readline installation to keg-only.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/readline/lib
    CPPFLAGS: -I/usr/local/opt/readline/include

==> Summary
  /usr/local/Cellar/readline/6.3.8: 40 files, 2.1M
==> Installing vips dependency: sqlite
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/sqlite-3.8.7.3.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring sqlite-3.8.7.3.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

OS X provides an older sqlite3.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/sqlite/lib
    CPPFLAGS: -I/usr/local/opt/sqlite/include

==> Summary
  /usr/local/Cellar/sqlite/3.8.7.3: 9 files, 2.1M
==> Installing vips dependency: gdbm
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gdbm-1.11.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring gdbm-1.11.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/gdbm/1.11: 17 files, 532K
==> Installing vips dependency: openssl
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/openssl-1.0.1j_1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring openssl-1.0.1j_1.yosemite.bottle.tar.gz
==> Caveats
A CA file has been bootstrapped using certificates from the system
keychain. To add additional certificates, place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include

==> Summary
  /usr/local/Cellar/openssl/1.0.1j_1: 431 files, 15M
==> Installing vips dependency: python
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/python-2.7.8_2.yosemite.bottle.3.tar.gz
######################################################################## 100.0%
==> Pouring python-2.7.8_2.yosemite.bottle.3.tar.gz
==> Caveats
Setuptools and Pip have been installed. To update them
  pip install --upgrade setuptools
  pip install --upgrade pip

You can install Python packages with
  pip install <package>

They will install into the site-package directory
  /usr/local/lib/python2.7/site-packages

See: https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Homebrew-and-Python.md

.app bundles were installed.
Run `brew linkapps` to symlink these to /Applications.
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/pip
Target /usr/local/bin/pip
already exists. You may want to remove it:
  rm /usr/local/bin/pip

To force the link and overwrite all conflicting files:
  brew link --overwrite python

To list all files that would be deleted:
  brew link --overwrite --dry-run python

Possible conflicting files are:
/usr/local/bin/pip
/usr/local/bin/pip2
/usr/local/bin/pip2.7
==> /usr/local/Cellar/python/2.7.8_2/bin/python -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python/2.7.8_2/bin --ins
==> /usr/local/Cellar/python/2.7.8_2/bin/python -s setup.py --no-user-cfg install --force --verbose --install-scripts=/usr/local/Cellar/python/2.7.8_2/bin --ins
==> Summary
  /usr/local/Cellar/python/2.7.8_2: 4776 files, 76M
==> Installing vips dependency: libpng
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libpng-1.6.15.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libpng-1.6.15.yosemite.bottle.tar.gz
  /usr/local/Cellar/libpng/1.6.15: 17 files, 1.3M
==> Installing vips dependency: freetype
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/freetype-2.5.4.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring freetype-2.5.4.yosemite.bottle.tar.gz
  /usr/local/Cellar/freetype/2.5.4: 60 files, 2.6M
==> Installing vips dependency: fontconfig
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/fontconfig-2.11.1.yosemite.bottle.3.tar.gz
######################################################################## 100.0%
==> Pouring fontconfig-2.11.1.yosemite.bottle.3.tar.gz
==> /usr/local/Cellar/fontconfig/2.11.1/bin/fc-cache -frv
  /usr/local/Cellar/fontconfig/2.11.1: 448 files, 3.6M
==> Installing vips dependency: gettext
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gettext-0.19.3_1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring gettext-0.19.3_1.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X provides similar software, and installing this software in
parallel can cause all kinds of trouble.

OS X provides the BSD gettext library and some software gets confused if both are in the library path.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/gettext/lib
    CPPFLAGS: -I/usr/local/opt/gettext/include

==> Summary
  /usr/local/Cellar/gettext/0.19.3_1: 1920 files, 21M
==> Installing vips dependency: libffi
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libffi-3.0.13.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libffi-3.0.13.yosemite.bottle.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

Some formulae require a newer version of libffi.

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/libffi/lib

==> Summary
  /usr/local/Cellar/libffi/3.0.13: 14 files, 412K
==> Installing vips dependency: glib
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/glib-2.42.1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring glib-2.42.1.yosemite.bottle.tar.gz
  /usr/local/Cellar/glib/2.42.1: 410 files, 17M
==> Installing vips dependency: orc
==> Downloading http://gstreamer.freedesktop.org/src/orc/orc-0.4.22.tar.xz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/orc/0.4.22 --disable-gtk-doc
==> make install
  /usr/local/Cellar/orc/0.4.22: 82 files, 1.3M, built in 32 seconds
==> Installing vips dependency: libgsf
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libgsf-1.14.30.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring libgsf-1.14.30.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/libgsf/1.14.30: 148 files, 2.7M
==> Installing vips dependency: libtiff
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libtiff-4.0.3.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libtiff-4.0.3.yosemite.bottle.tar.gz
  /usr/local/Cellar/libtiff/4.0.3: 254 files, 3.8M
==> Installing vips dependency: fftw
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/fftw-3.3.4.yosemite.bottle.2.tar.gz
######################################################################## 100.0%
==> Pouring fftw-3.3.4.yosemite.bottle.2.tar.gz
  /usr/local/Cellar/fftw/3.3.4: 39 files, 11M
==> Installing vips dependency: little-cms
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/little-cms-1.19.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring little-cms-1.19.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/little-cms/1.19: 22 files, 856K
==> Installing vips dependency: pixman
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/pixman-0.32.6.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring pixman-0.32.6.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/pixman/0.32.6: 11 files, 1.4M
==> Installing vips dependency: cairo
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/cairo-1.14.0.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring cairo-1.14.0.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/cairo/1.14.0: 106 files, 6.4M
==> Installing vips dependency: icu4c
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/icu4c-54.1.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring icu4c-54.1.yosemite.bottle.1.tar.gz
==> Caveats
This formula is keg-only, which means it was not symlinked into /usr/local.

Mac OS X already provides this software and installing another version in
parallel can cause all kinds of trouble.

OS X provides libicucore.dylib (but nothing else).

Generally there are no consequences of this for you. If you build your
own software and it requires this formula, you'll need to add to your
build variables:

    LDFLAGS:  -L/usr/local/opt/icu4c/lib
    CPPFLAGS: -I/usr/local/opt/icu4c/include

==> Summary
  /usr/local/Cellar/icu4c/54.1: 242 files, 65M
==> Installing vips dependency: harfbuzz
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/harfbuzz-0.9.35_1.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring harfbuzz-0.9.35_1.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/harfbuzz/0.9.35_1: 72 files, 2.9M
==> Installing vips dependency: gobject-introspection
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/gobject-introspection-1.42.0.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring gobject-introspection-1.42.0.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/gobject-introspection/1.42.0: 196 files, 10M
==> Installing vips dependency: pango
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/pango-1.36.8.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring pango-1.36.8.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/pango/1.36.8: 132 files, 4.8M
==> Installing vips dependency: libexif
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libexif-0.6.21.yosemite.bottle.1.tar.gz
######################################################################## 100.0%
==> Pouring libexif-0.6.21.yosemite.bottle.1.tar.gz
  /usr/local/Cellar/libexif/0.6.21: 29 files, 924K
==> Installing vips dependency: graphicsmagick
==> Downloading https://downloads.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.20/GraphicsMagick-1.3.20.tar.bz2
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/graphicsmagick/1.3.20 --enable-shared --disable-static --with-modules --disable-openmp --without-gslib --with-gs-font
==> make install
  /usr/local/Cellar/graphicsmagick/1.3.20: 472 files, 13M, built in 72 seconds
==> Installing vips dependency: webp
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/webp-0.4.2_1.yosemite.bottle.tar.gz
######################################################################## 100.0%
==> Pouring webp-0.4.2_1.yosemite.bottle.tar.gz
  /usr/local/Cellar/webp/0.4.2_1: 32 files, 1.8M
==> Installing vips
==> Downloading http://www.vips.ecs.soton.ac.uk/supported/7.40/vips-7.40.11.tar.gz
######################################################################## 100.0%
==> ./configure --prefix=/usr/local/Cellar/vips/7.40.11 --with-magick --with-magickpackage=GraphicsMagick
==> make check
==> make install
==> Caveats
Python modules have been installed and Homebrew's site-packages is not
in your Python sys.path, so you will not be able to import the modules
this formula installed. If you plan to develop with these modules,
please run:
  mkdir -p /Users/nonakaryuichi/Library/Python/2.7/lib/python/site-packages
  echo 'import site; site.addsitedir("/usr/local/lib/python2.7/site-packages")' >> /Users/nonakaryuichi/Library/Python/2.7/lib/python/site-packages/homebrew.pth
==> Summary
  /usr/local/Cellar/vips/7.40.11: 196 files, 13M, built in 117 seconds

gulp-responsiveのインストール

続いてgulp-responsiveをインストールします。

$ sudo npm install gulp-responsive --save-dev
Password:
/
> sharp@0.8.1 install /Users/nukos/Projects/test.io/vccw/www/wordpress/wp-content/themes/test.io/node_modules/gulp-responsive/node_modules/sharp
> node-gyp rebuild

  CXX(target) Release/obj.target/sharp/src/common.o
  CXX(target) Release/obj.target/sharp/src/utilities.o
  CXX(target) Release/obj.target/sharp/src/metadata.o
  CXX(target) Release/obj.target/sharp/src/resize.o
  CXX(target) Release/obj.target/sharp/src/sharp.o
  SOLINK_MODULE(target) Release/sharp.node
  SOLINK_MODULE(target) Release/sharp.node: Finished
├── async@0.9.0
├── rename@0.2.3
├── minimatch@1.0.0 (sigmund@1.0.0, lru-cache@2.5.0)
├── lodash@2.4.1
├── through2@0.6.3 (xtend@4.0.0, readable-stream@1.0.33)
└── sharp@0.8.1 (semver@4.1.0, nan@1.4.1, bluebird@2.3.11, color@0.7.3)

responsiveタスクを作る

オプションの指定はgulp-responsiveのドキュメントを参考に設定します。今回は試しにサンプルのPNG画像を横幅200pxに縮小してみます。

var gulp     = require('gulp');
var responsive = require('gulp-responsive');

var paths = {
  srcDir : 'assets/images/_src',
  dstDir : 'assets/images/_src'
}

gulp.task('responsive', function () {
  var srcGlob = paths.srcDir + '/orig/*.png';
  var dstGlob = paths.dstDir + '/2x';
  var responsiveOptions = [{
    name: '*.png',
    width: 200
  }];

  return gulp.src( srcGlob )
    .pipe(responsive( responsiveOptions )) //<-
    .pipe(gulp.dest( dstGlob ));
});

gulp-responsiveはGlobで対象とするファイルを制限するだけでなくオプションで複数のリサイズルールを指定します。上記のタスクではGlobにpaths.srcDir + '/orig/*.png';を指定していますがresponsiveOptionsにname: '*.png'という指定があります。これはStream中のファイルにnameに一致するファイルがあればwidth: 200の画像が作られます。複数指定する場合は以下のようになります。

  var responsiveOptions = [{
    name: '*.png',
    width: 200
  },
  {
    name: '*.png',
    width: 400
  }];

タスクを実行する

$ gulp responsive
[17:56:00] Using gulpfile ~/Projects/test.io/vccw/www/wordpress/wp-content/themes/test.io/gulpfile.js
[17:56:00] Starting 'responsive'...
[17:56:00] Finished 'responsive' after 83 ms

これで横幅200pxの画像が作られます。

gulp-imageminと連携する

gulp-imageminと連携してgulp-responsiveで作られた画像を最適化します。処理の流れとしてimage-optimタスクを実行するとimageminタスクが呼ばれ、imageminタスクを実行するためにresponsiveタスクを先に実行するようタスクを作ります。

image-optimタスク

gulp.task('image-optim', ['imagemin']);

imageminタスク

['responsive']を設定します。

gulp.task( 'imagemin', ['responsive'], function(){
  var srcGlob = paths.srcDir + '/**/*.+(jpg|jpeg|png|gif|svg)';
...

image-optimタスクを実行する

image-optimタスクを実行して、処理を確認します。

[18:06:18] Using gulpfile ~/Projects/test.io/vccw/www/wordpress/wp-content/themes/test.io/gulpfile.js
[18:06:18] Starting 'responsive'...
[18:06:18] Finished 'responsive' after 78 ms
[18:06:18] Starting 'imagemin'...
[18:06:18] Finished 'imagemin' after 3.39 ms
[18:06:18] Starting 'image-optim'...
[18:06:18] Finished 'image-optim' after 6.22 μs
[18:06:20] gulp-imagemin: Minified 3 images (saved 9.84 kB - 31.6%)

思惑通りresponsiveタスクで指定のサイズで画像が作られimageminタスクで画像が最適化されました。 インストールするソフトやライブラリが多いため気軽に使える感じではありませんがレスポンシブ用の画像を簡単に用意できるようになります。次回はgulp-image-resizeプラグインを使った画像のリサイズを試してみたいと思います。

この記事はこれからはじめるGulp(15):gulp-responsiveプラグインを使ったレスポンシブイメージ作成の自動化の転載です。