読者です 読者をやめる 読者になる 読者になる

Corredor

ウェブ、プログラミングの勉強メモ。

Gulp で Browser-Sync を動かしてブラウザにリアルタイムに変更を反映させる

前回の記事はコレ。

neos21.hatenablog.com

前回の記事で、Browserify を使って JavaScript ファイルをガッチャンコする Gulp タスクを作った。動作確認には Http-Server というパッケージを使っていたが、JavaScript のビルドは毎度 gulp build-js (自作タスク名) というコマンドを叩かなくてはならず、HTML ファイルを修正した時もブラウザを F5 しなおさなくてはならなかった。

今回はこれらの細々した動作を完全に自動化させ、ファイルを保存すると自動的にビルドし、ブラウザを自動で更新して変更内容を反映するための環境を作る。

Browser-Sync をインストールする

ブラウザへの反映を自動化するために、Browser-Sync というパッケージを導入する。

# グローバルインストール
$ npm install --global browser-sync

# package.json に書き込みつつローカルインストール
$ npm install -D browser-sync

Browser-Sync を単体で使うこともできるようなのだが、今回は Gulp タスクに組み込んでしまおうと思う。

Gulp タスクの書き換え

これまでは、Browserify を実行する build-js というタスクしか作っていなかった gulpfile.js だが、ココにファイルの変更を監視するタスクと、ブラウザを更新するタスクを追加する。

/** gulpfile.js */
var gulp = require("gulp");
var browserify = require("browserify");
var source = require("vinyl-source-stream");
var browserSync = require("browser-sync");    // 今回追加したモジュール。変数名にはハイフンが使えないっぽい (後述)

/** 「gulp」コマンドを打たれた時に実行するコマンドたちを定義 */
gulp.task("default", ["watch", "build-js", "browserSync", "reload"]);

/** ファイルの更新をチェックして JS のビルド処理を呼び出す */
gulp.task("watch", () => {
  // () => は function() {} のショートハンド
  gulp.watch(["./src.js"], () => {
    gulp.start(["build-js"]);
  });
});

/** JS のビルド : src.js を main.js にビルドする */
gulp.task("build-js", () => {
  browserify({
    // ビルド対象ファイル
    entries: ["./src.js"]
  })
  .bundle()                   // Browserify の実行
  .pipe(source("main.js"))    // Vinyl に変換
  .pipe(gulp.dest("./"));     // 出力
});

/** ブラウザ表示 */
gulp.task("browserSync", () => {
  browserSync({
    server: {
      baseDir: "./"    // サーバとなる Root ディレクトリ
    }
  });
  // ファイルの監視 : 以下のファイルが変わったらリロード処理を呼び出す
  gulp.watch("./main.js", ["reload"]); // ビルドされた JS ファイル
  gulp.watch("./*.html",  ["reload"]); // HTML ファイル
});

/** リロード */
gulp.task("reload", () => {
  browserSync.reload();
});

少々長くなったが、これが gulpfile.js の全量だ。

build-js タスクの他に、default の定義と、watchbrowserSyncreload を追加した。

gulp.watch() というメソッドで、ファイルの更新を監視することができる。監視対象のファイルは * アスタリスクでの指定も可能。

browserSync というタスクで、Browser-Sync を使って簡易サーバを立ち上げる。そしてこのタスクからは、ブラウザをリロードするトリガーとなるファイルの変更を監視する。

というわけで、src.js を変更した時の一連の動作の順番をまとめるとこうなる。

  1. src.js を書き換えて保存する
  2. watch タスクがファイルの変更を検知し、build-js タスクを呼ぶ
  3. build-js タスクで main.js をビルドする
  4. main.js に変更が入ったことになるので、browserSync タスクでの監視がこれを検知し、reload タスクを呼ぶ
  5. reload タスクがブラウザをリロードする

一方、HTML ファイルを書き換えた場合は、ビルド処理がないので、直接 browserSync タスクが変更を検知して reload タスクを呼ぶ。

一つ注意点としては、gulpfile.js では変数名にハイフンが使えないらしい。var browserSyncvar browser-sync と書いていたら、以下のようなエラーが出てしまった。

/NodeJsTest/gulpfile.js:4
var browser-sync = require("browser-sync");
           ^
SyntaxError: Unexpected token -

Gulp タスクを動かす

gulpfile.js ができたら、ターミナル (Windows ならコマンドプロンプトか GitBash) を開き、上記の gulpfile.js があるフォルダで gulp コマンドを打つ。

$ gulp

すると、default タスクに記載のタスクが実行され、Browser-Sync によってブラウザが開く。

$ gulp
[01:52:48] Using gulpfile /NodeJsTest/gulpfile.js
[01:52:48] Starting 'watch'...
[01:52:48] Finished 'watch' after 25 ms
[01:52:48] Starting 'build-js'...
[01:52:48] Finished 'build-js' after 34 ms
[01:52:48] Starting 'browserSync'...
[01:52:48] Finished 'browserSync' after 296 ms
[01:52:48] Starting 'reload'...
[BS] Reloading Browsers...
[01:52:48] Finished 'reload' after 847 μs
[01:52:48] Starting 'default'...
[01:52:48] Finished 'default' after 3.85 μs
[01:52:49] Starting 'reload'...
[BS] Reloading Browsers...
[01:52:49] Finished 'reload' after 670 μs
[BS] Access URLs:
 ------------------------------------
       Local: http://localhost:3000
    External: http://192.168.1.2:3000
 ------------------------------------
          UI: http://localhost:3001
 UI External: http://192.168.1.2:3001
 ------------------------------------
[BS] Serving files from: ./

ブラウザが開くと http://localhost:3000 にアクセスした状態になる。

ターミナルはそのまま置いておき、src.js なり index.html なりを編集すると、以下のようにタスクが自動的に実行され、ブラウザがリロードされて変更内容が自動的に反映される。

# src.js を変更して保存した直後のターミナル表示

[01:54:50] Starting 'build-js'...
[01:54:50] Finished 'build-js' after 2.89 ms
[01:54:50] Starting 'reload'...
[BS] Reloading Browsers...
[01:54:50] Finished 'reload' after 1.79 ms

gulp.watch() を書いているタスクは表示されないが、そこが監視していて呼び出したタスクについてはターミナルに表示される。

開発を中断する時は、Ctrl + C で gulp コマンドの動作を止めるなり、ターミナルを閉じるなりしてしまえば良い。


自身の開発環境に合わせて gulpfile.js のタスクを修正する必要はあるものの、一度作ってしまえばある程度使い回しが利くシロモノだ。いちいちビルドタスクを動かして、ブラウザを F5 して…としなくても、完全自動で反映されるのは想像しているよりも快適だ。

今回のソースは以下にコミットしてあるので、よかったらこちらもご覧いただきたい。

参考

ブレイクスルーJavaScript フロントエンドエンジニアとして越えるべき5つの壁―オブジェクト指向からシングルページアプリケーションまで (WEB Engineer’s Books)

ブレイクスルーJavaScript フロントエンドエンジニアとして越えるべき5つの壁―オブジェクト指向からシングルページアプリケーションまで (WEB Engineer’s Books)