最初に
タスクランナーとしてgulpは使っているもののgulp用のコマンドだけ覚えて使っているだけなのでわかっている気がしている状態が続いていた。
それではダメだと思いgulp v4が出たのをきっかけに作ってみようと思った。
v4はv3までと書き方が大きく変化していた為新しい方法で覚えるのがいいと思った。
なるべく脱コピペを実践する。
最終的な目標
・とりあえず1から作ってみる
・pugをhtmlにコンパイル
・sassをcssにコンパイルしてmin化
・jsをまとめてコンパイルしmin化
・eslintでjsの構文チェック
・imgを圧縮してコンパイル
・変更をしないファイルをコピー
・ファイルに変更が入った場合にタスクを通してブラウザをリロード
とりあえず1から作ってみる
まずは何をするにもベースとなる'path'を用意するしておく
今回は以下の設定で行うことにした
const path = {
src : {
html : './src/pug/',
css : './src/scss/',
script : './src/scripts/',
images : './src/images/'
},
dist : {
html : './public/',
css : './public/css/',
script : './public/js/',
images : './public/images/'
}
}
ディレクトリ構成
src/
└ html/
└ pug/
└ data/
└ include/
└ common/
└ core/
└ layout/
└ pages/
└ scss/
└ module/
└ lib/
└ script/
└ common/
└ lib/
↓ コンパイル後
public/
└ pages/
└ css/
└ lib/
└ js/
└ lib/
そして最低限以下の設定をする
※パッケージのインストールの仕方はわかってる前提で書きますので省略します
// -- gulp main packages
import gulp from 'gulp'
import fs from 'fs'
// -- gulp other packages
import plumber from 'gulp-plumber'
fsモジュールはnode.jsの標準機能
その中のfs.readFileSyncで簡単にファイルの同期読み込みができる
plumberでStream中に起こるのエラーが原因でタスクが強制停止することを防止
watch中にエラーが発生した場合のwatch自体が停止してしまうのを防止
gulpfile.babel.js
gulpfile.babel.jsでconstを使うためbabelを通す
package.jsonに以下を追加する
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@babel/register": "^7.4.4",
}
pugをhtmlにコンパイル
pugをコンパイルしてdistへ書き出す為に行った方法
// -- gulp html packages
import pug from 'gulp-pug'
pugを使ってコンパイルしてみる。
jsonファイルから読み込んでいる箇所もあるのでまずは変数を持たせる
そしてdistへ書き出し
const html = () => {
const json = JSON.parse(fs.readFileSync( path.src.html + 'data/default.json' ));
return gulp.src( [path.src.html + '**.pug', path.src.html + '**/[^_]*.pug'], { since: gulp.lastRun(html) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted);
this.emit('end');
}
}) )
.pipe(
pug({
pretty: true
})
)
.pipe( gulp.dest(path.dist.html) )
}
sassをcssにコンパイルしてmin化
sassをコンパイルしてmin化するのとreset.cssなどは別ファイルとしてコンパイルできるようにする為に行った方法
// -- gulp sass packages
import autoprefixer from 'gulp-autoprefixer'
import sass from 'gulp-sass'
import sourcemaps from 'gulp-sourcemaps'
import cleanCSS from 'gulp-clean-css'
まずsassでコンパイルする
cleanCSSで圧縮ファイルへ変換
sourcemapsでソースマップを作成する
autoprefixerでベンダープレフィックス付与する
そしてdistへ書き出し
// -- build css task
const css = () => {
return gulp.src( [path.src.css + '**.scss', path.src.css + '**/[^_]*.scss'], { since: gulp.lastRun(css) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted);
this.emit('end');
}
}) )
.pipe(sass({outputStyle: 'expanded'}))
.pipe(cleanCSS())
.pipe(sourcemaps.write())
.pipe(autoprefixer({
overrideBrowserslist: ['last 3 versions'],
cascade: false
}))
.pipe( gulp.dest(path.dist.css) )
}
jsをまとめてコンパイルしmin化
// -- gulp js packages
import uglify from 'gulp-uglify'
import concat from 'gulp-concat'
import babel from 'gulp-babel'
gulp-babel
を入れないとconst
が使えずコンパイルできなかったので注意
concatでファイルを1ファイルにまとめる
ファイル名指定可能なのでall.js
に設定
uglifyでall.js
をmini化する
distファイルへ書き出す
// -- build js task
const js = () => {
return gulp.src( [path.src.script + '**.js', path.src.script + 'common/[^_]*.js'], { since: gulp.lastRun(js) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted);
this.emit('end');
}
}) )
.pipe(babel())
.pipe(concat('all.js'))
.pipe(uglify({
compress: true,
mangle: true,
output:{
comments: /^!/
}
}))
.pipe( gulp.dest(path.dist.script) )
}
eslintでjsの構文チェック
// -- gulp other packages
import gulpEslint from 'gulp-eslint'
const eslint = () => {
return gulp.src( [path.src.script + '**.js', path.src.script + 'common/[^_]*.js'], { since: gulp.lastRun(eslint) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted)
this.emit('end')
}
}) )
.pipe(gulpEslint())
.pipe(gulpEslint.format())
.pipe(gulpEslint.failOnError())
}
eslintを通す前と通した後
// eslint通す前
var setFuga = {
init: function () {
this.setEvent();
},
setEvent: function () {
$('.js-fuga').on('click', function() {
e.preventDefault();
$('.js-fuga-button').submit();
});
}
}
$(function () {
// 処理1
if ($('.js-hoge').length) {
setFuga.init();
}
});
↓ eslintを通すとエラーが発生するのでエラーを解消する
// eslint通した後
const setFuga = {
init() {
this.setEvent()
},
setEvent() {
$('.js-fuga').on('click', el => {
el.preventDefault()
$('.js-fuga-button').submit()
})
},
}
$(() => {
// 処理1
if ($('.js-hoge').length) {
setFuga.init()
}
})
imgを圧縮してコンパイル
jpg,png,gifファイルを画像圧縮する
// -- gulp images packages
import imagemin from 'gulp-imagemin'
import mozjpeg from 'imagemin-mozjpeg'
import pngquant from 'imagemin-pngquant'
import imageminPng from 'imagemin-optipng'
import imageminGif from 'imagemin-gifsicle'
gulp-imagemin
を入れるとその中にjpg,png,gif
のパッケージが入っているので使いやすい
またimagemin-jpegtran
をjpgように当初使用していたがロスレスで圧縮しないとダメっぽいということがわかりimagemin-mozjpeg,imagemin-pngquant
に変更した
svg用のパッケージも入っているが調べた範囲だと使わない方がいいらしい
なので今回はsvgは対象外にしてます
// -- build images task
const img = () => {
return gulp.src( [path.src.images + '**.+(jpg|jpeg|png|gif)', path.src.images + '**/[^_]*.+(jpg|jpeg|png|gif)'], { since: gulp.lastRun(img) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted)
this.emit('end')
}
}) )
.pipe(changed(path.dist.images))
.pipe(imagemin([
mozjpeg({
quality: 80
}),
pngquant(),
imageminPng(),
imageminGif({
interlaced: false,
optimizationLevel: 3,
colors: 180
})
]
))
.pipe( gulp.dest(path.dist.images) )
}
変更をしないファイルをコピー
lib配下にあるjsは何もせずdistへコピーする
// -- build copy task
const copy = () => {
return gulp.src( [path.src.script + 'lib/[^_]*.js'], { since: gulp.lastRun(copy) } )
.pipe( plumber({
errorHandler: function(err) {
console.log(err.messageFormatted);
this.emit('end');
}
}) )
.pipe( gulp.dest(path.dist.script + 'lib/') )
}
ファイルに変更が入った場合にタスクを通してブラウザをリロード
ブラウザシンクが使えるように設定する
watchをしてファイルに変更が入った場合ブラウザのリロードをする
// -- gulp other packages
import rimraf from 'rimraf'
import browserSync from 'browser-sync'
以下のserver
指定でブラウザシンクの設定をして初期ファイルの表示をlist.html
に設定
reload
のタスクを用意してwatchが走った場合に最後にリロードできるように設定
// -- build server task
const server = done => {
return browserSync.init({
open: 'external',
server: {
baseDir: path.dist.html,
index : 'list.html'
}
})
done();
}
const reload = done => {
browserSync.reload();
done();
}
// -- build watch task
const watch = done => {
gulp.watch([path.src.html + '**.pug', path.src.html + '**/*.pug'], gulp.parallel(html,reload))
gulp.watch([path.src.css + '**.scss', path.src.css + '**/*.scss'], gulp.parallel(css,reload))
gulp.watch([path.src.script + '**.js', path.src.script + 'common/*.js'], gulp.parallel(js,reload))
gulp.watch([path.src.images + '**.+(jpg|jpeg|png|gif)', path.src.images + '**/[^_]*.+(jpg|jpeg|png|gif)'], gulp.parallel(img,reload))
done();
}
gulp.series....直列処理
gulp.parallel..並列処理
tags
gulp4, js, pug, Sass, babel, ESlint
感想
今まで使っていたgulpの機能がそもそもどうやって動いているのか、役割が何なのかを理解することができた
使用するパッケージも類似パッケージが多数あり何を選定するかも重要であるかが理解でき選定したパッケージ次第で書きかたなどが違うことなどもわかった
最初は苦手意識が高くエラーも多く吐き出して動かなかったがエラーを1つ1つ解消していくことにより理解も深まった感があった
eslintを導入する事でjsの書き方を統一する事ができるがエラーチェックが厳しいのでエラーを解消するのに時間がかかった