Skip to content →

gulpとかnpmのこととか

最近、Gruntからgulpに切り替え始めている人が増えている気がします。この数ヶ月でいろんなブログなんかでも導入記事が増えてるようですが、ひとつ言っておきますと「数ヶ月前の記事は鵜呑みにしてはいけない(というか、そのままだと動かないこともありうる)」かな〜、なんて。

あれがどうしたこうしたと質問を受けたりするんですが、いろんな人がはまってる原因はそこら辺にある気がしてならないのですよね。そんなわけで、ちょっとその辺の話をまとめておこうかと立ち上がった次第です。

※この記事は2014年7月30日時点のものですので、数ヶ月後にコレを読んでる方はご注意を。

アップデートの頻度が高いので…

こういったツールのアップデート頻度は高いものですが、gulpのバージョンアップ頻度もまぁまぁで現在の最新版は「v3.8.6」になっています。プラグインを使えばあらゆる機能を追加することができますが、そういったプラグインを使ったタスクの書き方も同様です。バージョンアップしたら、以前の書き方ではエラーが出てしまったり…。

この数ヶ月の間だけでも「なんとかって書いてたのはもう使わないよ」みたいなこともありました(リリース履歴)。たとえば「gulpfile.js」には必要なタスクを記述しますが、v3.4.xv3.8.xではやはり違うわけです(一番最後のデフォルトのタスクとかウォッチの書き方)。プラグインだって、バージョンアップとともに別のものに移行することもあります。

数日前に公開されたこちらのKDDIウェブコミュニケーションズさんの記事「Gulpでlocalhostサーバーを起動、さらにBrowser-Syncで作業効率化」では、ローカルサーバの起動のデモで「gulp-connect」を使ってらっしゃいますが、このプラグインはもう開発が終わっていて別の「gulp-webserver」になっているわけで(gulp-connectのページにちゃんと書いてあるんですけどね…w)。gulp-connectはもうオフィシャルのプラグイン検索からも除外されてます。ちゃんとね、調べてから書こう。

特にインストールの仕方からタスクの書き方の記事をそのままコピペして使ってるような方は要注意

書かれてあるとおりに「npm install」したらその時の最新バージョンがダウンロードされますからね。gulp本体にしてもプラグインにしても、ブログなどの記事の通りに書いてみたらエラーになるってことだってなくはないということです。

gulpを起動する前に

gulpの導入のため最初にやることと言えば、まずgulpをグローバルにインストールすることでしょう。これ自体はgulpのオフィシャルのページでもそう説明されてます(Getting Started)。

npm install -g gulp

で、グローバルにインストールしておいて、ローカルのプロジェクトのディレクトリにもインストールする、という流れですね(ローカルにgulpがないと「gulp」と打っても起動しません)。

npm install gulp --save-dev

これでそのディレクトリ(ローカルのnode_modules)にもインストールされます。あとは「gulpfile.js」を書いて「gulp」と実行すれば動きます。

gulp

ええ、動きます。

それはそれで特に問題もないのですが、グローバルとローカルの双方にgulpをインストールした状態のディレクトリで「gulp –version」を実行すると以下のように出ます。

gulp --version
[time] CLI version 3.8.6
[time] Local version 3.8.6

グローバルにインストールしてるのは「gulp」ってコマンドをどこからでも実行できるようにしてるだけで、実のところはわざわざグローバルに入れなくても大丈夫だったりします。つまるところ、ローカルのを直接呼び出して動かすことはできる(かつてのGruntがそうであったように、プロジェクトによるバージョンの相違みたいなのが出てきてしまうんですよね)。

グローバルにgulpを入れているなら必要に応じてアップデートしないと古いままになります。かといって、既にあるプロジェクトのgulpは古いもので安定稼働中みたいなこともありますからね(グローバルとローカルにあって、ローカルが古いとWarningが出るようになっています)。Warningが出るからと、安定稼働中のものを無理してアップデートするかって言うと…、したことで書き換えとかも面倒。

グローバルのはローカルのを呼んでるだけだとしても、Warningが出るとなんとなく…な気分的な問題もありますw

gulp-warning

でもまぁ、こんなのをいちいち入力するわけにもいかない。

./node_modules/gulp/bin/gulp.js

さすがにちょっと…な感じです。

npmも使ってみよう

そこで登場するのが「npm」。

タスクランナーを使うぐらいでしか利用しない方にはあまり知られてないようなんですけど、npmも立派なプログラムです。npmから「gulp」を呼び出せば、ローカルのnode_modulesにあるgulpが起動します。npmはあらかじめ用意されたコマンドを実行できますが、自分で実行用のスクリプトを登録することも可能。

「npm init」して「package.json」が生成されていれば、その中に「scripts」って書かれたブロックがあるはずです(自分で作ったのなら追加してください)。

{
    (中略)
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    }
}

こんな感じで、デフォルトで何もしなければ「test」だけ記述されているでしょう。さっきの長ったらしいコマンドなんかいちいち打てないので、ここにgulpを起動するためのコマンドを追加する、と楽。

{
    (中略)
    "scripts": {
        "start": "gulp",
        "test": "echo \"Error: no test specified\" && exit 1"
    }
}

たとえばこの「start」ってとこに「gulp」と書いて以下のコマンドを実行するとローカルのgulpが起動します。

npm start

あえてグローバルにgulpをインストールしないで、エイリアスとかで「alias gulp=”npm start”」とか登録しておけば、プロジェクトのディレクトリで「gulp」と打ったらいつでもローカルのgulpが起動することになりますね。その代わり、ちゃんとpackage.jsonに「start」を書き忘れないように。

どっちが良いかは各自の判断で。gulpに限った話でもないんですが、グローバルとローカルでバージョンの相違があるといちいちWarningが出たりするのが気持ち悪かったりでボクはこっちのやり方に変えました。

あと、自分で任意のコマンドを登録するならこんな感じ。

{
    (中略)
    "scripts": {
        "start": "gulp",
        "deploy": "gulp deploy",
        "test": "echo \"Error: no test specified\" && exit 1"
    }
}

自分で追加したのは「npm run-script スクリプト名」の形で呼び出せばOK。「npm run-script deploy」を実行すれば、gulpfile.jsに指定した「deploy」というタスクだけを実行できるでしょう。

※ピクセルグリッドの神に「npm run 〜」の方が短くて好みというコメントをもらったので追記: 「task automation with npm run」に書いてあるように、package.jsonのscriptsのとこは書き方次第でいかようにもすることができます。上のももっと短く「npm run deploy」で動かすことができますね。

gulpfile.jsの書き方

書き方そのものはオフィシャルのサンプル(バージョン確認してね)を参考にしましょう。それはプラグインの呼び出し方やオプション指定の記述も同様です(アップデートされて何かが変わるなんてよくあること)。

gulpfile.jsの基本構造は以下のようになります。

var gulp = require('gulp'),
 prettify = require('gulp-prettify'), // 必要なプラグインの指定
 jade = require('gulp-jade'); // 必要なプラグインの指定

gulp.task('taskA', function() {
 return gulp.src('./src/**') // ソース元
  .pipe(jade()) // プラグインの実行
  .pipe(prettify()) // プラグインの実行
  .pipe(gulp.dest('./dist/')); // 書き出し先
});

gulp.task('watch', function() {
 gulp.watch('./src/**', ['taskA']); // 監視対象と実行するタスク
});

gulp.task('default', ['taskA', 'watch']); // 起動時に実行するタスク

まず、冒頭で「gulp」やその他の使用するプラグインなどを明示します(明示するのが面倒だったら、GoogleのWeb Starter Kitでも使われてるgulp-load-pluginsってのが使えます)。

あとは、任意のタスク名を決めて(この場合はtaskA)、「gulp.src()」で実行対象となるディレクトリやファイル(ワイルドカードなんかでもOK)を指定。「.pipe(処理したいこと())」で処理を繋げていきます。書き出し先は「.pipe(gulp.dest())」で指定する、と。

タスク’watch’のところは、監視する対象となるディレクトリやファイルを指定しつつ、どのタスクを実行するか、を書く感じ、’default’のタスクは起動時に何を実行するか、といったところです。詳しいことは公式のドキュメントとかレシピなんかも参考に。

ソース元や監視対象なんかは、複数の場所やファイルを指定することもできますし、あらかじめ変数として場所を定義しておいてそれを呼び出しても良いでしょう。

var gulp = require('gulp'),
 prettify = require('gulp-prettify'),
 jade = require('gulp-jade');

var path = {
 'tmpl': './src/*.jade', // ソース元
 'dist': './dist/'  // 書き出し先
}

gulp.task('taskA', function() {
 return gulp.src(path.tmpl)
  .pipe(jade())
  .pipe(prettify())
  .pipe(gulp.dest(path.dist));
});

gulp.task('watch', function() {
 gulp.watch(path.tmpl, ['taskA']);
});

gulp.task('default', ['taskA', 'watch']);

このまま「gulp」とかやってもプラグインがなくてエラーになります(もちろん)。gulpfile.jsを書く前でも書いた後でもいいので、使う予定のプラグインをnpmでインストールしましょう。

npm install gulp-prettify gulp-jade --save-dev

インストールされたら実行です。

動いた環境はそのままパクる

新しく何か始める時、それも似たような構成のものを作る時、またゼロからgulpfile.jsを作ったりモジュールを手動でインストールするほどアホらしいことはありません。

「npm install ~ –save-dev」とかしてれば、それを実行した時のバージョンが列挙されたpackage.jsonがあるはず。新しく何か始める時は、それだけでもコピーすると楽でしょう(少なくともインストールコマンドの実行は楽できる)。

npm install

これだけ実行すれば、package.jsonさえあればそこに書かれた内容のものが勝手にインストールされます。動いてる環境のものをコピーしていればそっくり同じものになりますから、おそらくエラーなどはおきないでしょう。あとは、gulpfile.jsをプロジェクトに合わせてちょいちょいっと書き直すぐらいでしょうか。

さっきの「start」とかも入れてあれば、

npm install && npm start

必要なファイルのインストールから実行まで1コマンドでOK。

npm postinstallとかも便利

npmはできる子なので、前述した’scripts’のとこに「’postinstall’: ‘実行したいコマンド’」を入れておくと、npm installしたあとに勝手に任意のコマンドを実行することができます。そういうのをうまく使えば、npmでモジュールをインストールした後に、Bowerでライブラリをまるっと拾ってきて〜みたいなことができるわけです。

{
    (中略)
    "scripts": {
        "start": "gulp",
        "postinstall": "bower install",
        "test": "echo \"Error: no test specified\" && exit 1"
    }
}

こんな感じでね。うまく使いこなせば、余計なコマンドなんか何も打たなくて制作を始めることができますよ。

参考になるかどうかわかりませんが、gulpでのベーシックな処理を簡単にまとめたのをおいてます。大体こんな感じで書いておけばどうにかなるだろうということで。

※この記事は2014年7月30日時点のものですので、数ヶ月後にコレを読んでる方はご注意を。

Published in articles