LoginSignup
4
3

More than 3 years have passed since last update.

gulp v4とbabelでタスクを作ってみた

Last updated at Posted at 2019-06-27

最初に

タスクランナーとしてgulpは使っているもののgulp用のコマンドだけ覚えて使っているだけなのでわかっている気がしている状態が続いていた。
それではダメだと思いgulp v4が出たのをきっかけに作ってみようと思った。
v4はv3までと書き方が大きく変化していた為新しい方法で覚えるのがいいと思った。
なるべく脱コピペを実践する。

最終的な目標

とりあえず1から作ってみる
pugをhtmlにコンパイル
sassをcssにコンパイルしてmin化
jsをまとめてコンパイルしmin化
eslintでjsの構文チェック
imgを圧縮してコンパイル
変更をしないファイルをコピー
ファイルに変更が入った場合にタスクを通してブラウザをリロード

とりあえず1から作ってみる

まずは何をするにもベースとなる'path'を用意するしておく
今回は以下の設定で行うことにした

gulpfile.babel.js
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/

そして最低限以下の設定をする
※パッケージのインストールの仕方はわかってる前提で書きますので省略します

gulpfile.babel.js
// -- 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に以下を追加する

package.json
  "devDependencies": {
    "@babel/core": "^7.4.5",
    "@babel/preset-env": "^7.4.5",
    "@babel/register": "^7.4.4",
  }

pugをhtmlにコンパイル

pugをコンパイルしてdistへ書き出す為に行った方法

gulpfile.babel.js
// -- gulp html packages
import pug from 'gulp-pug'

pugを使ってコンパイルしてみる。
jsonファイルから読み込んでいる箇所もあるのでまずは変数を持たせる
そしてdistへ書き出し

gulpfile.babel.js
 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などは別ファイルとしてコンパイルできるようにする為に行った方法

gulpfile.babel.js
// -- 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へ書き出し

gulpfile.babel.js
// -- 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化

gulpfile.babel.js
// -- 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ファイルへ書き出す

gulpfile.babel.js
// -- 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の構文チェック

gulpfile.babel.js
// -- gulp other packages
import gulpEslint  from 'gulp-eslint'
gulpfile.babel.js
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を通す前と通した後

fuga.js
// 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ファイルを画像圧縮する

gulpfile.babel.js
// -- 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は対象外にしてます

gulpfile.babel.js
// -- 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へコピーする

gulpfile.babel.js
// -- 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をしてファイルに変更が入った場合ブラウザのリロードをする

gulpfile.babel.js
// -- gulp other packages
import rimraf      from 'rimraf'
import browserSync from 'browser-sync'

以下のserver指定でブラウザシンクの設定をして初期ファイルの表示をlist.htmlに設定
reloadのタスクを用意してwatchが走った場合に最後にリロードできるように設定

gulpfile.babel.js
// -- 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の書き方を統一する事ができるがエラーチェックが厳しいのでエラーを解消するのに時間がかかった

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3