hacca8

静的なサイト用のgulp4を作成

静的サイトの作業用にgulpを導入します。
バージョン3系までしか作ったことがなかったので、学習も兼ねてgulp4で作成しています。

今回はPug、Sassをコンパイルしてbrowser-syncを利用します。
JavaScriptは組み込んではいますが、案件によって変わるので特に処理は行ってません。
こちらを利用される場合は、適宜必要なプラグインや処理を追加してください。

作成ディレクトリ、ファイル

リポジトリ: gulp4-static-web

  • 構成 以下のディレクトリ構成で動作します。
.
├── gulpfile.js
├── node_modules
├── public
└── src
    ├── js
    ├── pug
    └── sass
  • package.json
{
  "dependencies": {
    "autoprefixer": "^10.4.7",
    "browser-sync": "^2.27.10",
    "gulp": "^4.0.2",
    "gulp-load-plugins": "^2.0.7",
    "gulp-notify": "^4.0.0",
    "gulp-plumber": "^1.2.1",
    "gulp-postcss": "^9.0.1",
    "gulp-pug": "^5.0.0",
    "gulp-sass": "^5.1.0",
    "sass": "^1.53.0"
  },
  "browserslist": [
    "last 2 versions"
  ]
}
  • gulpfile.js
const { src, dest, watch, series, parallel } = require('gulp');
const $ = require('gulp-load-plugins')({
  pattern: [
    'gulp-*',
    'autoprefixer',
    'browser-sync',
  ]
});
const sass = $.sass(require('sass')); // M1 Mac

// path list
const srcPathList = {
  pug: './src/pug/**/*.pug',
  sass: './src/scss/**/*.scss',
  js: './src/js/**/*.js'
}
const publicPathList = {
  pug: './public/',
  sass: './public/css/',
  js: './public/js/',
  base: './public/'
}

// func
const pugCompile = () => {
  return src(srcPathList.pug)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe($.pug({ pretty: true }))
    .pipe(dest(publicPathList.pug));
}
const sassCompile = () => {
  return src(srcPathList.sass)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe(sass.sync({ outputStyle: 'expanded' }))
    .pipe($.postcss([ $.autoprefixer() ]))
    .pipe(dest(publicPathList.sass));
}
const jsCompile = () => {
  return src(srcPathList.js)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe(dest(publicPathList.js));
}
const bsReload = (done) => {
  $.browserSync.reload();
  done();
}
const bsFunc = () => {
  $.browserSync({
    server: {
      baseDir: publicPathList.base
    },
    reloadOnRestart: true
  });
}

// watch list
const watchFileList = () => {
  watch(srcPathList.pug, series(pugCompile, bsReload));
  watch(srcPathList.sass, series(sassCompile, bsReload));
  watch(srcPathList.js, series(jsCompile, bsReload));
}

// exports
exports.default = series(
  parallel(pugCompile, sassCompile, jsCompile),
  parallel(watchFileList, bsFunc)
);

gulpfileの中身を順に見ていきます。

gulpfile.js

モジュールの読み込み

以下の記述で、gulpを読み込んでいます。

const { src, dest, watch, series, parallel } = require('gulp');

こちらでも構いません。

const gulp = require('gulp'); // こちらの場合、利用の際は gulp.src(...) などの記述になる

また、gulp-load-pluginsを使用して、読み込みを簡略化しています。
patternオプションでgulp-以外から始まるプラグインも記述しておくと、一緒に読み込めます。
const $で宣言すると、使用する際は$.plumberのような記述になります。(gulp-の部分を省略できる)

const $ = require('gulp-load-plugins')({
  pattern: [
    'gulp-*', // gulp-から始まるプラグイン
    'autoprefixer', // gulp-以外
    'browser-sync', // gulp-以外
  ]
});

M1 Macの場合は、sassの読み込みに注意が必要です。

const sass = $.sass(require('sass')); // M1 Mac
// gulp-load-pluginsを使わない場合は const sass = require('gulp-sass')(require('sass'));

作業ディレクトリと出力先の指定

srcディレクトリのファイルを処理して、publicディレクトリに出力します。

// path list
const srcPathList = {
  pug: './src/pug/**/*.pug',
  sass: './src/scss/**/*.scss',
  js: './src/js/**/*.js'
}
const publicPathList = {
  pug: './public/',
  sass: './public/css/',
  js: './public/js/',
  base: './public/'
}

処理用の関数

各ファイルのコンパイルや処理関数を設定します。
gulp4ではgulp.taskは非推奨になりましたので、関数を設定してexportsで実行する流れになります。
いずれもgulp-plumber、gulp-notifyでエラーを出力しています。
sassは、sass({ outputStyle: 'expanded' })の記述でも動作しますが、sass.syncの方が処理が速いとのことで利用しています。
(非同期処理を同期処理にして速度を改善しているとのこと)

// func
const pugCompile = () => {
  return src(srcPathList.pug)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe($.pug({ pretty: true }))
    .pipe(dest(publicPathList.pug));
}
const sassCompile = () => {
  return src(srcPathList.sass)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe(sass.sync({ outputStyle: 'expanded' }))
    .pipe($.postcss([ $.autoprefixer() ]))
    .pipe(dest(publicPathList.sass));
}
const jsCompile = () => {
  return src(srcPathList.js)
    .pipe($.plumber({ errorHandler: $.notify.onError("Error: <%= error.message %>") }))
    .pipe(dest(publicPathList.js));
}

browser-syncの処理を設定します。
bsReloadは何もreturnしない(処理が終了しない)ので、コールバックにdoneを指定して終了させます。
bsFuncは、起動用です。

const bsReload = (done) => {
  $.browserSync.reload();
  done();
}
const bsFunc = () => {
  $.browserSync({
    server: {
      baseDir: publicPathList.base
    },
    reloadOnRestart: true
  });
}

watchと実行について

  • watch ブラウザで自動更新されるよう、watchを設定します。
    seriesは、引数を順番に処理します。(以下だと、コンパイル→browser-syncでリロードの流れ)
// watch list
const watchFileList = () => {
  watch(srcPathList.pug, series(pugCompile, bsReload));
  watch(srcPathList.sass, series(sassCompile, bsReload));
  watch(srcPathList.js, series(jsCompile, bsReload));
}
  • exports exports.defaultでgulpを起動するコマンドnpx gulpの処理内容を設定します。
    parallelは、引数を並行に処理します。
// exports
exports.default = series(
  parallel(pugCompile, sassCompile, jsCompile),
  parallel(watchFileList, bsFunc)
);

default以外にも、例えばビルド用にexports.buildを設定しておけばnpx gulp buildで、ビルド処理のみ行えます。
作業に合わせてexportsを設定しておけばよいでしょう。