Help us understand the problem. What is going on with this article?

Gulp4設定まとめ(Pug/Sass)

1. はじめに

Gulp+Pug+SassでWebサイトの開発環境を作りました。
何度か作っているのですが、毎回忘れてしまうのでまとめです。

※ gulp自体のインストール(グローバルインストールとローカルインストール)はされている前提です。
※ npmを使っています。

2. ディレクトリ構造

dest/
  ├css/
  ├images/
  └javascripts/
  index.html
src/
  ├images/
  ├javascripts/
  ├pages/
  ├pug/
  └sass/
gulpfile.js
package.json

3. 環境

Gulp 4.0.2

4. インストールしたパッケージ

パッケージ 概要
gulp-pug Pugをコンパイル
gulp-sass Sassをコンパイル
gulp-autoprefixer CSSプロパティにベンダープレフィックスを付与
gulp-cssmin CSSを圧縮
gulp-uglify JSを圧縮
browser-sync ブラウザのリロード, ローカルサーバーの立ち上げ
gulp-plumber エラーを検出
gulp-notify デスクトップに通知
del フォルダやファイルを削除

インストールコマンドの一覧です。

$ npm i -D gulp-pug
$ npm i -D gulp-sass
$ npm i -D gulp-autoprefixer
$ npm i -D gulp-cssmin
$ npm i -D gulp-uglify
$ npm i -D browser-sync
$ npm i -D gulp-plumber
$ npm i -D gulp-notify
$ npm i -D del

5. gulpfile.js

gulpを実行したら以下のような処理になるようにしました。

1. destディレクトリ配下のコンテンツを丸ごと削除
srcディレクトリとdestディレクトリにあるコンテンツに差分がない状態を保ちたいので、gulpを実行したらdestディレクトリ配下のコンテンツを丸ごと削除します。

2. 他タスクを並列で実行
1の処理が終わったら、コンパイル、ローカルサーバー起動、ファイル監視を並列で実行します。

各処理のポイント

destディレクトリ配下のコンテンツ削除

コンテンツを削除するために使用しているdelパッケージですが、paths.dest + '/**'としか書いていない場合、タスクの実行が成功してもコンテンツが削除されないので気をつけましょう。

公式ドキュメントを読むと、paths.dest + '/**', '!' + paths.dest のように明示的に「親ディレクトリを削除しない」と書かないと親ディレクトリも削除対象になるということが書かれているのですが、私の環境では削除自体が実行されませんでした。

gulpfile.js
//Clean
gulp.task('clean', function(done) {
  del.sync(paths.dest + '/**', '' + paths.dest);
  done();
});

Sass -> CSS

SassからCSSにコンパイルする処理では、コンパイルエラーの検知・通知、ベンダープレフィックスの自動付与、CSS圧縮が行われます。

gulpfile.js
//Sass
gulp.task('css', function() {
  return gulp.src([
    paths.src + '/sass/**/*.scss',
    '!' + paths.src + '/sass/**/_*.scss'
  ])
  .pipe(plumber({ //エラーを検知しデスクトップ通知
    errorHandler: notify.onError("Error: <%= error.message %>")
  }))
  .pipe(sass()) //Sass -> CSS
  .pipe(autoprefixer({ //ベンダープレフィックスを付与
      overrideBrowserslist: 'last 2 versions'
  }))
  .pipe(cssmin()) //圧縮
  .pipe(gulp.dest(paths.dest + '/css'))
});

Pug -> HTML

PugからHTMLにコンパイルする処理では、コンパイルエラーの検知・通知、読みやすいコードへの整形が行われます。

gulpfile.js
//Pug
gulp.task('html', function() {
  return gulp.src([
    paths.src + '/pages/**/*.pug',
    '!' + paths.src + '/pages/**/_*.pug'
  ])
  .pipe(plumber({ //エラーを検知しデスクトップ通知
    errorHandler: notify.onError("Error: <%= error.message %>")
  }))
  .pipe(pug({pretty: true})) // 読みやすいコードに整形
  .pipe(gulp.dest(paths.dest))
});

JavaScript

JavaScriptは圧縮します。

gulpfile.js
//JavaScript
gulp.task('js', function() {
  return gulp.src(
    paths.src + '/javascripts/**/*'
  )
  .pipe(uglify())//圧縮
  .pipe(gulp.dest(paths.dest + '/javascripts'))
});

監視

srcディレクトリ配下の各種ファイルを監視し、変更を検知したら各種ファイル形式にあわせたコンパイルタスクを実行しリロードします。

gulpfile.js
//Watch
gulp.task('watch', function () {
  const reload = () => {
    browserSync.reload(); //リロード
  };
  gulp.watch(paths.src + '/sass/**/*.scss').on('change', gulp.series('css', reload));
  gulp.watch(paths.src + '/pages/**/*.pug').on('change', gulp.series('html', reload));
  gulp.watch(paths.src + '/javascripts/**/*').on('change', gulp.series('js', reload));
  gulp.watch(paths.src + '/images/**/*').on('change', gulp.series('image', reload));
});

サンプルコード

gulpfile.jsの全文です。

gulpfile.js
const gulp = require('gulp');
const pug = require('gulp-pug');
const sass = require('gulp-sass');
const autoprefixer =require('gulp-autoprefixer'); 
const cssmin = require('gulp-cssmin');
const uglify = require('gulp-uglify');
const browsersync = require('browser-sync');
const notify = require('gulp-notify');
const plumber = require('gulp-plumber');
const del = require('del');

const paths = {
  src: 'src',
  dest: 'dest'
};

//Pug
gulp.task('html', function() {
  return gulp.src([
    paths.src + '/pages/**/*.pug',
    '!' + paths.src + '/pages/**/_*.pug'
  ])
  .pipe(plumber({
    errorHandler: notify.onError("Error: <%= error.message %>")
  }))
  .pipe(pug({pretty: true}))
  .pipe(gulp.dest(paths.dest))
});

//Sass
gulp.task('css', function() {
  return gulp.src([
    paths.src + '/sass/**/*.scss',
    '!' + paths.src + '/sass/**/_*.scss'
  ])
  .pipe(plumber({
    errorHandler: notify.onError("Error: <%= error.message %>")
  }))
  .pipe(sass({
    outputStyle: 'expanded'
  }))
  .pipe(autoprefixer({
      overrideBrowserslist: 'last 2 versions'
  }))
  .pipe(cssmin())
  .pipe(gulp.dest(paths.dest + '/css'))
});

//JavaScript
gulp.task('js', function() {
  return gulp.src(
    paths.src + '/javascripts/**/*'
  )
  .pipe(uglify())
  .pipe(gulp.dest(paths.dest + '/javascripts'))
});

//Image File
gulp.task('image', function() {
  return gulp.src(
    paths.src + '/images/**/*'
  )
  .pipe(gulp.dest(paths.dest + '/images'))
});

//Browser Sync
gulp.task('browser-sync', function (done) {
  browsersync({
    server: { //ローカルサーバー起動
        baseDir: paths.dest
  }});
  done();
});

//Watch
gulp.task('watch', function () {
  const reload = () => {
    browsersync.reload(); //リロード
  };
  gulp.watch(paths.src + '/sass/**/*').on('change', gulp.series('css', reload));
  gulp.watch(paths.src + '/pages/**/*').on('change', gulp.series('html', reload));
  gulp.watch(paths.src + '/javascripts/**/*').on('change', gulp.series('js', reload));
  gulp.watch(paths.src + '/images/**/*').on('change', gulp.series('image', reload));
});

//Clean
gulp.task('clean', function(done) {
  del.sync(paths.dest + '/**', '' + paths.dest);
  done();
});

//Default
gulp.task('default',
  gulp.series(
  'clean',
    gulp.parallel(
      'html',
      'css',
      'js',
      'image',
      'watch',
      'browser-sync'
)));

6. さいごに

毎回Gulpの設定を忘れてしまうので、今後はこの記事を更新するようにしたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした