2021-04-24 投稿

Gulpでフロントエンド開発を自動化してラクをする

効率的にコーディングをするためのnpmパッケージはたくさんありますが、 何かを変更するたびに毎回コマンドを実行しないといけないのは面倒です。 ここでは、変更を検知してコマンドを自動的に実行できるGulpと、実行するタスク(gulp-sass, gulp-pug, gulp-babel)を作っていきます。

Gulpによる自動化

タスクランナーとは

フロントエンド開発において、SassからCSSへの変換、テンプレートからHTMLへの変換、画像の圧縮など様々なタスクがあります。 これらを、自動的に実行してくれるのがタスクランナーです。 タスクランナーにはGrunt, Gulpなどがありますが、ここではGulpを導入します。

Gulpの導入

Gulpはnpmパッケージなので、npm コマンドでインストールします。プロジェクトのルートディレクトリで以下を実行します。

1npm install gulp gulp-cli --save-dev

まずは、SassをCSSに変換するタスクを定義するために、以下のパッケージをインストールします。

1npm install sass gulp-sass --save-dev

gulpfile.jsの作成

Gulpで実行したいタスクは、gulpfile.jsというファイルに記述していきます。 プロジェクトのルートディレクトリに、gulpfile.jsを用意します。

1const { src, dest } = require('gulp');
2const gulpSass = require('gulp-sass');
3
4function taskSass() {
5  return src('sass/**/*.scss')
6    .pipe(gulpSass())
7    .pipe(dest('css/'))
8}
9
10exports.sass = taskSass

gulpfile.jsはNode.jsで記述します。
1行目は、gulpパッケージからメソッド(ここではsrcとdest)を呼び出しています。 srcメソッドは、プロジェクトから指定したパスにマッチするファイルを読み込みます。destメソッドは、指定したディレクトリに処理したものを出力します。

4〜8行目は、Sassを変換するタスク(taskSass)です。戻り値にgulpのメソッドストリームを指定します。
sassディレクトリ配下にあるすべてのscss拡張子ファイルを、sassコマンドを通してcssディレクトリに出力するというタスクです。

10行目で、呼びされる際のデフォルトのメソッド(ここではtaskSass)を指定しています。

exports.sassに指定したメソッドは、以下のコマンドで実行できます。 正常に実行されると、以下のようなメッセージが出力されます。

1gulp sass
2// 以下のような内容が出力される
3[08:34:56] Using gulpfile ~/Projects/someProject/gulpfile.js
4[08:34:56] Starting 'sass'...
5[08:34:56] Finished 'sass' after 1.6 ms

複数タスクを同時に実行させる

別のタスクを用意して、複数のタスクを実行させましょう。 テンプレートエンジンであるPugをHTMLに変換し、さらにインデントをきれいにするタスクを登録します。

1const { src, dest, series, parallel } = require('gulp');
2const gulpSass = require('gulp-sass');
3const gulpPug = require('gulp-pug-3');
4const gulpBeautify = require('gulp-beautify');
5
6function taskSass() {
7  return src('sass/**/*.scss')
8    .pipe(gulpSass())
9    .pipe(dest('css/'))
10}
11
12function taskPug() {
13  return src('resource/pug/**/*.pug')
14    .pipe(gulpPug())
15    .pipe(gulpBeautify.html({ indent_size: 2 }))
16    .pipe(dest('public/'))
17}
18
19exports.default = parallel(taskSass, taskPug)

exports.defaultに指定しているのは、taskSassとtaskPugを並列(pararell)に実行するというものです。 1行目、gulpからseriesメソッドとparallelメソッドを呼び出していることに注意してください。 タスクを直列(series)、または並列(parallel)に実行することができます。series,parallelは更に入れ子にすることもできます。

gulpタスクを実行します。

1gulp default
2//または以下(defaultは省略できる)
3gulp
4
5// 以下のような内容が出力される
6[08:58:59] Using gulpfile ~/Projects/someProject/gulpfile.js
7[08:58:59] Starting 'default'...
8[08:58:59] Starting 'taskPug'...
9[08:58:59] Starting 'taskSass'...
10[08:58:59] Finished 'taskSass' after 72 ms
11[08:58:59] Finished 'taskPug' after 79 ms
12[08:58:59] Finished 'default' after 81 ms

ファイルの変更を監視して自動実行(watch)

タスクを実行してファイルを変換することはできました。ですが、それでも毎回gulpコマンドを叩かなければなりません。 そこで、ユーザの変更を監視して自動的にタスクを実行できる機能を利用します。

1const { src, dest, series, parallel, watch } = require('gulp');
2
3// ...(省略)
4
5exports.watch = function() {
6    watch('sass/**/*.scss', taskSass);
7    watch('pug/**/*.pug', taskPug);
8}

gulp watchコマンドを実行すると、監視している状態になります。

1gulp watch
2
3// 以下のような内容が出力される
4[09:03:04] Using gulpfile ~/Projects/someProject/gulpfile.js
5[09:03:04] Starting 'watch'...

ためしにsassファイルを編集してみます。すると自動的にtaskSassタスクが実行されることがわかります。

1[09:03:04] Using gulpfile ~/Projects/someProject/gulpfile.js
2[09:03:04] Starting 'watch'...
3[09:03:19] Starting 'taskSass'...
4[09:03:19] Finished 'taskSass' after 373 ms

プロジェクトの起動時に一度gulp watch コマンドを実行しておけば、あとはwatchメソッドで監視対象にしておいたファイルを編集するたびに 自動的にGulpのタスクが実行されます。SassをいちいちCSSに変換する手間から開放されます。

その他タスク

Webpack

Webpackはモジュールバンドラーというもので、アプリケーションで読み込むJavaScriptなどのファイル群をまとめて出力してくれるものです。 Javascriptのモジュールは互いに依存しあっていることが多いため、その関係を考慮しながら順番に読み込むのは大変です。 Webpackはその依存関係も含めて一つのファイルにまとめる(バンドル)することができます。 任意の形式のファイルに対して特定のタスクを実行して出力する事ができるので、タスクランナーのような使い方もできます。

Browserify

npmパッケージ化されているライブラリを、requireメソッドを呼ぶことによりブラウザ向けJavaScript内で利用できます。 node_modulesディレクトリの中からわざわざライブラリを探してパスを指定しなくて済みます。

npm install browserify --save-dev

Babel

JavaScriptでは、ES2015から新しい書き方も導入されました。しかし、IEなどのブラウザではES2015に対応していません。
またJavaScriptには、TypeScriptやDart、CoffeeScriptなど様々な拡張言語(AltJS)があります。
これらはブラウザで処理できないので、処理できるようなJavaScriptに変換してあげる必要があります。

以下はES2015以降の記法をブラウザ向けに変換させる場合です。 preset-envというプリセットを適用しています TypeScript変換用のpreset-typescript、React変換用のpreset-reactなども存在します。

1const taskBabel = () => {
2  return src("resource/es2015/**/*.js")
3    .pipe(babel({
4      presets: ["@babel/preset-env"]
5    }))
6    .pipe(dest("public/js/"))
7  }
8}

また、Babelの設定を.babelrcというファイルに書くこともできます。 Babelの実行時に、存在する.babelrcを自動的に読み込んでくれるようになります。

1{
2  "presets": ["@babel/preset-env"]
3}

BrowserSync

gulp watchで自動的に変更しても、反映を確認するためにはブラウザをリロードする必要があります。 このリロードを自動的に行なってくれるBrowserSyncというものがあります。

1const sync = require('browser-sync').create();
2
3.. (省略)
4
5function taskBrowserSync(cb) {
6  sync.reload();
7  cb();
8}
9exports.watch = function () {
10  sync.init({
11    server: 'public/'
12  });
13  watch('resource/sass/**/*.scss', series(taskSass, taskBrowserSync));
14  watch('resource/pug/**/*.pug', series(taskPug, taskBrowserSync));
15}