SONICMOOV Googleページ

2015年はgulpで決まり!開発環境をgruntから乗り換えよう!(コーダー編)

2015年はgulpで決まり!開発環境をgruntから乗り換えよう!(コーダー編)

  • このエントリーをはてなブックマークに追加

もーいーくつねーるーと~、おーしょーうーがーつー♪
という所で、今年も残り 10 営業日を切りましたね・・・・!早いですね!
皆さまいかがお過ごしでしょうか♪

世間はクリスマスなムード一色ですが、皆さまお忘れになってはいないでしょうか。
大掃除という名の一大行事を!!終えない限りはクリスマスを迎えられませんよね(鬱
今週こそはきっと・・・ほほほ。。

自分を追い込んでみたところで、本題に入りたいと思います!
こちらは、ソニックムーブ Advent Calendar 2014 12日目の記事になります!

目次

なぜ gulp なのか

当記事は grunt から gulp に乗り換えを考えているユーザーを対象としているので、Node.js のインストール方法の説明を省かせていただきます・・・!

gulp の実装当時は、grunt と比べてプラグインが少なかったことを理由に grunt を採用する方が多かったかと思います。ですが、今現在は何ら不便がないところまでプラグインも増えてきています!Google の WebStarterKit でも、ついに gulp が採用しました。これはもう乗り換えるしかありませんよね・・・!

gulp に乗り換えるにあたり、メリット・デメリットは下記のようになります。

メリット

  • grunt に比べてコード量が少なくタスクを定義できる
  • StreamAPI を利用することでファイルを毎回書き出す grunt より高速に処理ができる
  • なんとなく先取り感が味わえる

デメリット

  • 記述が Node.js 寄りなので、ある程度 javascript の知識が必要
  • 記述を少なくできる言っても、処理が断長になれば記述もそれなりに多くなる

「なんとなく先取り感が味わえる」・・・これ大事ですよね!!! とりあえず、今回はこの「なんとなく先取り感が味わえる」ように、既存の grunt を gulp へ地道に書き換えてまいりますっ

目標

マークアップをする上で必要不可欠なタスクを厳選しています! これらのタスクなどの設定を順序立てて、解説していきます。

  • Sass/Compass を扱う
  • 簡易サーバーを立ち上げる
  • ファイルが更新されたら自動でブラウザをリロードする
  • 自動でベンダープレフィックスを付与する
  • 自動で CSS のプロパティをソートする
  • 画像のデータ容量を圧縮する
  • ファイルをコピーする
  • ファイルを削除する
  • タスクを直列処理する

gulp-compass

sass/compass を扱うパッケージ。自動で css sprite を生成させる。

gulp-compass

gulp-connect

簡易サーバーを立ち上げるパッケージ。

gulp-connect

gulp-watch

ファイルが更新されたら自動でブラウザをリロード(Livereload)するパッケージ。

gulp-watch

gulp-autoprefixer

自動でベンダープレフィックスを付与するパッケージ。

gulp-autoprefixer

gulp-csscomb

自動で CSS のプロパティをソートするパッケージ。

grunt-csscomb

gulp-imagemin

画像のデータ容量を圧縮するパッケージ。

gulp-imagemin

gulp-clean

ファイルを削除するパッケージ。

gulp-clean

run-sequence

タスクを並列/直列処理するパッケージ。

run-sequence

Before(grunt)

module.exports = function(grunt) {
	// pakage.json を呼び出す
	var pkg = grunt.file.readJSON('package.json');
	grunt.initConfig({
		dir: { // ディレクトリ設定
			src: '_src', // _srcフォルダ置き換え
			dist: 'dist' // distフォルダ置き換え
		},
		compass: { // Compassの設定
			dist: {
				options: {
					config: 'config.rb' // confing.rbを読み込む
				}
			}
		},
		connect: { // 簡易サーバー
			livereload: {
				options: {
					port: 3000,
					hostname: '*',
					base: '<%= dir.src %>', // ルートディレクトリの場所を指定
					livereload: true 
				}
			}
		},
		watch: { // ファイル更新監視
			compassdev: { // scssの監視
				files: '<%= dir.src %>/**/*.scss', // 対象ファイル
				tasks: ['compass'] // 実行タスク(css開発用)
			},
			html: {// htmlの監視
				files: ['<%= dir.src %>/*.html','<%= dir.src %>/**/*.html']
			},
			options: { // ライブリロードを有効にする
				livereload: true
			}
		},
		autoprefixer: { // ベンダープレフィックス付与設定
			options: {
				browsers: [ 'last 2 versions' ] // 対象ブラウザの設定
			},
			default: {
				expand: true,
				cwd: '<%= dir.dist %>/css/', // 読み込みファイル
				src: '{,**/}*.css',
				dest: '<%= autoprefixer.default.cwd %>' // 書き出しファイル 同じファイルが続くので置き換える
			}
		},
		csscomb: { // CSSのプロパティの順番整理
			default: {
				src: '<%= autoprefixer.default.src %>',
				dest: '<%= autoprefixer.default.dest %>'
			}
		},
		pngmin: { // PNG 画像を圧縮
			compile: {
				options: {
					ext: '.png'
				},
				files: [
					{
						expand: true,
						src: ['{,**/}*.png'],
						cwd: '<%= dir.src %>/images/',
						dest: '<%= dir.dist %>/images/'
					}
				]
			}
		},
		copy: { // ファイルのコピー
			spritesImg: {
				expand: true,
				cwd: '<%= dir.src %>/',
				src: '{,**/}sprites.png',
				dest: '<%= dir.dist %>/'
			},
			img: {
				src:['{,**/}*.{png,jpg,gif}'],
				dest: '<%= dir.dist %>/images/',
				expand: true,
				cwd: '<%= dir.src %>/images/'
			},
			css: {
				expand: true,
				cwd: '<%= dir.src %>/',
				src: 'css/**',
				dest: '<%= dir.dist %>/'
			},
			js: {
				expand: true,
				cwd: '<%= dir.src %>/',
				src: 'js/**',
				dest: '<%= dir.dist %>/'
			},
			html: {
				expand: true,
				cwd: '<%= dir.src %>/',
				src: '**/*.html',
				dest: '<%= dir.dist %>/'
			}
		},
		clean: { // 不要なファイルを削除する
			deleteDist: { // distフォルダ内のhtml以外を一度全て削除する
				src: ['<%= dir.dist %>/**/*.html','<%= dir.dist %>/css','<%= dir.dist %>/images','<%= dir.dist %>/js']
			},
			deleteSprites: { // スプライト画像生成フォルダ(images/sprites)を全て削除する
				src: ['{,**/}sprites-*.png','<%= dir.dist %>/{,**/}sprites']
			}
		}
	});

	// pakage.jsonに記載されているパッケージをオートロード
	var taskName;
	for(taskName in pkg.devDependencies) {
		if(taskName.substring(0, 6) == 'grunt-') {
			grunt.loadNpmTasks(taskName);
		}
	}
	// 以下タスクの登録
	// デフォルト(各ファイル監視してビルド)
	grunt.registerTask('default', [
		'connect',
		'watch'
	]);
	// リリース用ビルド
	grunt.registerTask('dist', [
		'clean:deleteDist',
		'compass',
		'autoprefixer',
		'csscomb',
		'pngmin',
		'copy',
		'clean:deleteSprites'
	]);
};

After(gulp)

// パッケージをインポートする
var gulp = require('gulp');
var compass = require('gulp-compass');
var connect = require('gulp-connect');
var watch = require('gulp-watch');
var autoprefixer = require('gulp-autoprefixer');
var csscomb = require('gulp-csscomb');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
var runSequence = require('run-sequence');
var clean = require('gulp-clean');

// ディレクトリ設定
var dir = {
	src: '_src', // _srcフォルダ置き換え
	dist: 'dist' // destフォルダ置き換え
}

// Compassの設定
gulp.task('compass', function() {
	return gulp.src( dir.src + '/{,**/}*.scss' ) // 読み込みファイル
	.pipe(compass({
		config_file: 'config.rb', // confing.rb を読み込む
		css: dir.src + '/css/', // 書き出し先
		sass: dir.src + '/sass/' // 読み込み先
	}));
});

// 簡易サーバー
gulp.task('connect', function() {
	return connect.server({
		port: 3000, // ポート番号を設定
		root: dir.src, // ルートディレクトリの場所を指定
		livereload: true // ライブリロードを有効にする
	});
});

// 自動更新
gulp.task('reload', function () {
	return gulp.src(dir.src + '/{,**/}*.html')
	.pipe(connect.reload());
});

// ファイル更新監視
gulp.task('watch', function() {
	// scssの監視
	gulp.watch([ 
		dir.src + '/{,**/}*.scss' // 対象ファイル
	],['compass']); // 実行タスク(css 開発用)
	gulp.watch([
		dir.src + '/{,**/}*.html', // 対象ファイル
		dir.src + '/{,**/}*.css',
		dir.src + '/{,**/}*.js'
	],['reload']); // 実行タスク(scss ファイル以外が更新されたタイミングでブラウザを自動更新)
});

// ベンダープレフィックス付与設定
gulp.task('autoprefixer', function () {
    return gulp.src( dir.src + '/{,**/}*.css' ) // 読み込みファイル
    .pipe(autoprefixer({
        browsers: ['last 2 versions'] // 対象ブラウザの設定
    }))
    .pipe( gulp.dest( dir.dist ) ); // 書き出しファイル
});

// CSSのプロパティの順番整理
gulp.task('csscomb', function () {
  return gulp.src(dir.src + '/{,**/}*.css') // 読み込みファイル
    .pipe(csscomb())
    .pipe(gulp.dest(dir.dist)); // 書き出し先
});

// 画像を圧縮
gulp.task('imagemin', function () {
	return gulp.src( dir.src + '/{,**/}*.{png,jpg,gif}' ) // 読み込みファイル
	.pipe(imagemin())
	.pipe(gulp.dest( dir.dist )); // 書き出し先
});

// ファイルのコピー
gulp.task('copy', function () {
	return gulp.src([
		dir.src + '/{,**/}*.html', // 対象ファイル
		dir.src + '/{,**/}*.js'
	])
	.pipe(gulp.dest( dir.dist ));
});

// 不要なファイルを削除する
// distフォルダ内を一度全て削除する
gulp.task('clean-dist', function () {
	return gulp.src([
		dir.dist + '/{,**/}*.html', // 対象ファイル
		dir.dist + '/css',
		dir.dist + '/js',
		dir.dist + '/img'
	], {read: false} )
	.pipe(clean());
});
// スプライト画像の生成データを全て削除する
gulp.task('clean-sprite', function () {
	return gulp.src( [
		dir.dist + '/{,**/}sprite-*.png', // 乱数付きのスプライト画像
		dir.dist + '/{,**/}sprite' // スプライト画像生成フォルダ
	], {read: false} )
	.pipe(clean());
});

// 以下タスクの登録
// デフォルト(各ファイル監視してビルド)
gulp.task('default', [
	'connect',
	'watch'
]);
// リリース用ビルド
gulp.task('dist', function(callback) {
  return runSequence( // タスクを直列処理する
    'clean-dist',
    'compass',
    ['autoprefixer','imagemin'],
    'csscomb',
    'copy',
    'clean-sprite',
    callback
  );
});

ディレクトリ構成

構成はシンプルに開発用と納品用でディレクトリを分けるようにしています。

_src/ ← 開発用
	css/
	img/
	js/
	sass/
	imdex.html

dist/ ← 納品用
config.rb
gulpfile.js
package.json

開発中にブラウザチェックを行なうルートとなるディレクトリは、「_src」 直下になります! ディレクトリ「dist」は空っぽで問題ありません!ディレクトリ「css」やディレクトリ「img」内は、カテゴリ毎でディレクトリを分けても耐えられるようにしています。

基本設定

1. package.json を作成する

1)コマンドプロンプトでプロジェクトとなるディレクトリに移動します。

cd [path]

※[path] は任意

2)コマンドプロンプトで下記コマンドを入力します。

npm init

3)設定についていろいろ質問が続きますが・・・ ひとまずは、すべて Enter を押していきます。

すると、設定した内容で package.json が生成されたことが確認できます! package.json の設定はのちほど変更することができますが・・・。name の値が gulp となっていると、「3. ローカルに gulp をインストールする」でエラーが出るので、gulp 以外の適当な英数字な値に変更しておきましょう!!

ss1

2. グローバルに gulp をインストールする

管理者権限でコマンドプロンプトを立ち上げ、下記コマンドを入力します。

Windows の場合

npm install gulp -g

Mac の場合

sudo npm install gulp -g

3. ローカルに gulp をインストールする

コマンドプロンプトで再びプロジェクトとなるディレクトリに移動して、下記コマンドを入力します。

npm install gulp --save-dev

grunt を扱っていた方はご存知なように、–save-dev を付けることによって package.json にパッケージの記述が自動的に追加されていきます!!

ss2

※github のリポジトリの記述がありますが、無くて大丈夫です。

4. gulpfile.js を作成する

もろもろ準備が整ったところで、gulp の設定を行ってまいりましょう!

1)ファイル名「gulpfile.js」として、新規ファイルを作成します。
2)gulpfile.js にパッケージ「gulp」をインポートする記述を追加します。

// パッケージをインポートする
var gulp = require("gulp");

3)gulpfile.js にディレクトリ設定の記述を追加します。

// ディレクトリ設定
var dir = {
	src: '_src', // _srcフォルダ置き換え
	dist: 'dist' // destフォルダ置き換え
}

このように定義して、ディレクトリパスを管理しやすくします!

さて・・・これで準備完了です!! 次はいよいよ、最強の武器となるタスクを設定していきます!

タスク設定

compass

sass/compass を扱うタスク。
自動で css sprite を生成させる。

パッケージ

gulp-compass

インストール

npm install gulp-compass --save-dev

設定

// パッケージをインポートする
var compass = require('gulp-compass');

// Compassの設定
gulp.task('compass', function() {
	gulp.src( dir.src + '/{,**/}*.scss' ) // 読み込みファイル
	.pipe(compass({
		config_file: 'config.rb', // confing.rb を読み込む
		css: dir.src + '/css/', // 書き出し先
		sass: dir.src + '/sass/' // 読み込み先
	}));
});

css や sass のオプションは必須のようです。設定が重複するので、confing.rb の css_dir や sass_dir は削除しておきましょう!

connect

簡易サーバーを立ち上げるタスク。

パッケージ

gulp-connect

インストール

npm install gulp-connect --save-dev

設定

// パッケージをインポートする
var connect = require('gulp-connect');

// 簡易サーバー
gulp.task('connect', function() {
	connect.server({
		port: 3000, // ポート番号を設定
		root: dir.src, // ルートディレクトリの場所を指定
		livereload: true // ライブリロードを有効にする
	});
});

reload

ファイル監視中に更新されたタイミングでブラウザを自動更新するために、事前にタスクを作成しておきます!!

設定

// 自動更新
gulp.task('reload', function () {
	gulp.src(dir.src + '/{,**/}*.html')
	.pipe(connect.reload());
});

watch

ファイルが更新されたら自動でブラウザをリロード(Livereload)するタスク。

パッケージ

gulp-watch

インストール

npm install gulp-watch --save-dev

設定

// パッケージをインポートする
var watch = require('gulp-watch');

// ファイル更新監視
gulp.task('watch', function() {
	// scssの監視
	gulp.watch([ 
		dir.src + '/{,**/}*.scss' // 対象ファイル
	],['compass']); // 実行タスク(css 開発用)
	gulp.watch([
		dir.src + '/{,**/}*.html', // 対象ファイル
		dir.src + '/{,**/}*.css',
		dir.src + '/{,**/}*.js'
	],['reload']); // 実行タスク(scss ファイル以外が更新されたタイミングでブラウザを自動更新)
});

autoprefixer

自動でベンダープレフィックスを付与するタスク。

パッケージ

gulp-autoprefixer

インストール

npm install gulp-autoprefixer --save-dev

設定

// パッケージをインポートする
var autoprefixer = require('gulp-autoprefixer');

// ベンダープレフィックス付与設定
gulp.task('autoprefixer', function () {
    gulp.src( dir.src + '/{,**/}*.css' ) // 読み込みファイル
    .pipe(autoprefixer({
        browsers: ['last 2 versions'] // 対象ブラウザの設定
    }))
    .pipe( gulp.dest( dir.dist ) ); // 書き出しファイル
});

csscomb

自動で CSS のプロパティをソートするタスク。

パッケージ

gulp-csscomb

インストール

npm install gulp-csscomb --save-dev

設定

// パッケージをインポートする
var csscomb = require('gulp-csscomb');

// CSSのプロパティの順番整理
gulp.task('csscomb', function () {
  return gulp.src(dir.src + '/{,**/}*.css') // 読み込みファイル
    .pipe(csscomb())
    .pipe(gulp.dest(dir.dist)); // 書き出し先
});

imagemin

画像のデータ容量を圧縮するタスク。

パッケージ

gulp-imagemin

インストール

npm install gulp-imagemin --save-dev
npm install imagemin-pngquant --save-dev

インストール(Windows7の場合)

npm install gulp-imagemin@1.0.0 --save-dev
npm install imagemin-pngquant --save-dev

設定

// パッケージをインポートする
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');

// 画像を圧縮
gulp.task('imagemin', function () {
	gulp.src( dir.src + '/{,**/}*.{png,jpg,gif}' ) // 読み込みファイル
	.pipe(imagemin())
	.pipe(gulp.dest( dir.dist )); // 書き出し先
});

copy

タスク「pngmin」で画像を圧縮した後、dist ディレクトリにコピーします! コピーするだけだと、特別なパッケージをインストールする必要はありません! 下記の記述を追加するだけとなりますっ

設定

// ファイルのコピー
gulp.task('copy', function () {
	return gulp.src([
		dir.src + '/{,**/}*.html', // 対象ファイル
		dir.src + '/{,**/}*.js'
	])
	.pipe(gulp.dest( dir.dist ));
});

clean

ファイルを削除するタスク。

パッケージ

gulp-clean

インストール

npm install gulp-clean --save-dev

設定

// パッケージをインポートする
var clean = require('gulp-clean');

// 不要なファイルを削除する
// distフォルダ内を一度全て削除する
gulp.task('clean-dist', function () {
	gulp.src([
		dir.dist + '/{,**/}*.html', // 対象ファイル
		dir.dist + '/css',
		dir.dist + '/js',
		dir.dist + '/img'
	], {read: false} )
	.pipe(clean());
});
// スプライト画像の生成データを全て削除する
gulp.task('clean-sprite', function () {
	gulp.src( [
		dir.dist + '/{,**/}sprite-*.png', // 乱数付きのスプライト画像
		dir.dist + '/{,**/}sprite' // スプライト画像生成フォルダ
	], {read: false} )
	.pipe(clean());
});

default

開発用タスク。各ファイル監視してビルドする。

設定

// タスクの登録
// 開発用
gulp.task('default', [
	'connect',
	'watch'
]);

dist

納品用タスク。データを最適化したり、データ容量を圧縮する。

パッケージ

run-sequence

インストール

npm install run-sequence --save-dev

設定

// パッケージをインポートする
var runSequence = require('run-sequence');

// タスクの登録
// 納品用
gulp.task('dist', function(callback) {
  return runSequence( // タスクを直列処理する
    'clean-dist',
    'compass',
    ['autoprefixer','imagemin'],
    'csscomb',
    'copy',
    'clean-sprite',
    callback
  );
});

gulp は登録したタスクが並列で実行されていくようになっているのですが、並列で動作するとタスク「imagemin」で画像が軽量化される前に タスク「copy」が実行され、軽量化されないデータがディレクトリ「dist」に書き出されてしまうなど、色々と問題が発生してしまうのです。。これらを防ぐため、タスクが完了してから次のタスクを実行するよう直列な処理ができるように、パッケージ「run-sequence」を併用してあげます!

以上で gulpfile.js が完成となります!!

トラブルシューティング

package.json の name を gulp にしていた場合のエラー

ss10

package.json にある name の値が gulp となっていませんか? gulp 以外の適当な英数字な値に変更しましょう!

gulp-imagemin をインストールする際に発生するエラー

ss3

※2014/12/11現在 gulp-imagemin@2.0.0

このようなエラーが発生したら・・・。 Windows7 で最新版をインストールしようとすると、エラーが出るので旧バージョンをインストールしましょう。

npm install gulp-imagemin@1.0.0 --save-dev
npm install imagemin-pngquant --save-dev

どうやら・・・Windows7 に対応している最新バージョンは「1.0.0」なようです。最新版からスタートして、インストール/アンインストールを繰り返し地道に調べましたよっ

さいごに

いかがでしたでしょうか?

今回は grunt で使っていたタスクをそのまま gulp に書き換えるよう専念しましたが、処理を組み合わせることで、もっともっと記述を短くして処理を軽くすることができるようです!

パッケージをインポートする部分の記述は package.json の内容を自動で読み込むように改変したい・・・!! 今後、今の半分は記述を減らせるように精進したいと思います!!

こちらの記事が皆様のお役に立てていただければ幸いでございます!
長文となりましたが・・・お付き合いいただきありがとうございました!

参考URL

  • このエントリーをはてなブックマークに追加

記事作成者の紹介

うさこ(マークアップエンジニア)

ソリューション事業部マークアップエンジニアのうさこです。入社して4年目となりました!ラーメンが大好きなのですが、脂肪という名の悪魔を極力避けるために我慢の日々を過ごしています… ぐぐぐ…

関連するSONICMOOVのサービス

フロントエンドエンジニア募集中!

×

SNSでも情報配信中!ぜひご登録ください。

×

SNSでも
情報配信中!
SONICMOOV Facebookページ SONICMOOV Twitter SONICMOOV Googleページ
フロントエンドエンジニア募集中!

新着の記事

mautic is open source marketing automation