gulp ver4
gulpとは
gulpはNode.jsをベースとしたストリーミングビルドシステムです。
タスクランナーと認識されるが、正確には異なります。
タスクランナーは、それぞれのタスクを順番に記述して実行するもの
ストリーミングビルドシステムは、入力されたものに対して処理をいれていき、1つの流れの中でビルドを行うアプローチ
例)
1. sass ファイルのコンパイルタスク
2. css にプレフィックスをつけるタスク
3. css の順番を並び替えるタスク
ストリームによる処理の利点
gulpはファイルをストリームとして扱いながら処理を行います。
ストリームがどういったものかイメージしやすいように、gulpにおけるタスクの例をあげます。
次のタスクは.pug形式のファイルに対して処理を行うものです。
code:js
export const compilePug = done => {
gulp.src(pugPaths.src.pug)
// エラーハンドリング
.pipe(plugins.plumber({}))
// 出力の設定
.pipe(plugins.pug())
// 出力先
.pipe(gulp.dest(pugPaths.dest.html))
done();
}
各処理を実行した結果を.pipe()によって次の処理に渡すことで、複数の処理を簡潔にまとめることが可能です。それぞれの処理の間に新たに処理を追加したい、といった場合には.pipe()を増やすだけでできます。タスクが何をするのか、わかりやすく直感的に書くことができます。
gulpでやれること(実際にフロントエンド開発でやってること)
pug等 htmlテンプレートエンジンのコンパイル
sass等 cssのコンパイル
typescript, ES6で書かれたjsのコンパイル
スプライト (複数画像を1枚の画像に合成して、表示範囲を絞ることにより容量を圧縮する技術の事)
画像ファイルの圧縮
ファイルのコピー
localhostでサーバを立てる
ファイルの変更を検知
環境
babel 6系
gulp 4系 (3系と書き方が結構違うので注意)
pug
code:js
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
const plugins = gulpLoadPlugins();
//pug入力先、html出力先を記述
export const pugPaths = {
src: {
pug: "src/view/*.pug",
},
dest: {
html: "build/",
},
};
// sass以降↑省略 特別importしてるものがあれば記載します
export const compilePug = done => {
gulp.src(pugPaths.src.pug)
// エラーハンドリング
.pipe(plugins.plumber({
errorHandler: plugins.notify.onError('<%= error.message %>')
}))
// 出力の設定
.pipe(plugins.pug({
pretty: true,
locals: {
env: {
IS_PRODUCTION: false
}
},
}))
// 出力先
.pipe(gulp.dest(pugPaths.dest.html))
done();
}
gulp-load-plugins
gulp で利用するプラグインをひとつひとつ読み込むと大量の require が並ぶことになる。gulp-load-plugins を利用すると package.json から自動で読み込み利用できるようになり、require する必要がなくなる。
package.jsonにあるgulp-*だけ
plugins.pug() は
import pug from 'gulp-pug';
pug() と同様
gulpfile.babel.js
code:js
/**
* @file gulp
*
*/
import { series, parallel } from 'gulp'
import { compilePug } from './gulp/tasks/pug'
exports.default = parallel(compilePug)
defaultでexportsしたものがyarn run gulpにより実行されます。
sass
code:js
// sass 実行タスク
export const compileSass = done =>{
gulp.src(sassPaths.src.scss)
// エラーハンドリング
.pipe(plugins.plumber({
errorHandler: plugins.notify.onError('<%= error.message %>')
}))
// Sassの@importにおけるglobを有効にする(@import "layout/**"と書けるようにする)
.pipe(plugins.sassGlob())
// sassのlint
.pipe(plugins.sassLint({
options: {
formatter: 'stylish',
'merge-default-rules': false
},
files: {ignore: '**/*.scss'},
rules: {
'no-ids': 1,
'no-mergeable-selectors': 0
},
configFile: 'config/other/.sass-lint.yml'
}))
// 指定したオプションによってフォーマットする
.pipe(plugins.sassLint.format())
// lintによるエラーが検出されたらタスク失敗させる
.pipe(plugins.sassLint.failOnError())
// 出力の設定
.pipe(plugins.sass())
// ベンダープレフィックスの自動付与
.pipe(plugins.autoprefixer())
// ファイル名を変える
.pipe(plugins.rename({extname: '.min.css'}))
// minifyする(gulp-minify-css は非推奨)
.pipe(plugins.cleanCss())
.pipe(gulp.dest(sassPaths.dest.css))
done();
}
postcssというCSSをコンパイルできるツールをgulpから呼び出すことによって上記と同様のことをする場合もあるが、今回はgulpのプラグインを使うやり方で。
js
code:js
export const compileScript = done => {
gulp.src(jsPaths.src.js)
// エラーハンドリング
.pipe(plugins.plumber({
errorHandler: plugins.notify.onError('<%= error.message %>')
}))
// jsのlint
.pipe(plugins.eslint({
useEslintrc: true // .eslintrc を参照
}))
.pipe(plugins.eslint.format())
.pipe(plugins.eslint.failAfterError())
// minify
.pipe(plugins.rename({extname: '.min.js'}))
.pipe(plugins.uglify())
// 出力
.pipe(gulp.dest(jsPaths.dest.js))
done();
}
gulpからwebpackを呼び出すこともできる。
sprite
code:js
export const sprite = done => {
const spriteData = gulp.src(spritePaths.src.img)
.pipe(plugins.spritesmith({
imgName: 'sprite.png', // スプライト画像
cssName: 'sprite.css', // 生成される CSS テンプレート
imgPath: 'build/assets/images/sprite/sprite.png', // 生成される CSS テンプレートに記載されるスプライト画像パス
cssFormat: 'css', // フォーマット拡張子
cssVarMap: (sprite) => {
sprite.name = 'sprite-' + sprite.name; // 生成される CSS テンプレートに変数の一覧を記述
}
}));
spriteData.img.pipe(gulp.dest(spritePaths.dest.img)); // imgName で指定したスプライト画像の保存先
spriteData.css.pipe(gulp.dest(spritePaths.dest.css)); // cssName で指定した CSS テンプレートの保存先
done();
}
https://gyazo.com/3288b8d18b5b6bd2387e97d6f468d8c9
生成されたsprite画像
https://gyazo.com/8a2baea66907e8163dcb780bdde84ec1
生成されたcss
code:css
/*
Icon classes can be used entirely standalone. They are named after their original file names.
Example usage in HTML:
display: block sprite:
<div class="icon-home"></div>
To change display (e.g. display: inline-block;), we suggest using a common CSS class:
// CSS
.icon {
display: inline-block;
}
// HTML
<i class="icon icon-home"></i>
*/
.icon-sprite-cat {
background-image: url(../images/sprite/sprite.png);
background-position: 0px 0px;
width: 150px;
height: 150px;
}
.icon-sprite-crow {
background-image: url(../images/sprite/sprite.png);
background-position: -150px 0px;
width: 150px;
height: 150px;
}
.icon-sprite-deer {
background-image: url(../images/sprite/sprite.png);
background-position: 0px -150px;
width: 150px;
height: 150px;
}
.icon-sprite-penguin {
background-image: url(../images/sprite/sprite.png);
background-position: -150px -150px;
width: 150px;
height: 150px;
}
.icon-sprite-rabbit {
background-image: url(../images/sprite/sprite.png);
background-position: -300px 0px;
width: 150px;
height: 150px;
}
.icon-sprite-raccoon {
background-image: url(../images/sprite/sprite.png);
background-position: -300px -150px;
width: 150px;
height: 150px;
}
imagemin
code:js
import mozjpeg from 'imagemin-mozjpeg';
import pngquant from 'imagemin-pngquant';
export const imagemin = done => {
gulp.src(imageminPaths.src.img)
// エラーハンドリング
.pipe(plugins.plumber({
errorHandler: plugins.notify.onError('<%= error.message %>')
}))
// 出力の設定
.pipe(plugins.imagemin([
pngquant({
speed: 1 // スピード
}),
mozjpeg({ quality: 65 }), // 画質 65%
plugins.imagemin.svgo(),
plugins.imagemin.optipng(),
plugins.imagemin.gifsicle({ optimizationLevel: 3 }) // 圧縮率
]))
// 出力先
.pipe(gulp.dest(imageminPaths.dest.img));
done();
}
copy
code:js
export const copy = done => {
gulp.src(copyPaths.src.html)
// エラーハンドリング
.pipe(plugins.plumber({
errorHandler: plugins.notify.onError('<%= error.message %>')
}))
// 出力先
.pipe(gulp.dest(copyPaths.dest.html))
done();
}
server
code:js
import browserSync from 'browser-sync';
const config = {
port: 4000,
baseDir: './build/',
index: 'index.html'
}
// 名前をつけて作成する
const bs = browserSync.create('browser-sync');
// 実行タスク
export const serverInit = done =>{
bs.init({
port: config.port,
server: {
baseDir: config.baseDir,
index : config.index
},
ui: false
});
done();
}
// ブラウザリロード
export const bsReload = done =>{
bs.reload();
done();
}
watch と最終的なgulpのdefaultタスク
code:js
/**
* @file gulp
*
*/
import { series, parallel, watch } from 'gulp'
import { pugPaths, compilePug } from './gulp/tasks/pug'
import { sassPaths, compileSass } from './gulp/tasks/sass'
import { jsPaths, compileScript } from './gulp/tasks/js'
import { spritePaths, sprite } from './gulp/tasks/sprite'
import { imageminPaths, imagemin } from './gulp/tasks/imagemin'
import { copyPaths, copy } from './gulp/tasks/copy'
import { serverInit, bsReload } from './gulp/tasks/server'
// ファイルの変更監視タスク
const watchFile = done =>{
watch(pugPaths.src.pug, series(compilePug, bsReload));
watch(sassPaths.src.scss, series(compileSass, bsReload));
watch(jsPaths.src.js, series(compileScript, bsReload));
watch(spritePaths.src.img, series(sprite, bsReload));
watch(imageminPaths.src.img, series(imagemin, bsReload));
watch(copyPaths.src.html, series(imagemin, bsReload));
done();
}
exports.default = series(
sprite,
parallel(
compileSass,
compileScript,
compilePug,
imagemin,
),
copy,
serverInit,
watchFile
);
gulp不要論もあります
npm scriptでできる
gulpは不要な抽象化レイヤー
抽象化すると実際になりやってるのか分からない
大量なgulpプラグインが必要
プラグイン作者への依存
gulp上でwebpackやBrowsersyncを統合するのが大変
gulp経由せずそのままnpm scriptで呼び出した方がシンプル
gulpプラグイン対応してないモジュールが増えてる
感想コーナー
👍 tamuraryoya tamuraryoya.icon がいいねしました on 2021/5/13