Gulp4で作業爆速化!オススメ設定を公開する【コピペOK】

こんにちは!フリーランスエンジニアのせっち@nosecchi01です。

コーダーが知っておきたいツールの一つとしてGulpがあります。
Sassを覚えたころにGulpの存在を知るという人も多いのではないでしょうか?

この記事ではGulpの詳しい設定方法を解説します。

現役コーダーさんからわかりやすいというお褒めの言葉をいただきました。

私の記事だと気づかず記事のツイートをしていただいた事もあったようで、わかりやすさで選んでいただいておりますm(_ _)m

それではいってみましょう!

追記:2020年6月にwebpackを組み合わせた最新版記事を書きました!そちらも合わせてどうぞ!

Gulp(ガルプ)とは?

すごくざっくりと言うと、さまざまな処理を自動で行ってくれる、タスク自動化ツールです。

Gulpではプラグインを使って様々な処理を自動化できます。

正しい定義を知りたい方は公式をご確認くださいm(__)m

僕の場合でいうと、下記の処理を自動化しています。

  • ブラウザの自動更新
  • Sassのコンパイル
  • ベンダープレフィックス
  • cssをアルファベット順に並べ替え
  • ejsを纏めてhtmlへ
  • 画像(jpeg, png, gif)の圧縮

これを全て自動でやってくれます!

gulpはまだまだ様々な機能があるので、ご自身のやりたいことに合わせてカスタマイズ可能です。

Gulpのバージョンに注意

この記事ではGulp4について記載します。

世の中には、Gulp3.9.1で書かれているものが多くあります。

最近はGulp4の記事も増えてきましたが、Gulp3.9.1とGulp4では記述が微妙に違い、gulp3.9.1の記述では、gulp4は動かなかったりします・・・。(僕は最初それでハマりました・・・)

Gulpの導入に際して、複数サイトを参考にされる方も多いと思いますが、

記事で扱っているgulpのバージョンに注意してください!

最新記事を効率よく検索するには、Chrome拡張機能であるato-ichinenがオススメです!

事前準備:色々インストール【5分】

残念ながら、すぐにgulpを使う事はできません。

しかし、コピペでささっと完了しますので、少し我慢しましょう。

node.jsのインストール

下記リンクよりnode.jsをインストールします。
https://nodejs.org/ja/

推奨版を選択。

インストーラをクリックし、手順に従ってガンガン進みます。

ユーザー名とパスワードを入力します。

インストーラーは要らないのでゴミ箱へ

・インストールが終わったら、nodeのバージョンを確認します。

<Terminal>

node -v

下記のようなこんな感じで出ればOK

node -v
v11.4.0

テスト用フォルダを作成する

こういう系はいきなり実案件や、本番で使おうとせず、テスト用ファイルで作って、動作確認してから、本番環境に導入するのがオススメです。

「gulptest」というフォルダを作り、下記のようなディレクトリ構成にしました。

●gulptest
src
|-css
|-img
|–base
|-scss
|–style.scss
index.html

Terminalでプロジェクトファイルへ移動する

Teminalを開き、cdコマンドで先ほど作ったgulptestへ移動します。

わざわざコマンドを全部打たなくても、cdと打って、ファイルをドラック&ドロップすればOK。

Visual Studio Code(VS Code)を使っている人は、VS Codeにファイルごとドラック&ドロップでOKです。

VS Code上でターミナルを開けば、最初からプロジェクトファイルの場所になっています。

VS Codeでターミナルを開くショートカットキー
ctrl + Shift + @

package.jsonをインストール

ここからはローカル(gulptest)でコマンドを打っていきます。

npm init -y

package.jsonができます。

gulpをインストールする

グローバルインストールは不要になったようですので、
ローカルにのみインストールすればOKです。

npm install -D gulp

ターミナルの画面はこんな感じ。

node_modulesとpackage-lock.jsonができます。

念のためgulpのバージョンを確認します。

gulp -v

下記のようなこんな感じになればOK。

gulp -v
Local vervion 4.0.1

ここまでのまとめ

  • gulpとは何か、何ができるかを理解した。
  • gulpに必要なものを色々インストールした。

インストールしたもの

  • node.js
  • package.json
  • node_modules + pakage-lock.json

自動化のためのプラグインをガンガンインストールする

Terminalで必要なプラグインをガンガンインストールしていきます。

npm install gulp-sass --save-dev
npm install gulp-plumber --save-dev
npm install gulp-notify --save-dev
npm install gulp-sass-glob --save-dev
npm install browser-sync --save-dev
npm install gulp-postcss --save-dev
npm install autoprefixer --save-dev
npm install css-declaration-sorter --save-dev
npm install gulp-imagemin --save-dev
npm install imagemin-optipng --save-dev
npm install imagemin-mozjpeg --save-dev
npm install gulp-ejs --save-dev
npm install gulp-rename --save-dev

スペースで区切り、まとめてインストールする事も可能です。(結果は同じ)

npm install gulp-sass gulp-plumber gulp-notify gulp-sass-glob browser-sync gulp-postcss autoprefixer css-declaration-sorter gulp-imagemin imagemin-optipng imagemin-mozjpeg gulp-ejs gulp-rename --save-dev

package.jsonを見ると無事インストールされていることがわかります。

gulpfile.jsを作成する

一番上の階層に、gulpfile.jsを作成します。

ターミナルではなく、普通に新規作成でOK。

gulpfile.jsを編集していきます。

僕のgulpfile.jsの中身は下記のようになっています。

必要なものだけ切り出して自由に使ってOKです。

var gulp = require('gulp');
var sass = require('gulp-sass'); //Sassコンパイル
var plumber = require('gulp-plumber'); //エラー時の強制終了を防止
var notify = require('gulp-notify'); //エラー発生時にデスクトップ通知する
var sassGlob = require('gulp-sass-glob'); //@importの記述を簡潔にする
var browserSync = require( 'browser-sync' ); //ブラウザ反映
var postcss = require('gulp-postcss'); //autoprefixerとセット
var autoprefixer = require('autoprefixer'); //ベンダープレフィックス付与
var cssdeclsort = require('css-declaration-sorter'); //css並べ替え
var imagemin = require('gulp-imagemin');
var optipng = require('imagemin-optipng');
var mozjpeg = require('imagemin-mozjpeg');
var ejs = require("gulp-ejs");
var rename = require("gulp-rename"); //.ejsの拡張子を変更

// scssのコンパイル
gulp.task('sass', function() {
return gulp
.src( './src/scss/**/*.scss' )
.pipe( plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )//エラーチェック
.pipe( sassGlob() )//importの読み込みを簡潔にする
.pipe( sass({
outputStyle: 'expanded' //expanded, nested, campact, compressedから選択
}) )
.pipe( postcss([ autoprefixer(
{
// ☆IEは11以上、Androidは5以上
// その他は最新2バージョンで必要なベンダープレフィックスを付与する
"overrideBrowserslist": ["last 2 versions", "ie >= 11", "Android >= 5"],
cascade: false}
) ]) )
.pipe( postcss([ cssdeclsort({ order: 'alphabetically' }) ]) )//プロパティをソートし直す(アルファベット順)
.pipe(gulp.dest('./src/css'));//コンパイル後の出力先
});

// 保存時のリロード
gulp.task( 'browser-sync', function(done) {
browserSync.init({

//ローカル開発
server: {
baseDir: "./",
index: "index.html"
}
});
done();
});

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

gulp.task("ejs", (done) => {
gulp
.src(["ejs/**/*.ejs", "!" + "ejs/**/_*.ejs"])
.pipe( plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )//エラーチェック
.pipe(ejs())
.pipe(rename({extname: ".html"})) //拡張子をhtmlに
.pipe(gulp.dest("./")); //出力先
done();
});

// 監視
gulp.task( 'watch', function(done) {
gulp.watch( './src/scss/**/*.scss', gulp.task('sass') ); //sassが更新されたらgulp sassを実行
gulp.watch('./src/scss/**/*.scss', gulp.task('bs-reload')); //sassが更新されたらbs-reloadを実行
gulp.watch( './src/js/*.js', gulp.task('bs-reload') ); //jsが更新されたらbs-relaodを実行
gulp.watch('./ejs/**/*.ejs',gulp.task('ejs') ) ; //ejsが更新されたらgulp-ejsを実行
gulp.watch('./ejs/**/*.ejs',gulp.task('bs-reload') ) ; //ejsが更新されたらbs-reloadを実行
});

// default
gulp.task('default', gulp.series(gulp.parallel('browser-sync', 'watch')));

//圧縮率の定義
var imageminOption = [
optipng({ optimizationLevel: 5 }),
mozjpeg({ quality: 85 }),
imagemin.gifsicle({
interlaced: false,
optimizationLevel: 1,
colors: 256
}),
imagemin.mozjpeg(),
imagemin.optipng(),
imagemin.svgo()
];
// 画像の圧縮
// $ gulp imageminで./src/img/base/フォルダ内の画像を圧縮し./src/img/フォルダへ
// .gifが入っているとエラーが出る
gulp.task('imagemin', function () {
return gulp
.src('./src/img/base/*.{png,jpg,gif,svg}')
.pipe(imagemin(imageminOption))
.pipe(gulp.dest('./src/img'));
});

gulpfile.jsの中身を解説

上から簡単に解説します。

gulp-sass

Sassのコンパイルをします。基本にして最重要ですね。

var gulp = require('gulp');
var sass = require('gulp-sass'); //Sassコンパイル

gulp.task('sass', function() {
return gulp
.src( './src/scss/**/*.scss' )
.pipe( sass({
outputStyle: 'expanded' //expanded, nested, campact, compressedから選択
.pipe(gulp.dest('./src/css'));//コンパイル後の出力先

.src( ‘./src/scss/**/*.scss’ )

はscssを格納している場所を書きます。ご自身の環境で適宜変更してください。

.pipe(gulp.dest(‘./src/css’));

が出力先です。

  • outputSytleはexpandedにしています。
  • 圧縮率を高めたい場合はcompressedに変更してください。

gulp-plumberとgulp-notify

こちらはセットで使用します。

var plumber = require('gulp-plumber'); //エラー時の強制終了を防止
var notify = require('gulp-notify'); //エラー発生時にデスクトップ通知する

.pipe( plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )

それぞれの役割は、下記です。

  • gulp-plumberでエラーが起きてもwatchを止めないようにします。
  • gulp-notifyでデスクトップにエラーメッセージを表示します。

gulp-plumberがないと、エラーが発生する度にgulpが止まってしまうので、是非入れておきたいです。

gulp-sass-glob

Sassが真価を発揮する@importをフォルダ単位でまとめて読み込んでくれます。

var sassGlob = require('gulp-sass-glob'); //@importの記述を簡潔にする

.pipe( sassGlob() )

例)
gulp-sass-globを使わずimportした場合

@import “setting/flexbox”;
@import “setting/responsive”;
@import “module/drawer”;
@import “component/btn”;
@import “component/box”;

gulp-sass-globでimportすると、

@import “setting/**”;
@import “module/**;
@import “component/**;

上記は一例ですが、僕は最近吉本式BEMを採用したので、かなり重宝しています。

post-cssとautoprefixer

ベンダープレフィックスを自動付与してくれます。

var postcss = require('gulp-postcss'); //autoprefixerとセット
var autoprefixer = require('autoprefixer'); //ベンダープレフィックス付与

.pipe( postcss([ autoprefixer(
{
// ☆IEは11以上、Androidは5以上
// その他は最新2バージョンで必要なベンダープレフィックスを付与する
"overrideBrowserslist": ["last 2 version", "ie >= 11", "Android >= 5"],
cascade: false}
) ]) )

overrideBrowserslist: [“last 2 versions”, “ie >= 11”, “Android >= 5”],

の部分で、バージョン指定をしています。

  • IE11以上
  • Androidは5以上
  • その他は最新2バージョンで必要なベンダープレフィックスを付与する。

cssの対応は日々変わっているため、こうした設定を自動取得&自動で付与してくれる機能は本当に神ですね!

試しにflexboxを書いてみると・・・

.main{
  display: flex;
  justify-content: space-between;
}

(コンパイル後)

.main{
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: justify;
  -ms-flex-pack: justify;
  justify-content: space-between;
}

もうこれだけでautoprefixerの威力が伝わるはずです・・・!

おまけ:どこまでベンダープレフィックス対応するのか問題?

クライアント次第だと思いますが、あまりにもベンダープレフィックスを付けまくるのも問題です。

IE11以外はブラウザ開発が進み、どんどんベンダープレフィックス不要になっていっています。

本当はもうほとんどつけなくていいのかもしれませんね!

そのベンダープレフィックス、いつまでつけてるの?

https://qiita.com/amamamaou/items/42197e443134478befaf

なんとなく付けるのではなく、「どこまでブラウザ対応するのか」を判断した上で選択していきましょう!

browser-sync

command + Sで保存した際に、自動でブラウザをリロードしてくれます。

var browserSync = require( 'browser-sync' ); //ブラウザ反映

gulp.task( 'browser-sync', function(done) {
browserSync.init({

server: {
baseDir: "./",
index: "index.html"
}
});
done();
});

gulp.task( 'bs-reload', function(done) {
browserSync.reload();
done();
});
var browserSync = require( 'browser-sync' ); //ブラウザ反映

何度もリロードするので、browser-syncは中毒性が高いです・・・。

gulp-ejs

ejsを使うと、htmlファイルで、header、footer等をパーツ化して、呼び出す事ができます。

html / css で下層ページを大量に作るときなどに重宝します。

拡張子(ejs)のままではブラウザで読み込めないので、ejsからhtmlへの変換をgulpで行います。

var ejs = require("gulp-ejs");
var rename = require("gulp-rename"); //.ejsの拡張子を変更

gulp.task("ejs", (done) => {
gulp
.src(["ejs/**/*.ejs", "!" + "ejs/**/_*.ejs"])
.pipe( plumber({ errorHandler: notify.onError("Error: <%= error.message %>") }) )
.pipe(ejs())
.pipe(rename({extname: ".html"})) //拡張子をhtmlに
.pipe(gulp.dest("./"));
done();
});

.pipe(rename({extname: “.html”})) 

ここの部分については記載のないサイトもありますが、どうやらGulp4.0.0以降これがないとindex.htmlではなく、index.ejsで出力されてしまうので必要です。

(参考)gulp:「gulp-ejs」Ver 4.0.0でファイル出力時の拡張子を変更する方法

https://www.nxworld.net/services-resource/gulp-plugin-gulp-ejs-rename-file-extension.html

ejsのエラーでgulpが止まらないように、ここにもgulp-plumberを入れています。

.src([“ejs/**/*.ejs”, “!” + “ejs/**/_*.ejs”])

はejsのソース元を書きます。

共通部品は”_”を使って.htmlに変換しないようにします。(_header.ejsなど)

.pipe(gulp.dest(“./”));

ここに出力先を書きます。

こんな感じの階層構成になっています。

ここでコマンドを打つとそれぞれの.htmlファイルが作成されます。

<Terminal>

gulp ejs

タスクをまとめて走らせる、watchする

通常は、

  • sassをコンパイルしたかったらgulp-sass
  • ejsをhtmlにまとめたかったら、gulp-ejs

などそれぞれのコマンドを打つ必要があります。
これでは、何か更新を加える度にそれぞれのコマンドを打つ必要があり非常に面倒です。

それをまとめてくれるのが下記の記述です。

gulp.task( 'watch', function() {
gulp.watch( './src/scss/**/*.scss', gulp.task('sass') ); //sassが更新されたらgulp sassを実行
gulp.watch('./src/scss/**/*.scss', gulp.task('bs-reload')); //sassが更新されたらbs-reloadを実行
gulp.watch( './src/js/*.js', gulp.task('bs-reload') ); //jsが更新されたらbs-relaodを実行
gulp.watch('./ejs/**/*.ejs',gulp.task('ejs') ) ; //ejsが更新されたらgulp-ejsを実行
gulp.watch('./ejs/**/*.ejs',gulp.task('bs-reload') ) ; //ejsが更新されたらbs-reloadを実行
});

// default
gulp.task('default', gulp.series(gulp.parallel('browser-sync', 'watch')));

・gulp.watchで監視(更新の度にそれぞれのgulpコマンドを自動で実行します。)
・gulp.task(‘default’…); の部分で、”gulp”コマンドを打てばwatchとbrowser-syncが自動で走るようにしています。

<Terminal>

gulp

※gulp-sass, gulp-ejs, browser-syncを同時にやってくれる

gulp-imagemin

JPEG, PNG, GIF画像を圧縮してくれる設定です。

<gulpfile.js>

var imagemin = require('gulp-imagemin');
var optipng = require('imagemin-optipng');
var mozjpeg = require(‘imagemin-mozjpeg');
//圧縮率の定義
var imageminOption = [
optiping({ optimizationLevel: 5 }),
mozjpeg({ quality: 85 }),
imagemin.gifsicle({
interlaced: false,
optimizationLevel: 1,
colors: 256
}),
imagemin.mozjpeg(),
imagemin.optipng(),
imagemin.svgo()
];
// 画像の圧縮

// $ gulp imageminで./src/img/base/フォルダ内の画像を圧縮し./src/img/フォルダへ
// .gifが入っているとエラーが出る
gulp.task('imagemin', function () {
return gulp
.src('./src/img/base/*.{png,jpg,gif,svg}')
.pipe(imagemin(imageminOption))
.pipe(gulp.dest('./src/img'));
});

gulp-imageminはversion7以降imagemin.jpegtran()が使えなくなりましたので代わりにimagemin.mozjpeg()を使います。

(参考)gulp-imageminをversion7以降に更新後、「TypeError: imagemin.jpegtran is not a function」というエラーが出た時の対処法

https://www.tenagazaru.net/gulp-imagemin-v7-function

・imageminOptionで圧縮率等を定義し、imagemin()に代入しています。

・src/img/baseファイルに入れた画像を圧縮し、src/imgに出力します。ご自身の環境で適宜変更してください。

Web上に画像圧縮サービスは沢山ありますが、枚数制限や、アップロード→圧縮→ダウンロードの手間がかかります。

gulpを使えば、何百枚あってもボタン一つでOKです。

画像圧縮は一度だけやればいいので、defaultには設定せず、
適宜 gulp imageminで圧縮するようにしています。

gulp imagemin

※baseフォルダ内の画像ファイルを圧縮する

gulpは使い回し可能【1回だけ頑張る】

gulpは一度設定すれば使い回し可能です。
gulpfile.jsとpackage.jsonを別のプロジェクトフォルダにコピペし、

npm install

これだけでOKです。
最初の設定は難しいですが、一度だけ頑張りましょう。

動けばこっちのもので、あとは使いまわせます。

納品やチームで共有する際はnode_modulesを入れない

納品する際は、node_modulesを納品しないようにしましょう。
理由は下記です。

  • 重たい(100MB以上)
  • ファイル数が膨大
  • gulpfile.jsとpackage.jsonがあれば、誰でも同じ環境を作れる

gitで共有する場合は.gitignoreに記載すればOK

gitを使っている場合は、わざわざフォルダから除外しなくても.gitignoreに記載すればOKです。

#node_modulesを除外する
node_modules

これで除外できます。

・#でコメントアウトを書きます。
・複数系のsを忘れないように!

どうしてもつまづいたら本もありです。

順を追って説明してきましたが、どうしてもつまづいてしまった場合は本に頼るのもありです。

僕は書籍は使っていませんが、最初の構築(Gulp3.9.1)では相当ハマりました。

今回の記事も、知り合い(@moyashi3333 )のgulpfile.jsをベースに構築したので割とすんなり構築できたというのはあります。

どうしてもわからない箇所がある場合は、本を参考にした方が早道かもです。

Webデザイナーの仕事を楽にする! gulpではじめるWeb制作ワークフロー入門

Web制作者のためのSassの教科書

この本は僕も実際に読みました。Gulpについてはわかったけど、実はSassを知らない・・・という人向けです。

Sassの使い方については別記事で解説しており、ぶっちゃけそれだけで十分かもですが、

Sassでできることが網羅的に説明されているので、ガッツリ使いこなしたい人にオススメです。

常に最新バージョンにしておこう

一度設定すれば使い回し可能!とお伝えしましたが、同じpackage.jsonをずっと使い回していると、バージョンがどんどん古くなっていきます。

適宜最新バージョンにアップデートするようにしましょう。

コチラの記事で解説しました。

Webpackと組み合わせよう

Webpack + Gulpの組み合わせで更に作業効率を上げましょう!

こちらの記事で解説しました。

マークアップエンジニア的には下記がベストプラクティスだと思います。

  • jsのコンパイル + babel + jQueryはwebpack
  • その他の作業はGulp

せいまさん@moyashi3333 
せいまさんからいただいたgulpfile.jsを元に設定しましたm(__)m

はにまわんさん@haniwa008 
ejsの設定ははにわまんさんの記事を参考にしました。
実際の設定でも色々とお知恵を拝借しましたm(__)m

その他の参考記事
最新ビルドシステムGulp 4入門 〜環境構築からタスク作成まで〜

絶対つまずかないGulp 4入門(2019年版)インストールとSassを使うまでの手順

HTML生成に JavaScriptテンプレート「ejs」を使いSublime Textから自動でビルド出来るようにする

gulp 4.0 が正式リリース、v3 からの移行に伴う gulpfile.js ファイルの修正点

この記事を書いた人

のせっち

福岡県出身。早稲田大学卒。創業100年の鉄鋼商社でバンコク駐在最年少抜擢。毎日擦り切れるまで働かなくても幸せに生きている人々を見てフリーランスになりました。
現在は、主にバンコクでWeb制作、物販を中心に生きています。