葉っぱのメモ帳

フリーランスなフロントエンドエンジニアの備忘録

【Gulp】BrowserSyncで自動リロード

2022.08.15

前々回、前回でWindowsでgulpを導入してSassをコンパイルする環境を作ってきました。
今回はそこにBrowserSyncを使用して、ファイルの修正→保存の度にブラウザも自動リロードしてくれるようにしていきたいと思います。

前回までのおさらい

デスクトップに作成したプロジェクトフォルダにgulpやDartSassやそのほかプラグイン等をインストールしました。
今回もそのフォルダをVS Codeで開き、ターミナルを表示させておきます。

フォルダ構成は下記の様になっています(index.htmlはこれからなんですが…)

├─ gulpfile.js
│  package-lock.json
│  package.json
├─ node_modules
│  ├─ ・・・
│(略)
│
├─ dist (出力先)
│  ├─ index.html
│  │
│  └─css
│      └─ style.css
│
└─src (作業フォルダ)
    │  index.html
    │
    └─sass
        ├─ style.scss
        │
        ├─ foundation
        │   ├─ _reset.scss
        │  (略)
        │ 
        ├─ layout
        └─ object

BrowserSyncの導入

htmlやcssといったソースコードを編集して保存→ブラウザリロードってけっこう面倒なんですよね。BrowserSyncとは、それを自動でやってくれるものです。

gulpfile.jsにHTMLをdistフォルダへ出力するタスクを作っておく

ファイル構成を見ていただくと分かるのですが、srcフォルダとdistフォルダにindex.htmlがあります。
ここではsrcフォルダのindex.htmlを編集するとdistフォルダへ出力して、自動リロードする、という流れにしたいのでsrcフォルダのhtmlをdistフォルダへ出力するタスクを作っておきます。

これ…この記事ではただsrcからdistへコピーするだけなので、正直distフォルダで作業しても同じなのですが(汗)
一応、htmlの方もなんやかんやして出力、ということをやることもあることを想定してこういう形にしています。
そして今回はやらないですがjsも同じようなことをしています…。

const html = () => {
  return gulp.src('./src/**/*.html')
    .pipe(gulp.dest('./dist'))
}

BrowserSyncのインストール

プロジェクトフォルダをVS Codeで開いた状態でターミナルを表示、ターミナルに下記の様にコマンドを入れてプロジェクトフォルダにBrowserSyncをインストールします。

npm install --save-dev browser-sync

gulpfile.jsを編集する

BrowserSyncを読み込み

const browserSync = require('browser-sync');

開きたいパスを指定する

const browserSyncFunc = (done) => {
  browserSync.init({
    server: {
      baseDir: './dist'           // browser-syncが基準とするディレクトリを指定する
    },
    startPath: 'index.html',      // 開きたいパスを指定する
    notify: false,                // 右上の通知オフ
  });
}

開始したときにどのファイルを開くかの指定です。ここでは出力先であるdistフォルダのindex.htmlを開くように指定してあります。

リロードの設定

const browserSyncReload = (done) => {
  browserSync.reload();
  done();
}

gulpfile.js全体のサンプル

あとはwatchやdefaultに必要なタスクを設定します。gulpfile.js全体はこんな感じになりました。

// モード
// ----------------------------------------------------------------------
"use strict";

// モジュール読み込み
// ----------------------------------------------------------------------
/* gulp */
const gulp = require('gulp');
const { src, dest, watch, series, parallel } = require('gulp');

/* sass */
const gulpDartSass  = require('gulp-dart-sass');
const sassGlob      = require('gulp-sass-glob-use-forward');
const autoprefixer  = require('gulp-autoprefixer');
const plumber       = require('gulp-plumber');
const gcmq          = require('gulp-group-css-media-queries');
const sourcemaps    = require('gulp-sourcemaps');

/* browser-sync */
const browserSync = require('browser-sync');

// タスク定義
// ----------------------------------------------------------------------
// sass
const sass = () => {
  return gulp
    .src('src/sass/**/*.scss')
    // 強制停止を防止
    .pipe(plumber({
      errorHandler: function (err) {
        console.log(err.messageFormatted);
        this.emit('end');
      }
    }))
    // ソースマップを初期化
    .pipe(sourcemaps.init())
    // glob
    .pipe(sassGlob())
    // scssをコンパイル
    .pipe(gulpDartSass({
      includePaths: ['src/sass'],
      outputStyle:'expanded',
    }))
    // ベンダープレフィックスを付ける
    .pipe(autoprefixer({cascade: false,}))
    // メディアクエリをまとめる
    .pipe(gcmq())
    // ソースマップを出力する
    .pipe(sourcemaps.write('./'))
    // できあがったcssを書き出す
    .pipe(gulp.dest('dist/css'))
    // リロードせずにブラウザに反映
    .pipe(browserSync.stream());
}

// htmlをdistへ出力
const html = () => {
  return gulp.src('./src/**/*.html')
    .pipe(gulp.dest('./dist'))
}

// browser-sync
const browserSyncFunc = (done) => {
  browserSync.init({
    server: {
      baseDir: './dist'           // browser-syncが基準とするディレクトリを指定する
    },
    startPath: 'index.html',      // 開きたいパスを指定する
    notify: false,                // 右上の通知オフ
  });
}

// リロード
const browserSyncReload = (done) => {
  browserSync.reload();
  done();
}

//  Watch
// ----------------------------------------------------------------------
const watchFiles = () => {
  gulp.watch('./src/sass/**/*.scss', sass);
  gulp.watch('./src/*.html', gulp.series(html, browserSyncReload));
}

// タスクの実行
// ----------------------------------------------------------------------
exports.sass = sass;

// default
// ----------------------------------------------------------------------
exports.default = gulp.series(
  gulp.parallel(html, sass),
  gulp.parallel( browserSyncFunc, watchFiles)
);

npx gulpとコマンドを打つと、htmlの出力、sassのコンパイルをする、browserSuncとwatchが開始される、watchではscssファイルとhtmlファイルが更新された時の挙動を記述しています。

seriesは直列 parallelは並列

watchやdefaultのところにseriesやparallelという部分があります。
こちらはseriesが直列の処理(順番に処理)parallelが並列の処理(非同期処理・それぞれ勝手に動く)という意味です。メモ程度に。

Sassの更新時にはreloadではなくStreamを使う

さて、上記のgulpfile.jsの中でsassの変更時の動作なのですが、sassの更新時はブラウザのリロードの指定をしていません。実際の作業ではデベロッパーツールなどでcssの確認をしながらscssの編集をする際、保存するたびにリロードすると少し不便だったりします。hoverの状態を選択して確認していた場合、リロードした際はまたその要素を探してhoverを選択したり。

sassのタスク部分にbrowersyncのstreamを指定すると、ブラウザのリロードはせずにsassの編集部分だけ反映されて便利です。

const sass = () => {
  return gulp
    .src('src/sass/**/*.scss')

   (略)

    // できあがったcssを書き出す
    .pipe(gulp.dest('dist/css'))
    // リロードせずにブラウザに反映
    .pipe(browserSync.stream());
}

デベロッパーツールでボタンのhover時の確認をしていたとします。ここでborderを太くしたいな~と思ってscssを編集…すると

ブラウザのリロード無しでscssのコンパイルと変更箇所が反映される!というイメージ。
なのでsassのタスクの最後にstreamを指定し、リロードはしない設定になっています。

htmlが変更されたときはリロードします。

これで一通りの「Sassのコンパイルと出力と変更部分の反映」「htmlの出力(コピーだけだけど…)」「ブラウザの自動リロード」をwatchする環境ができました!
あとは思う存分scssをゴリゴリするだけです!DartSassのことについては探せば情報がたくさん出てくると思いますので…。

ということで…ここまでお疲れ様でした~~!

まとめ

更に画像を圧縮したりとかできることはあるのですが、ここまでできれば基本的な流れみたいなものはだいたい把握できるかと思います。あとは必要な機能を足していったりする感じになっていきますね。
読んでくださってありがとうございました!

参考にさせていただきました

サポートよろしくお願いします

この記事を気に入って下さった方、応援してもいいという方、サポートしていただけると嬉しいです。

Amazonほしいものリスト Amazonギフト券をメールで送る

※受取人のEメールアドレスに とご入力ください。
※上記のアドレスはギフト受け取り専用です。

書いた人

トップへ