こちらの記事は執筆から1年以上が経過しています。
Gulpやパッケージの更新により一部のタスクが動作しない可能性があります。
最新情報はnoteにて更新中ですので、そちらをご確認ください。
こんにちは!フリーランスエンジニアのせっち@nosecchi01です。
コーダーが知っておきたいツールの一つとしてGulpがあります。
Sassを覚えたころにGulpの存在を知るという人も多いのではないでしょうか?
この記事ではGulpの詳しい設定方法を解説します。
現役コーダーさんからわかりやすいというお褒めの言葉をいただきました。
大変わかりやすい記事をありがとうございました!gulp導入の際の大きなヒントとなりました!
— 👁🗨くー(Sait) (@sait_SMPE) 2019年7月2日
自分のGulp構成を見直すためにググってたら(pc熱くなるから小規模では避けてきた)、神記事見つけましたねぇ。
これは文字通り万人のベストプラクティスになりそうなってそうで、まじリスペクトです@yukinouz1さん
👼https://t.co/oUcDq3mO7F— しょーご@web制作フリーランス (@samuraibrass) 2019年7月19日
私の記事だと気づかず記事のツイートをしていただいた事もあったようで、わかりやすさで選んでいただいておりますm(_ _)m
え、待って!この記事よく見たらせっちさんのブログじゃないすか!
自然検索で普通に2~3番目に出て気づかずに貼ったんですけど!!笑
— ヤマダ🐺Webデザイナー🐺 (@Y_Macccky) 2019年6月30日
#gulp ではじめるweb制作ワークフロー入門とSassの教科書を読み込みました。gulpとは何か、環境構築の細かい手順やgulpによる処理の流れを学びました。
— こうへい@データアナリスト (@kei_01011) July 22, 2019
改めて、せっちさん@yukinouz1の記事を読むと、要点を簡潔にまとめられていて感動!感謝です。https://t.co/0i1U2UeLPk pic.twitter.com/yBKESRhLmj
それではいってみましょう!
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()を使います。
・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から自動でビルド出来るようにする