⚠︎Gulp4になって地味に記法が変わっていたので、本記事はちゃんとGulp4で推奨されている記法に沿って書いております!
静的ページをガリガリ書こう!とはいえ…
制作する上でたくさん処理がありますよね
sassのコンパイルから始まり、ベンダープレフィックスも書かなきゃいけないし、画像の最適化もしたいし、他にも他にも……
め、めんどくさ〜〜い!
📣 なら自動化しましょう!
簡単に導入できて、カスタマイズ自在、様々な処理を自動化したいそのお悩み、解決できますよ
そう、gulpならね
Gulp.js A toolkit to automate & enhance your workflow |
gulpとは、webページなどの制作における煩雑な処理を自動化するタスクランナーツールです
gulpを使用するにはNode.jsが必要なので、インストールした状態で記事を読み進めてください
gulpにやってもらうこと
- ローカルサーバーの立ち上げ(プロキシ指定ver.もあるよ)
- ファイルの監視、自動リロード
- ビルド失敗時のデスクトップ通知
- 画像の最適化
- pugの使用とコンパイル
- sassのコンパイル、ベンダープレフィックスの自動付与、cssの圧縮
- Javascriptの検証、圧縮
まずはサクッとgulpをインストール🥤
プロジェクトのディレクトリを初期化して、
npm init -y
gulpをインストール
npm install --save-dev gulp
# 完成品 先に、**コピペしたら前項の機能全部使える**package.jsonとgulpfileを置いておきます 次項からの[タスク別解説](#タスク別解説)をすべて合体するとこの形になります
「説明なんかいらん!とりあえず動くものよこせ!」
といった方は、これをコピペして自由に俺流にカスタマイズしてください………泣いてないわよ
package.json👇
("name"
と"repository" > "url"
は適宜変えてください)
{
"name": "プロジェクト名",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git://github.com/xxx/xxx.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"browser-sync": "^2.26.7",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^7.0.1",
"gulp-eslint": "^6.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-pleeease": "^2.0.2",
"gulp-plumber": "^1.2.1",
"gulp-pug": "^4.0.1",
"gulp-sass": "^4.0.2",
"gulp-svgmin": "^2.2.0",
"gulp-uglify": "^3.0.2",
"node-notifier": "^7.0.2",
"process": "^0.11.10"
}
}
上コピペしたら、npm install
gulpfile👇
(assets_dir
のパスとsrc_file
のパスは適宜変えてください)
(ESLintを使用するので、適宜.eslintrc.json
を用意してください)
const gulp = require('gulp');
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const pleeease = require('gulp-pleeease');
const plumber = require('gulp-plumber');
const uglify = require('gulp-uglify');
const eslint = require('gulp-eslint');
const imgMin = require('gulp-imagemin');
const jpgMin = require('imagemin-mozjpeg');
const pngMin = require('imagemin-optipng');
const gifMin = require('imagemin-gifsicle');
const svgMin = require('gulp-svgmin');
const browserSync = require('browser-sync');
const process = require('process');
const notifier = require('node-notifier');
const pug = require('gulp-pug');
// setting
const assets_dir = {
css: 'assets/css/',
js: 'assets/js/',
img: 'assets/img/',
root: './assets/'
};
const src_file = {
scss: 'src/scss/**/*.scss',
js: 'src/js/**/*.js',
img: 'src/img/**/*.+(jpg|jpeg|png|gif)',
svg: 'src/img/**/*.svg',
pug: '**/*.pug'
};
// task
function exit(done){
process.exit(0);
done();
}
exports.task = exit;
const errorHandler = function(error) {
console.log(error.message);
notifier.notify({
message: 'Putted the error in the log',
title: 'ERROR!',
appIcon: './err_icon.jpeg'
});
// gulp.task(exit);
};
function pug_compile(){
return gulp
.src(src_file.pug)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(pug())
.pipe(gulp.dest('./'));
}
exports.task = pug_compile;
function sass_compile(){
return gulp
.src(src_file.scss)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(sass())
.pipe(pleeease())
.pipe(autoprefixer())
.pipe(gulp.dest(assets_dir.css));
}
exports.task = sass_compile;
function js_min(){
return gulp
.src(src_file.js)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failOnError())
.pipe(uglify())
.pipe(gulp.dest(assets_dir.js));
}
exports.task = js_min;
function img_min(){
return gulp
.src(src_file.img)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(imgMin([
jpgMin(),
pngMin(),
gifMin({
optimizationLevel: 3
})
]))
.pipe(gulp.dest(assets_dir.img));
}
function svg_min(){
return gulp
.src(src_file.svg)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(svgMin())
.pipe(gulp.dest(assets_dir.img));
}
exports.task = img_min;
exports.task = svg_min;
function serve(done) {
browserSync.init({
// ローカルサーバー
server: {
baseDir: './'
},
port: 3000
// プロキシ指定
// proxy: 'http://●●/',
// Host: '●●.com',
// open: 'external'
});
done();
}
exports.task = serve;
function reload(done){
browserSync.reload();
done();
}
exports.task = reload;
function watch(done){
gulp.watch(src_file.pug, gulp.task(pug_compile));
gulp.watch(src_file.scss, gulp.task(sass_compile));
gulp.watch(src_file.js, gulp.task(js_min));
gulp.watch(src_file.img, gulp.task(img_min));
gulp.watch(src_file.svg, gulp.task(svg_min));
gulp.watch(['assets/**/*', '**/*.html'], gulp.task(reload));
done();
}
exports.task = watch;
// default
gulp.task('default', gulp.series(serve, watch));
上コピペしたら、npx gulp
で $\textrm{So Happy...}$
# タスク別解説 前項のこだわりgulpfileの中身を、タスク別で分けて解説していきます 必要なタスクを組み合わせて、自分のプロジェクトに応じたgulpfileを作ってみてください
gulpfileの最後に書いているタスク呼び出しは、この記事👇が参考になります
複数タスクを組み合わせたいときに参考にしてみてください
Gulp - v4 の series と parallel を使って直列・並列処理を制御する Gulp v4 で導入された series と parallel を使ってみました。 |
本記事でのエントリーポイントと出力先パスは以下の通りに設定しています
自分のプロジェクトのディレクトリ構成に応じて、適宜変更してください
// setting
const assets_dir = {
css: 'assets/css/',
js: 'assets/js/',
img: 'assets/img/',
root: './assets/'
};
const src_file = {
scss: 'src/scss/**/*.scss',
js: 'src/js/**/*.js',
img: 'src/img/**/*.+(jpg|jpeg|png|gif)',
svg: 'src/img/**/*.svg',
pug: '**/*.pug'
};
✂︎-------------< 以下、解説 >-------------✂︎
ローカルサーバーの立ち上げ(プロキシ指定ver.もあるよ)
npm install --save-dev gulp browser-sync
const gulp = require('gulp');
const browserSync = require('browser-sync');
function serve(done) {
browserSync.init({
// ローカルサーバー
server: {
baseDir: './'
},
port: 3000
// プロキシ指定
// proxy: 'http://●●/',
// Host: '●●.com',
// open: 'external'
});
done();
}
exports.task = serve;
gulp.task('serve', serve); //gulp serve 実行でserveタスクが実行される
ローカルサーバーの立ち上げには、browser-sync
パッケージを使用します
⚠︎便宜上プロキシ指定しているオプションはコメントアウトしています(基本的にどちらかを設定するため)
-
baseDir
- サーバー立ち上げた時に参照するディレクトリ
-
port
- 開放するポート
-
proxy
- 仮想サーバーのURL
-
Host
- ホスト名
-
open
-
external
外部URLを開く
-
このままサーバーを立ち上げると、localhost:3000が開きます
プロキシ指定する際は、server
とport
オプションを削除して、proxy
Host
open
オプションのコメントアウトを外してください
ファイルの監視、自動リロード
npm install --save-dev gulp browser-sync
const gulp = require('gulp');
'browser-sync');
// 自動リロード
function reload(done){
browserSync.reload();
done();
}
exports.task = reload;
// ファイルの監視、ファイル更新時自動リロード
function watch(done){
gulp.watch('監視するファイル(パス含む)', gulp.series('タスク名')); //ファイルの監視
gulp.watch('監視するファイル(パス含む)', gulp.series(reload)); //ファイル更新時自動リロード
done();
}
exports.task = watch;
gulp.task('watch', watch); //gulp watch 実行でwatchタスクが実行される
リロードはbrowser-sync
パッケージを使用し、監視はgulp
パッケージでできます
リロードタスクと監視タスクは分けています
どちらもAPIをそのまま使用するので、特にこちらでオプションを指定する必要はありません
ファイル監視のタスクでは、第一引数のファイルが変更された時に、第二引数のタスクが実行されます
ファイル更新時自動リロードのタスクでは、第一引数のファイルが変更された時に、第二引数のreload
タスクが実行されます
監視したいファイルを複数指定したい時は配列に入れましょう
ビルド失敗時のデスクトップ通知
npm install --save-dev gulp node-notifier process
const gulp = require('gulp');
const process = require('process');
const notifier = require('node-notifier');
// gulpの停止
// function exit(done){
// process.exit(0);
// done();
// }
// exports.task = exit;
// タスク失敗通知
const errorHandler = function(error) {
console.log(error.message);
notifier.notify({
message: 'Putted the error in the log',
title: 'ERROR!',
appIcon: './err_icon.jpeg'
});
// gulp.task(exit);
};
⚠︎次項以降でこのタスクを使用するため、便宜上プロセス停止部分はコメントアウトしています
エラー吐いた時にプロセスも終了したい場合は、このコメントアウトを外してください
プロセス制御にprocess
パッケージ、デスクトップ通知にnode-notifier
パッケージを使用します
動作するとこんな感じ👇
-
message
- 通知の本文
-
title
- 通知の見出し
-
appIcon
- 画像でいうと現場猫の部分
なにもヨシ!ではない
癒し画像にするとエラー吐いても心穏やかにいられるよ
- 画像でいうと現場猫の部分
エラーログはコンソールに吐き出され、プロセスは終了します
このタスクは基本的に独立して使用するものではなく、他のタスクに組み込んで使用するので、exports.task
でタスク定義は行いません
画像の最適化
npm install --save-dev gulp gulp-plumber gulp-imagemin gulp-svgmin
const gulp = require('gulp');
const plumber = require('gulp-plumber');
const imgMin = require('gulp-imagemin');
const svgMin = require('gulp-svgmin');
const jpgMin = require('imagemin-mozjpeg');
const pngMin = require('imagemin-optipng');
const gifMin = require('imagemin-gifsicle');
function img_min(){
return gulp
.src(src_file.img)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(imgMin([
jpgMin(),
pngMin(),
gifMin({
optimizationLevel: 3
})
]))
.pipe(gulp.dest(assets_dir.img));
}
function svg_min(){
return gulp
.src(src_file.svg)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(svgMin())
.pipe(gulp.dest(assets_dir.img));
}
exports.task = img_min;
exports.task = svg_min;
gulp.task('imageMin', gulp.parallel(img_min, svg_min)); //gulp imageMin 実行でimg_minタスクとsvg_minタスクが実行される
エラー起因のプロセス強制終了を防ぐためにgulp-plumber
パッケージ、
画像圧縮するためにgulp-imagemin
gulp-svgmin
パッケージを使用し、
画像ファイルそれぞれの拡張子に対応するため、imagemin-mozjpeg
imagemin-optipng
imagemin-gifsicle
プラグインを呼び出しています
-
plumber
-
errorHandler
エラーになった時の挙動を指定できます。今回は先に書いたエラー通知タスクを実行するようにしています
-
-
imgMin
-
gifMin
-
optimizationLevel
最適化レベルを1〜3で指定します
今回は一番レベルの高い3を指定しています 時間はかかりますがより精密に最適化が行われます
-
-
タスク内では、
エントリーポイントの指定 → plumberの起動 → 最適化 → 指定した出力先に吐き出し
の順で動作しています
pugの使用とコンパイル
npm install --save-dev gulp gulp-pug gulp-plumber
const gulp = require('gulp');
const plumber = require('gulp-plumber');
const pug = require('gulp-pug');
function pug_compile(){
return gulp
.src(src_file.pug)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(pug())
.pipe(gulp.dest('./'));
}
exports.task = pug_compile;
gulp.task('pug', pug_compile); //gulp pug 実行でpug_compileタスクが実行される
エラー起因のプロセス強制終了を防ぐためにgulp-plumber
パッケージ、
pugの使用、HTMLへのコンパイルをするためにgulp-pug
パッケージを使用しています
-
plumber
-
errorHandler
エラーになった時の挙動を指定できます。今回は先に書いたエラー通知タスクを実行するようにしています
-
タスク内では、
エントリーポイントの指定 → plumberの起動 → pugのコンパイル → 指定した出力先に吐き出し
の順で動作しています
sassのコンパイル、ベンダープレフィックスの自動付与、cssの圧縮
npm install --save-dev gulp gulp-sass gulp-plumber gulp-pleeease gulp-autoprefixer
const gulp = require('gulp');
const plumber = require('gulp-plumber');
const pleeease = require('gulp-pleeease');
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
function sass_compile(){
return gulp
.src(src_file.scss)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(sass())
.pipe(pleeease())
.pipe(autoprefixer())
.pipe(gulp.dest(assets_dir.css));
}
exports.task = sass_compile;
gulp.task('sass', sass_compile); //gulp sass 実行でsass_compileタスクが実行される
エラー起因のプロセス強制終了を防ぐためにgulp-plumberパッケージ、
sassの使用、cssへのコンパイルをするためにgulp-sass
パッケージ、
コンパイルされたcssの圧縮をするためにgulp-pleeease
パッケージ、
ベンダープレフィックスの自動付与をするためにgulp-autoprefixer
パッケージを使用しています
-
plumber
-
errorHandler
エラーになった時の挙動を指定できます。今回は先に書いたエラー通知タスクを実行するようにしています
-
タスク内では、
エントリーポイントの指定 → plumberの起動 → sassのコンパイル → cssの圧縮 → ベンダープレフィックスの付与 → 指定した出力先に吐き出し
の順で動作しています
Javascriptの検証、圧縮
npm install --save-dev gulp gulp-plumber gulp-uglify gulp-eslint
const gulp = require('gulp');
const plumber = require('gulp-plumber');
const uglify = require('gulp-uglify');
const eslint = require('gulp-eslint');
function js_min(){
return gulp
.src(src_file.js)
.pipe(plumber({
errorHandler: errorHandler
}))
.pipe(eslint())
.pipe(eslint.format())
.pipe(eslint.failOnError())
.pipe(uglify())
.pipe(gulp.dest(assets_dir.js));
}
exports.task = js_min;
gulp.task('jsMin', js_min); //gulp jsMin 実行でjs_minタスクが実行される
{
"extends": ["eslint:recommended"],
"env": {
"browser": true
}
}
エラー起因のプロセス強制終了を防ぐためにgulp-plumber
パッケージ、
構文チェックのためにgulp-eslint
パッケージ、
Javascriptの圧縮をするためにgulp-uglify
パッケージを使用しています
-
plumber
-
errorHandler
エラーになった時の挙動を指定できます。今回は先に書いたエラー通知タスクを実行するようにしています
-
ESLintを使用するには設定ファイルが必要です
.eslintrc.json
を用意します
中身では、ESLintの推奨設定を継承して、ESLintで構文チェックする対象コードの実行環境を指定しています
タスク内では、
エントリーポイントの指定 → plumberの起動 → 構文チェック → Javascriptの圧縮 → 指定した出力先に吐き出し
の順で動作しています
以上! 面倒で煩雑な処理は全部gulpにお任せすれば、コーディングに集中できますね🎉
コピペしてうまく動作しないなどの不具合があったり、コードに間違いなどありましたら、編集リクエストやコメントで教えていただけますと助かります🙇♀️
おまけ
今回は紹介しませんでしたが、Typescriptのパッケージもあるみたい
https://www.npmjs.com/package/gulp-typescript