現場で使えるgulp入門 第1回 gulpとは何か

さまざまな作業を自動化するビルドシステムgulpの基礎を解説します。第1回目は、gulpとは何か? 自動化のメリットはどこにあるのか概観。インストールから簡単なタスクを走らせてみます。

発行

著者 中島 直博 フロントエンド・エンジニア
現場で使えるgulp入門 シリーズの記事一覧

はじめに

このシリーズでは、JavaScriptで書かれたビルドシステムであるgulp(ガルプ)について、導入から使い方など、基本的な部分を解説します。

なお、記事執筆時点のgulpのバージョンは3.8.7です。

第1回目では、まず、なぜgulpのようなツールが必要なのか、ツールの背景に触れます。さらにgulpの概要と、環境設定を中心に解説します。

gulpとは

gulpはNode.jsをベースとしたビルドシステムヘルパーです。以前CodeGridでも紹介したGruntと似た目的を持って作られたツールで、gulpを使えばさまざまな作業を自動化することができます。gulpの一番の特徴はサイトのトップページで「ストリーミングビルドシステム」と自ら名乗っているように、ファイルの処理をストリームで行うというところです。この特徴によって複雑なタスクも細かくカスタマイズして書くことができます。ストリームがどのようなものかは、後述します。

ビルドシステムヘルパーとタスクランナーの違い

先に登場したタスクランナーのGrunt、今回紹介するビルドシステムヘルパーのgulp、両者の目的は似ています。どちらも、いろいろな機能(プラグイン)を使い、目的とする成果物を求める一連の処理(タスク)を実行しますが、そのアプローチは少々異なります。

Gruntの場合、タスク=プラグインといった感じに、その単一のタスク(プラグイン)を実行させるのが主な役割です。単一のタスクをうまいこと組み合わせて実行することで、ビルドという大きい目標に辿り着くというアプローチです。

gulpの場合、プラグインはあくまでも入力に対して処理を行うためのものです。gulpのタスクはGruntでいうところのビルドに近いものです。タスクの中でいろいろなプラグインを組み合わせることで、タスク=ビルドを行うといったアプローチを取っています。プラグインを容易に組み合わせられるので、柔軟なタスクを作成できるとともに、タスク同士の依存関係を極力減らすことが可能です。

ストリームによる処理の利点

gulpはファイルをストリームとして扱いながら処理を行います。ストリームがどういったものかイメージしやすいように、gulpにおけるタスクの例を見てみましょう。次のタスクは.scss形式のファイルに対して処理を行うものです。

gulp.task('sass', function() {
  var stream = gulp.src('sass/*.scss')
    .pipe(sass())
    .pipe(autoprefixer())
    .pipe(minify())
    .pipe(gulp.dest('css'));
  return stream;
});

sassフォルダにある.scss形式のファイルに対してコンパイル>プレフィックス付与>圧縮と、流れるように処理を行い、最後にgulp.dest()というメソッドによってファイルを書き出します。

各処理を実行した結果を.pipe()によって次の処理に渡すことで、複数の処理を簡潔にまとめることが可能です。それぞれの処理の間に新たに処理を追加したい、といった場合には、.pipe()を増やすだけです。タスクが何をするのか、わかりやすく直感的に書くことができます。

また、.pipe()はそれぞれの処理の間でファイルの読み書きを行わないので、I/Oによる不要な待ち時間が発生しないのも強みです。

手続き的な記述と宣言的な記述の違い

GruntではタスクをJSON形式で宣言的に記述していきます。宣言的な記述はタスクの内容がパッと見でわかりやすい反面、タスク同士を組み合わせるのが難しいです。タスクが増えていくと、それぞれの関連性などを把握しきれなくなります。

一方、gulpでは処理したファイルをストリームによって次の処理に渡すことで、手続き的に記述することができます。「アレをしてからコレをする」というタスクをわかりやすく、より簡潔に書くことができます。gulpのAPIはたいていコールバック関数を取れるようになっているので、タスク実行後に何かする、といったものもわかりやすく書くことができます。gulpではタスクと処理を行う機能とが分離できることで、タスクの持っている役割をより明確にすることができます。

自動化がなぜ必要か

例えば、SassやSylusなどのCSSプリプロセッサを使うときや、CoffeeScriptやTypeScriptといったAltJSを使うときなど、コンパイルという作業が毎回必要になります。コンパイルだけならば各種のコンパイラに付いているwatch機能を利用して変更を監視することはできます。が、コンパイル後に「圧縮・結合して、ブラウザの自動更新も行いたい」と思った場合はどうでしょう。これらの作業を毎回手動で実行するのは手間がかかります。これらの作業をgulpのタスクにし、自動化することで作業を効率的に進めることができるでしょう。

作業の自動化以外にも、ビルドシステムを導入することで得られるものがあります。それは最終的な成果物の質を一定に保つということです。特に、複数人で製作を行うプロジェクトにビルドシステムやタスクランナーを導入すれば、この恩恵を多く受けることができるでしょう。

例えば、最終的な成果物を得るためには、先に挙げたCSSやJSのコンパイルや圧縮・結合といった作業のほかにも、プロジェクトごとに合わせた作業が必要になると思います。これらの作業を特定の誰か、もしくは毎回違う誰かが行う場合、環境や手順の違いによって成果物にバラつきが出てしまうかもしれません。また、何かをし忘れるといったミスも起こるかもしれません。gulpやGruntといったシステムを導入し、これらの作業を自動化して共有することは、最終的なアウトプットの質を保つ助けになるでしょう。

実行環境の構築とgulpのインストール - Node.js/gulp

gulpはNode.jsのパッケージ(ライブラリ)のひとつです。gulpを利用するにはNode.jsのインストールが必要です。

Node.jsをインストールする

Node.jsをインストールしていない方は、次のサイトからインストーラをダウンロードし、実行してください。インストールするとnodeコマンドとnpmコマンドが利用できるようになります。

すでにNode.jsをインストールしている場合でも、この記事で紹介していくプラグインを使うために0.10以上が必要になりますので、コマンドラインからnode -vを実行し、現在インストールされているバージョンをチェックしてください。

npmによるインストール

Node.jsではnpmによってパッケージのインストールを行います。gulp自体のインストールだけでなく、gulpで利用するプラグインについても同様にnpmコマンドでインストールすることになります。

npmでパッケージをインストールする際には、次のコマンドを実行します。実行するとnode_modulesフォルダが作られ、そこにパッケージがインストールされます。

$ npm install パッケージ名

ローカルインストールとグローバルインストール

npmではパッケージをローカルとグローバルのどちらにインストールするか、選ぶことができます。ローカルにインストールしたパッケージは、そのプロジェクトのフォルダ内でのみ利用できます。グローバルにインストールした場合は、そのマシン上のどこからでも利用できるようになります。デフォルトでは、ローカルにパッケージがインストールされるようになっています。グローバルにインストールしたい場合には-gオプションを付け、次のように実行します。

$ npm install -g パッケージ名

プロジェクトごとに利用するパッケージの管理

npmにはインストールしたパッケージを管理する機能も用意されています。パッケージを管理するためにはまずpackage.jsonというファイルを作成する必要があります。package.jsonはJSONファイルとして解釈できる必要があるので、最低限{}が書かれている必要があります。

package.jsonは直接作成する以外にも、npm initというコマンドを実行すると、対話形式でプロジェクトの名前や、作成者などの情報を決めた上でpackage.jsonを書き出してくれます。

installコマンドのオプション

package.jsonでインストールするパッケージの管理をするにはnpm installを実行する際に--saveまたは--save-devというオプションを付けます。--saveは作成しているプログラム自体にそのパッケージが必要なときに付けます。gulpやgulpで使うプラグインなど、開発時だけ必要となるものには--save-devを付けるとよいでしょう。

$ npm intsall --save-dev パッケージ名

package.jsonで利用するパッケージを管理しておくことで、ライブラリを直接コピーせずに、使うライブラリの情報だけを共有することができます。プロジェクトの環境を共有する際、共有された側は最初にnpm installを実行すれば、プロジェクトに必要なパッケージをインストールすることができるのです。

コラム:npmコマンドにはショートカットがある

npmではinstall--save-devなどを短く表記するためのショートカットが用意されています。installiと一文字で表記することができてnpm iと短縮できます。--save-dev-D--save-Sと短縮できます。合わせると以下のように短縮できて手間をかなり減らすことができます。

$ npm i -D パッケージ名

npmにはほかにもいろいろなショートカットや機能が用意されていますので積極的に活用していきましょう。

gulpのインストール:package.jsonを作成する

gulp自体も管理するパッケージに含めたいので、まずpackage.jsonを作成します。新規テキストファイルを作成して下記の内容を記述後、package.jsonという名前で保存してください。

{}

gulpのインストール:npmでgulpをインストールする

gulpのインストールは通常ですとローカルとグローバルの両方にインストールする必要があります。グローバルにインストールされたgulpは、ローカルにインストールしたgulpを実行するのが役割です。

ローカルにインストールしたgulpを実行する仕組みにすることで、プロジェクトによって使用するgulpのバージョンが異なる場合でも、無理にgulpのバージョンを合わせることなく、タスクを実行できるようになっています。

下記の2つのコマンドを実行してインストールします。

$ npm install -g gulp
$ npm install --save-dev gulp

コマンド実行後、インストールが正しく完了していることを確認するために、次のコマンドを実行します。

$ gulp -v

コマンド実行後に以下のような結果がコンソールに表示されればインストール完了です。[ ]内は実行時の時間を表しています。

$ gulp -v
[03:21:39] CLI version 3.8.7
[03:21:39] Local version 3.8.7

gulpのバージョン管理

glupのバージョンを固定せずにnpm installした際には、インストールするパッケージの最新のバージョンがインストールされます。これによってローカルとグローバルのgulpのバージョンに相違が出てしまうかもしれません。グローバルにインストールしたパッケージは適宜アップデートする必要があります。

もしローカルとグローバルのバージョンの管理が面倒だと思う方は、npm runなどを使ってローカルにあるgulpを実行するように設定しておくとよいでしょう。

タスクを書いてみる

インストールが完了したら簡単なタスクを書いてみましょう。gulpのタスクはgulpfileに書いていきます。まずgulpfile.jsという名前で新規ファイルを作成しましょう。作成したら下記のサンプルコードを記述して保存してください。

var gulp = require('gulp');

gulp.task('hello', function() {
  console.log('Hello gulp!');
});

gulp.task('default', ['hello']);

gulp.taskに渡している第一引数helloがタスク名です。helloはコマンドライン上にHello gulp!と表示するだけのタスクです。

defaultタスクは、gulpコマンドを実行する際に、タスク名を指定しなかったときに実行されるタスクです。gulp.task('default', ['hello']);とした場合、`hello`タスクが実行されます。上記コードの保存後、コマンドラインからgulpコマンドを実行して、次のような結果が得られれば成功です。

$ gulp
[04:22:27] Using gulpfile /usr/local/work/genkou/gulp/demo/gulpfile.js
[04:22:27] Starting 'hello'...
Hello gulp!
[04:22:27] Finished 'hello' after 73 μs
[04:22:27] Starting 'default'...
[04:22:27] Finished 'default' after 4.24 μs

コラム:gulpfileはCoffeeScriptでも書ける

タスクを記述するgulpfileCoffeeScriptを使って書くこともできます。少し前まではgulpコマンド実行時にオプションを指定しなければなりませんでしたが、バージョン3.7からはgulpfile.coffeeをデフォルトで読み込んでくれるようになりました。CoffeeScriptで書く場合にはcoffee-scriptのパッケージが必要になるので、下記コマンドでパッケージをインストールしましょう。

npm install --save-dev coffee-script

おわりに

今回はgulpの概要と環境構築、簡単なタスクの書き方を解説しました。次回はgulpのプラグインを利用したタスクの書き方を解説していきます。