Gulp入門: CodekitのようなSass/JS自動コンパイル環境を作る方法

この記事では、「Gulpを用いて、Codekitと同様のWeb制作環境を再現する」ことを目的に、その手順を解説します。

主な自動化タスクは「SCSSのコンパイル」「JSのコンパイル(Babel・Minify)」「ブラウザの自動リロード」の3点です。Gulpの導入方法から、環境再現に必要なプラグインの紹介、設定ファイルの記述方法までを分かりやすく説明していきます。

1. そもそもGulpとは?

Gulp.js (公式サイト)

Gulpは、Node.jsをベースにしたビルドシステムで、一般に「タスクランナー」と呼ばれています。Web制作における様々な作業(例えば、Sassのコンパイルやファイルの圧縮など)を自動化してくれるツールです。

gulpfile.jsという設定ファイルを作成し、そこに実行したいタスクを記述していくことで、作業を自動化します。

2. Gulpのインストール手順

Gulpを利用するためには、いくつかの準備が必要です。順を追って進めましょう。

2-1. Node.jsのインストール

GulpはNode.jsのパッケージとして提供されているため、まずNode.jsの公式サイトからインストーラーをダウンロードし、インストールしてください。

2-2. プロジェクトディレクトリへの移動

Gulpを使いたいプロジェクトのディレクトリ(フォルダ)に、ターミナル(コマンドプロンプト)で移動します。基本的には、.gitディレクトリなどが置かれているプロジェクトの最上階層で問題ありません。

$ cd test-gulp

2-3. npmの初期化とpackage.jsonの作成

次に、npm(Node.jsのパッケージ管理ツール)を初期化し、プロジェクトの情報を管理するpackage.jsonファイルを作成します。

$ npm init -y

npm initだけを実行すると、プロジェクト名などを対話形式で質問されます。特に指定がない場合は、-yオプションを付けてすべて「Yes」で進めるのが簡単です。

2-4. Gulpのインストール

Gulp本体を、プロジェクトのローカル環境にインストールします。

$ npm install gulp --save-dev
# または
$ npm install -D gulp

--save-dev(または-D)は、開発環境でのみ使用するパッケージ(devDependencies)としてpackage.jsonに記録するためのオプションです。

インストールが成功したか、バージョンを確認してみましょう。

$ gulp -v
[18:54:22] CLI version 1.4.0
[18:54:22] Local version 4.0.2

上記のようにバージョン情報が表示されるか、package.jsonファイル内に「devDependencies」という項目が追加され、そこに「gulp」が記載されていれば成功です。

2-5. gulpfile.jsの作成

Gulpのタスクを記述するための設定ファイルgulpfile.jsを作成します。package.jsonと同じ階層に作成してください。

作成したgulpfile.jsに、Gulp本体を読み込むため、以下の1行を記述して保存します。

const gulp = require('gulp');

以上でGulpを実行する準備は完了です。次に、Codekitの機能を再現するための各種プラグインをインストールします。

3. Codekit再現に必要なGulpプラグイン

Gulpは、プラグインを追加することで機能を拡張できます。Codekitの環境を再現するために、今回は以下のプラグインを使用します。

  • SCSS系
    • gulp-sass: SCSSをCSSにコンパイルします。
    • gulp-sourcemaps: ソースマップを作成します。
    • gulp-postcss: Autoprefixerなど、CSSを処理するプラグインを利用するために必要です。
    • autoprefixer: ベンダープレフィックスを自動付与します。gulp-postcssとセットで使用します。
  • JS系
    • gulp-uglify: JSファイルを圧縮(Minify)します。
    • gulp-rename: ファイル名を変更します(例: .js.min.js に)。
    • gulp-babel: ES6+の記法をES5にトランスパイルします。
    • @babel/core, @babel/cli, @babel/preset-env: Babel本体と設定です。
    • gulp-eslint: ESLintを使い、JSの構文チェックを行います。
  • ブラウザ同期
    • browser-sync: ファイル保存時にブラウザを自動リロードします。
  • 画像
    • gulp-imagemin: 画像を最適化(圧縮)します。
  • その他(ユーティリティ)
    • gulp-notify: エラー発生時にデスクトップ通知を表示します。
    • gulp-plumber: エラーが発生してもGulpのタスク(watch)が強制終了するのを防ぎます。

これらのプラグインは、以下のコマンドで個別にインストールできます。

$ npm install --save-dev gulp-sass

また、以下のように複数をまとめてインストールすることも可能です。

$ npm install --save-dev gulp-sass gulp-sourcemaps gulp-postcss autoprefixer gulp-uglify gulp-rename gulp-babel @babel/core @babel/cli @babel/preset-env gulp-eslint browser-sync gulp-imagemin gulp-notify gulp-plumber

4. Gulp設定ファイルの記述

Gulpではgulpfile.jsにタスクを記述していきます。今回は、BabelとAutoprefixerの設定を別ファイル(.babelrc, package.json)に切り出します。

4-1. gulpfile.js

Gulpタスクの本体です。各プラグインの読み込みや、具体的な処理内容を定義します。

//プラグインの読み込み
const gulp = require('gulp');// gulp宣言
//scss関係
const sass = require('gulp-sass');//Sassをコンパイルするプラグインの読み込み
const sourcemaps = require('gulp-sourcemaps');//ソースマップの作成
const postcss = require('gulp-postcss');//autoprefixer用(autoprefixerとセット)
const autoprefixer = require('autoprefixer');//autoprefixer用
//JS関係
const uglify = require('gulp-uglify');//jsのminfy化
const rename = require('gulp-rename');//ファイルをリネームする(xx.jsをxx.min.jsに変更)
const babel = require('gulp-babel');//js babel
const eslint = require('gulp-eslint');//js es-lint
//その他
const notify = require('gulp-notify');//エラー発生時にデスクトップ通知する
const plumber = require('gulp-plumber');//エラー時の強制終了を防止する
const browserSync = require('browser-sync');//保存したらブラウザ再読み込み
//画像
const imagemin = require('gulp-imagemin');//画像の最適化(ロスレス圧縮)

//ドキュメントルート(環境に合わせて変更してください)
const docRoot = '/recruit';

//▼scss関連タスク
gulp.task('sass', function () {
	return gulp.src('.'+docRoot+'/data/_src_scss/*.scss')	//コンパイル前のファイルのパス
		.pipe(plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )	//エラーチェック
		.pipe(sourcemaps.init())	//ソースマップ作成処理開始
		.pipe(sass({
			outputStyle: 'compact' //expanded, nested, campact, compressedから選択
		}).on('error', sass.logError)) //エラーを出力
		//autoprefixer※設定はpackage.jsonのbrowserslistを参照
		.pipe(postcss([autoprefixer({cascade: false})]))	//プロパティのインデントを整形するcascadeオプションはfalse
		.pipe(sourcemaps.write())	//ソースマップを作成
		.pipe(gulp.dest('.'+docRoot+'/data/css/'))	//コンパイル後のファイルのパスを記述
		.pipe(browserSync.stream());//コンパイル時ブラウザをリロードさせず反映させる
});

//▼js関連タスク
gulp.task('js-minify', function() {
	return gulp.src(['.'+docRoot+'/data/_src_js/*.js', '!.'+docRoot+'/data/_src_js/*.min.js'])	//コンパイル前のファイルのパス(.min.jsを除く)
		.pipe(plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )	//エラーチェック
		.pipe(sourcemaps.init())	//ソースマップ作成処理開始
		.pipe(eslint.format())	//eslint
		.pipe(eslint.failAfterError())	//eslint
		.pipe(babel())	//babel
		.pipe(uglify())	//minify
		.pipe(rename({extname: '.min.js'}))	//リネーム
		.pipe(sourcemaps.write())	//ソースマップを作成
		.pipe(gulp.dest('.'+docRoot+'/data/js/'));	//コンパイル後のファイルのパスを記述
});

//画像関連のタスク
gulp.task('imagemin', function () {
	return gulp.src('.'+docRoot+'/data/images/**/*.{jpg,jpeg,png,gif,svg}')
		.pipe(imagemin(
		[
			imagemin.jpegtran(),	//jpgロスレス
			imagemin.optipng(),	//pngロスレス
			imagemin.svgo(),	//svgロスレス
			imagemin.gifsicle()	//gifロスレス
		]
		))
		.pipe(gulp.dest('.'+docRoot+'/data/images/'));
});

// browser-syncタスク
var HTML_SRC = './**/*.html'; //拡張子がhtmlのファイル
var SCSS_SRC = './**/*.scss'; //拡張子がscssのファイル
var PHP_SRC = './**/*.php'; //拡張子がphpのファイル
var JS_SRC = './**/*.js'; //拡張子がjsのファイル

// browserSync機能
gulp.task('browserSync', function(){
	var browserSyncOptions = {};
	browserSyncOptions.files = [HTML_SRC,PHP_SRC,JS_SRC]; // ここに監視対象ファイルを書く
	browserSyncOptions.proxy = '192.168.110.180:8075'; // MAMPなどのローカルサーバー環境のURL
	browserSyncOptions.port = 3001; // proxy実行する時のport
	browserSync.init(browserSyncOptions);
});

gulp.task('browser-reload', function () {
	browserSync.reload();
});

// 監視 watch機能
gulp.task('watch', function(done) {
	gulp.watch('.'+docRoot+'/data/_src_scss/*.scss', gulp.task('sass') ); //sassが更新されたらgulp task('sass')を実行
	gulp.watch('.'+docRoot+'/data/_src_js/*.js', gulp.task('js-minify') ); //jsが更新されたらgulp task('js-minify')を実行
	gulp.watch([HTML_SRC,PHP_SRC,JS_SRC], gulp.task('browser-reload') ); //配列内のファイルが更新されたらgulp task('browser-reload')を実行
	done(); // Gulp 4系ではタスク完了を通知するためにdone()を呼ぶ
});

//立ち上げ
gulp.task('default', gulp.series(gulp.parallel('browserSync','watch','imagemin')));

4-2. package.json

Autoprefixerが対応するブラウザの範囲を指定するため、package.jsonの末尾に"browserslist"の項目を追記します。

{
	"name": "プロジェクト名",
	"version": "1.0.0",
	"description": "プロジェクト説明文:XXXXXXXXXXXXXXX",
	"main": "index.js",
	"scripts": {
		"test": "echo \"Error: no test specified\" && exit 1"
	},
	"repository": {
		"type": "git",
		"url": "ilm@ilm.git.backlog.jp:/ILM/ilm_recruit.git"
	},
	"keywords": [],
	"author": "",
	"license": "ISC",
	"devDependencies": {
		"@babel/cli": "^7.7.5",
		"@babel/core": "^7.7.5",
		"@babel/preset-env": "^7.7.6",
		"autoprefixer": "^9.7.3",
		"browser-sync": "^2.26.7",
		"gulp": "^4.0.2",
		"gulp-babel": "^8.0.0",
		"gulp-eslint": "^6.0.0",
		"gulp-imagemin": "^6.2.0",
		"gulp-merge-media-queries": "^0.2.1",
		"gulp-notify": "^3.2.0",
		"gulp-plumber": "^1.2.1",
		"gulp-postcss": "^8.0.0",
		"gulp-rename": "^2.0.0",
		"gulp-sass": "^4.0.2",
		"gulp-sourcemaps": "^2.6.5",
		"gulp-uglify": "^3.0.2"
	},
	"browserslist": [
		"> 1%",
		"last 2 versions",
		"Firefox ESR",
		"Opera 12.1"
	]
}

4-3. .babelrc

Babelの設定ファイル.babelrcを、gulpfile.jsと同じ階層に新規作成し、以下を記述します。

{ "presets": ["@babel/preset-env"] }

4-4. Gulpタスクの基本的な処理

gulpfile.jsに記述したタスクは、以下の処理を組み合わせて構成されています。

  • require('プラグイン名'): npm installしたプラグインを読み込みます。
  • gulp.task('タスク名', 実行される処理): 実行するタスクを定義します。
  • gulp.src('取得するファイル'): タスクの対象となるファイルを取得(読み込み)します。
  • pipe(): 処理をつなげます。src()で読み込んだファイルに対し、pipe()でSassコンパイル、Autoprefixer、Minifyなどの処理を連続して実行できます。
  • gulp.dest('保存先フォルダー'): 処理が完了したファイルを指定の場所に書き出(保存)します。

4-5. Gulp 4系でのタスク記述 (defaultタスク)

Gulpはバージョン3系から4系へのアップデートで、タスク実行の記述方法が変更されました。

Gulp 3系では以下のように記述していました。

gulp.task('default', ['task1', 'task2'], function(){
	// タスクの記述
});

Gulp 4系では、タスクを直列(順番)に実行するgulp.series()と、並列(同時)に実行するgulp.parallel()を使い、以下のように記述します。

// 'task1'と'task2'を並列で実行し、その後に関数を実行
gulp.task('default', gulp.series( gulp.parallel('task1', 'task2'), function(done){
	// さらなるタスクがあれば記述
	done(); // タスク完了を通知
}));

今回の設定ファイルでは、browserSyncwatchimageminの3つのタスクを並列(同時)に実行するよう設定しています。

5. Gulpの実行方法

ここまでの設定が完了したら、ターミナル(コマンドプロンプト)で以下のコマンドを実行します。

npx gulp

npxは、ローカル(プロジェクト内)にインストールしたGulpを実行するためのコマンドです(npm 5.2.0以上で利用可能)。

これによりdefaultタスクが実行され、ファイルの監視(watch)が始まります。SCSSやJSファイルを編集・保存すると、自動的にコンパイルが実行され、ブラウザがリロードされます。

Gulpの停止と個別実行

  • Gulpの停止: ターミナルで Ctrl + C を押します。
  • タスクの個別実行: npx gulp タスク名で、指定したタスクのみを実行できます。例えば、画像圧縮だけを行いたい場合は以下のように実行します。
npx gulp imagemin

よくある質問(FAQ)

Q1: Codekitを使ったことがないのですが、この記事は役立ちますか?
A1: はい、役立ちます。この記事は「Sassのコンパイル」「JSのBabel/Minify」「ブラウザの自動リロード」という、現代のWeb制作で一般的に行われる自動化環境をGulpで構築する手順を解説しています。Codekitの代替が目的ですが、Gulpの環境構築入門としても最適です。
Q2: なぜCodekitではなくGulpを使うのですか?
A2: GulpはCodekitと同様のタスク自動化ツールですが、よりカスタマイズ性が高いのが特徴です。必要なプラグインを自分で選び、設定ファイルを記述することで、プロジェクトごとに最適化された独自のビルド環境を構築できます。また、Node.jsベースであるため、多くの開発環境で利用されています。
Q3: gulpfile.jsのコードが複雑で難しそうです。
A3: はじめは難しく感じるかもしれませんが、基本的な構造は決まっています。重要なのは「① requireでプラグインを読み込む」「② gulp.taskで個々のタスク(Sassコンパイル、JS圧縮など)を定義する」「③ gulp.watchでファイルの変更を監視し、タスクを実行する」という流れです。まずは全体の流れを掴み、Sassのタスクから試してみることをお勧めします。

CONTACT

webサイト制作、デザインに関するご相談、御見積のご依頼など、弊社へのお問い合わせはこちら