今更ながら、タスクランナーの「Gulp(ガルプ)」を導入してみました。
インストール方法や、Sassのコンパイル・画像圧縮などのタスク処理の書き方などの参考記事は多々あるものの、記事によってそれぞれの書き方が異なり、実際にやってみるとつまずく部分が多くかなり手こずりました。
それぞれのモジュール(プラグイン)のバージョンなどによる仕様の違いなど、当時は何が違うのかなどがサッパリわからず心折れかけたので、Gulp導入にあたってつまずいた点をまとめておきます。
インストールコマンドの違い
モジュールをGulpで使えるようにインストールする際のコマンドnpm install
。
大元のgulpモジュールを例とすると、こんな書き方の違いがありました。
## その1
npm install -D gulp
## その2
npm install gulp --save-dev
-Dと—save-dev。
結論としては、-D は –save-dev のショートカットということで、この2つの意味は同じでした。
npm install
の違いまとめ
コマンド例 | 保存される場所(package.json) | 主な用途 |
---|---|---|
npm install モジュール名 | dependencies | アプリが本番環境でも使うモジュール(例: React, axios など) |
npm install モジュール名 --save | dependencies | 同上(※今はオプションなしと同じ扱い) |
npm install モジュール名 --save-dev | devDependencies | 開発時だけ使うモジュール(例: gulp, Sass, ESLint, BrowserSyncなど) |
-D(—save-dev)の位置は、モジュール名の先でも後でも問題はなく、基本的にgulp関連で使う場合は、-Dの使用でOK。
task()と関数の違い
実際に実行するタスク処理の書き方。
Sassのコンパイルを例とすると、よく目にした書き方が、これ。
//gulpfile.js
//モジュールの読み込みは割愛
gulp.task('default', function () {
return gulp
.src('css/style.css')
.pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError))
.pipe(gulp.dest("css"))
});
ところが、このtask()の書き方はGulp v4から非推奨となっているようです。
代わりにタスクごとに名前付き関数で定義して、それを呼び出してね、ということ。
2025年現在のGulpの最新バージョンは5。
今後はtask()ではなく関数を使った書き方となっていくので、参考記事を探す時はその観点で探してみてください。
//gulpfile.js
//モジュールの読み込みは割愛
const sassCompile = (done) => {
gulp
.src('css/style.css')
.pipe(
sass({outputStyle: 'expanded'})
.on("error", sass.logError)
)
.pipe(gulp.dest('css'))
done();
};
//関数化
exports.sassCompile = sassCompile;
// タスク実行
exports.default = gulp.series(sassCompile);
この辺りの、task()を関数化する書き方は、以下の記事が参考になりました。

モジュールの読み込み方の違い
インストールしたモジュールを、gulpfile.jsで使用するために読み込む書き方。
//gulpfile.js
// その1
const gulp = require('gulp');
// その2
import gulp from 'gulp';
その後の諸々にもかなり影響していたのですが、モジュールシステムである「CommonJS」と「ESModules(ECMA Script Modulesの略。以下:ESM)」の違い。
仕様が異なるので、書き方が違うということ。
CommonJSとは、サーバーサイドなどのウェブブラウザ環境外におけるJavaScriptの各種仕様を定めることを目標としたプロジェクトである。
Wikipedia
ECMAScript(エクマスクリプト)は、Ecmaインターナショナルにおいて標準化されたJavaScriptの国際規格である。
Wikipedia
つまり、先ほどの書き方の違いはこういうこと。
//gulpfile.js
// その1(CommonJS)
const gulp = require('gulp');
// その2(ESModules)
import gulp from 'gulp';
ESMはCommonJSの上位互換であり、Gulpのモジュールもバージョンの新しいものはESM仕様になっていることもあるので、今後はESMでの書き方をした方が良さそう。
特に、画像圧縮の「gulp-imagemin」モジュールのバージョン8以降はESM専用となっているので、「gulp-imagemin」を使用する場合は、ESM一択ですね。

ESMで記述する場合は、gulpfile.jsの拡張子を.mjsへ変更することもお忘れなく。
前述のtask()→関数化も含めて、ESM記述への書き換えは以下の記事が参考になりました。


ERR_REQUIRE_ASYNC_MODULEエラー
ESM記述への以降の際によく出てきたエラー。
Error [ERR_REQUIRE_ASYNC_MODULE]: require() cannot be used on an ESM graph with top-level await. Use import() instead. To see where the top-level await comes from, use --experimental-print-required-tla.
エラーの通り、require()ではなくimportを使ってね、とのこと。
また、翻訳すると「トップレベルawaitやrequireが問題」と言っているので、以下のコマンドでエラーの出どころ(どのファイルが原因か)を教えてくれます。
node --experimental-print-required-tla gulpfile.mjs(調べたいファイル名)
top-level awaitまわりは、正直今も理解しきれてないです。
が、「importを使え」とのことなので、前述のようにこのエラーが出たらESMで書け、ということですね。
このエラーの解説は、以下の記事が詳しかったです。



なお、gulp-imageminモジュール内のgifsicleは、ESM + Top-level await を使ってるので今のところ使うのは難しいようです。
もしgifsicleを使用したい場合は、「imagemin-gifsicle 」モジュールを別で読み込んで処理をすること。
パスの指定の仕方
Sassコンパイルや画像圧縮の元ファイルや生成先の指定など、gulpfie.js(.mjs)の中で幾度となくファイルのパスの指定があります。
パスの指定は、Gulpfileの位置(プロジェクトルート)を起点に書きましょう。
フロントエンドをやってる人なら、ついつい../sass/
のように相対パスで書きたくなりますが、この書き方だと動かないことがあるので注意。
まとめ
タスクランナー「Gulp」導入にあたって、つまずいた・よくわからなかった点をまとめました。
今だからこそ理解できていることもあり、今でもよくわかっていないことも多々あります。
参考記事を探す中で、ひとまず今言えることは、コレ。
- モジュールの読み込みは、require()ではなくimport
- タスク処理の設定は、task()ではなく関数
- 記述時方式は、CommonJSではなくESM(.mjs)
Node.js、Gulp、各モジュールのバージョンの組み合わせによって記述の仕方が異なり、自分の状況とぴったり当てはまるサンプルがないのが手こずった理由ですかね。
自分用にカスタマイズするには、まだまだ細かな設定が必要ですが、大前提となる部分の意味がわかるだけでも違うかなと思って残しておきます。