プログラミング
 Computer >> コンピューター >  >> プログラミング >> プログラミング

【初心者向け】Gulp超入門チュートリアル|npmの基礎からタスク自動化まで丁寧に解説

現代のWeb開発において、ビルドツールの活用はもはや欠かせないものとなっています。

Gulpは、Webpackと並んで現在もっとも人気のあるビルドツールのひとつです。

しかし、Gulpを習得するには一定の学習コストがかかります。最大のハードルは、一見すると何百個もあるように感じられる構成要素を理解することでしょう。

さらに、すべての操作をコマンドラインで行う必要があるため、コマンドラインに慣れていない人にとっては非常に敷居が高く感じられるはずです。

このチュートリアルでは、npm(Node Package Manager)の基本と、フロントエンドプロジェクトへのGulpの導入方法を順を追って解説します。

読み終える頃には、開発ワークフローの構築にもコマンドライン操作にも、きっと自信が持てるようになっているでしょう。

Gulpの何がすごいのか?

Gulpは時間を大幅に節約できるツールです。Gulpを使えば、次のような面倒な作業をコンピューターに任せられます。

  • SassファイルをCSSへコンパイル
  • 複数のJavaScriptファイルの連結(結合)
  • CSS・JSファイルの最小化(圧縮)
  • ファイル変更の検知と上記タスクの自動実行

もちろん、Gulpにはここで挙げた以上に複雑な処理も可能ですが、このチュートリアルではGulpの基本と仕組みに絞って説明していきます。

このチュートリアルで行うこと

全体の流れは以下の通りです。

  1. パソコンにNode.jsとnpmをインストールする
  2. Gulpとプロジェクトに必要なパッケージをインストールする
  3. gulpfile.jsを設定して、目的のタスクを実行できるようにする
  4. あとはコンピューターが仕事をしてくれる!🙂

今の時点で用語がよくわからなくても大丈夫です。ひとつずつ順番に説明していきます。それでは始めましょう!

環境をセットアップする

Node.jsとは

Gulpを動かすには、まずローカル環境にNode.jsをインストールする必要があります。

Node.jsは公式に「JavaScriptランタイム」と称されており、いわゆるサーバーサイド(バックエンド)JavaScriptの実行環境です。GulpはNode上で動作するため、事前にNodeのインストールが必須となります。

Node.jsの公式サイトからダウンロードできます。Nodeをインストールすると、npmも同時にインストールされます。

npm(Node Package Manager)とは

npmは、世界中の開発者が書いたJavaScriptプラグイン(「パッケージ」と呼ばれます)のコレクションで、常に更新され続けています。Gulpもそのプラグインのひとつです(後ほど、他にもいくつか必要なパッケージが出てきます)。

npmの優れた点は、コマンドラインから直接パッケージをインストールできることです。わざわざWebサイトに行ってファイルをダウンロードし、手動で実行する必要がありません。

パッケージをインストールする基本の構文はこちらです。

npm install [パッケージ名]

とてもシンプルですね。

node_modulesフォルダについて

ひとつ知っておいてほしいのは、npmパッケージをインストールすると、npmがnode_modulesというフォルダを作成し、そこにすべてのパッケージファイルを格納するという点です。

node_modulesフォルダの中身を見たことがある人なら、大量の(本当に大量の!)ネストされたフォルダやファイルを目にしたことがあるかもしれません。

なぜこんなことになるのでしょうか?

これは、npmパッケージがそれぞれの機能を実現するために、別のnpmパッケージに依存していることが多いからです。これらの依存先のパッケージは「依存関係(dependencies)」と呼ばれます。

プラグインを開発するなら、既存パッケージの機能を活用するのが合理的です。誰も毎回車輪の再発明をしたいわけではありませんよね。

そのため、node_modulesフォルダにプラグインをインストールすると、そのプラグイン自身が必要とする追加パッケージが、さらにその中のnode_modulesフォルダにインストールされます。

これが繰り返され、結果として深くネストしたフォルダ構造になるというわけです。

現時点でnode_modulesの中身を気にしすぎる必要はありません。あのカオスなフォルダで何が起きているのか、軽く理解してもらえれば十分です 🙂

package.jsonでパッケージを管理する

npmのもうひとつの便利な機能として、プロジェクトにインストール済みのパッケージを記録しておける点があります。

何らかの理由ですべてを再インストールしなければならない場合に重要になりますし、他の開発者があなたのプロジェクトのパッケージを素早く簡単に自分の環境へ導入できるため、共同作業もしやすくなります。

npmはpackage.jsonというファイルを使って、インストール済みのパッケージとそのバージョンを管理します。プロジェクト名、作者、Gitリポジトリなどの情報もここに保存されます。

package.jsonを作成する

このファイルの初期化も、コマンドラインから行えます。

まず、プロジェクトフォルダがある場所へ移動します。そして次のコマンドを入力してください。npm init

するとnpmがプロジェクト情報の入力を促してきます。ほとんどの項目はEnterキーを押せば、括弧内のデフォルト値が採用されます。

完了すると、プロジェクトフォルダ内にpackage.jsonファイルが生成されます!エディタで開くと、次のような内容になっているはずです。

{
  "name": "super-simple-gulp-file",
  "version": "1.0.0",
  "description": "Super simple Gulp file",
  "main": "gulpfile.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/thecodercoder/Super-Simple-Gulp-File.git"
  },
  "keywords": [
    "gulp"
  ],
  "author": "Jessica @thecodercoder",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/thecodercoder/Super-Simple-Gulp-File/issues"
  },
  "homepage": "https://github.com/thecodercoder/Super-Simple-Gulp-File#readme"
}

もちろん、実際のプロジェクトではあなた自身の名前や情報が入ります。

この段階で全フィールドを完璧に埋める必要はありません。これらの情報は主に、npmに公開パッケージとして登録する際に使われるものだからです。

さて、あなたがpackage.jsonに記録していくのは、Gulpの実行に必要なパッケージの一覧です。具体的な追加方法を見ていきましょう。

パッケージをインストールする

前のセクションで紹介した npm install [パッケージ名] をコマンドラインに入力すると、パッケージがダウンロードされ、node_modulesフォルダにインストールされます。

同時に、そのパッケージは依存関係としてpackage.jsonファイルへ自動的に保存されます。

Gulpをインストールするには、次のように入力します。npm install gulp

Gulp関連のインストールには1〜2分かかることがあります。警告メッセージが表示されることもありますが、インストール自体が失敗しない限り気にしなくて大丈夫です。

インストール後、package.jsonを開くと、末尾にGulpが依存関係として追加されているのが確認できます。

"dependencies": {
  "gulp": "^3.9.1"
}

この依存関係リストは、パッケージを追加するたびに増えていきます。

Gulpに必要なその他のパッケージ

冒頭で述べたSCSS/CSSやJSファイルのコンパイルなどのタスクを実現するために、今回は次のパッケージを使用します。

  • gulp-sass — SassファイルをCSSへコンパイル
  • gulp-cssnano — CSSファイルを最小化
  • gulp-concat — 複数のJSファイルを1つに連結
  • gulp-uglify — JSファイルを最小化

先ほどと同じ要領で、以下のコマンドを1行ずつ実行して各パッケージをインストールしてください。1つのインストールが終わるのを待ってから、次の行に進みます。

npm install gulp-sass
npm install gulp-cssnano
npm install gulp-concat
npm install gulp-uglify

gulp-cliとグローバルGulpの違い

以前は、コマンドラインで「gulp」コマンドを使えるようにするには、「npm install --global gulp」でGulp本体をグローバルインストールする必要がありました。

しかし、グローバル版が1つだけだと、異なるバージョンのGulpを必要とする複数のプロジェクトを扱う際に問題が発生しかねませんでした。

現在の推奨做法は、Gulp本体ではなくgulp-cliという別パッケージをグローバルにインストールすることです。

こうすれば「gulp」コマンドはそのまま使えつつ、プロジェクトごとに異なるバージョンのGulpを利用できます。

コマンドはこちらです。

npm install --global gulp-cli

さて、必要なパッケージがすべて揃いました。次はプロジェクトファイルのセットアップに進みましょう!

ファイル構成を整える

ファイルやフォルダを作り始める前に、ファイル構成にはさまざまな流派があることを頭に入れておいてください。ここで紹介する方法は基本的なプロジェクトに適していますが、「正しい」構成はプロジェクトのニーズによって大きく変わります。

まずはこの基本形で各要素の役割をつかみ、あとは自分好みにアレンジしていけばOKです。

プロジェクトツリーは次のようになります。

  • プロジェクトのルートフォルダ
    • index.html
    • gulpfile.js
    • package.json
    • node_modules(フォルダ)
    • app(フォルダ)
      • script.js
      • style.scss
    • dist(フォルダ)

package.jsonとnode_modulesについてはすでに説明しましたね。index.htmlは言うまでもなく、サイトのメインファイルです。

gulpfile.jsは、冒頭で話した各種タスクをGulpに実行させるための設定を書くファイルです。詳細は後ほど扱います。

appフォルダとdistフォルダ

ここで触れておきたいのが、Gulpワークフローにおいて重要な2つのフォルダ、appdistです。

appフォルダには、JavaScriptファイル(script.js)とSCSSファイル(style.scss)を置きます。あなたが書くJSとCSSのコードは、すべてこのフォルダ内のファイルに記述します。

一方、distフォルダは、Gulpが処理した後の最終的なコンパイル済みJS・CSSファイルを格納するためだけの場所です。dist内のファイルは直接編集せず、編集は必ずapp側のファイルに対して行います。ただし、index.htmlで読み込むのはdist内のコンパイル済みファイルです。

繰り返しますが、プロジェクト構成は自由です。大切なのは、自分にとって理にかなった、効率よく作業できる構成にすることです。

それでは、このチュートリアルの核心であるGulpの設定に取り掛かりましょう!

Gulpfileを作成・設定する

Gulpfileには、インストール済みパッケージを読み込み、各種関数を実行するためのコードを書きます。コードの役割は大きく分けて2つあります。

  1. インストール済みパッケージをNodeモジュールとして初期化する
  2. Gulpタスクを作成・実行する

パッケージを初期化する

プロジェクトに追加したnpmパッケージの機能を活用するには、それらをNodeのモジュールとして読み込む必要があります(だからこそフォルダ名が「node_modules」なんです)。

Gulpfileの先頭に、次のようにモジュールを追加します。

var gulp = require('gulp');
var cssnano = require('gulp-cssnano');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');

これでパッケージが読み込まれたので、Gulpfile内でそれらの関数やオブジェクトを使えるようになりました。Node.js組み込みの関数も併用します。

Gulpタスクを作成する

Gulpタスクは、次のようなコードで作成します。

gulp.task('[関数名]', function(){
   // ここに処理を書く
}

こうすることで、コマンドラインに gulp [関数名] と入力すればタスクを実行できます。名前付きタスクは他のGulpタスクから呼び出せるので、この仕組みが重要になります。

今回作成するのは複数のタスクで、デフォルトタスクを実行するとすべてがまとめて走るようにします。

主に使う関数は以下の通りです。

  • .task() — タスクを作成する(前述の通り)
  • .src() — そのタスクで処理対象となるファイルを指定する
  • .pipe() — Gulpが使用するNodeストリームに関数を追加する。1つのタスク内で複数の関数をパイプできる
  • .dest() — 結果のファイルを指定した場所へ出力する
  • .watch() — 変更を検知する対象ファイルを指定する

詳しく知りたい方は、Gulp公式ドキュメントも参照してみてください。

準備はいいですか?それでは本題に入り、タスクを書いていきましょう!(『ムーラン』のBGMをお忘れなく)

Gulpに実行させたいタスクは次の4つです。

  • Sassタスク — SCSSをCSSにコンパイルし、最小化する
  • JSタスク — JSファイルを連結し、最小化(uglify)する
  • Watchタスク — SCSSやJSファイルの変更を検知し、タスクを再実行する
  • デフォルトタスク — コマンドラインで gulp と打ったときに、必要なタスクをすべて実行する

Sassタスク

まずtask()でタスクを作成し、「sass」という名前を付けます。

次に、タスクが実行する各処理を追加していきます。src()でソースファイルを app/style.scss に指定し、その後ろにpipe()で処理を繋いでいきます。

最初のpipe()ではsass()関数を実行します(Gulpfileの先頭で「sass」という名前で読み込んだgulp-sassモジュールです)。CSSファイルはSCSSファイルと同じ名前で自動的に保存されるため、ここでは style.css になります。

2番目のpipe()でcssnano()によりCSSを最小化し、最後にdist/cssフォルダへ出力します。

コード全体はこちらです。

gulp.task('sass', function(){
   return gulp.src('app/style.scss')
      .pipe(sass())
      .pipe(cssnano())
      .pipe(gulp.dest('dist/css'));
});

テスト用に、style.scssに適当なSCSSを入れておきます。

div {
    display: block;

    &.content {
        position: relative;
    }
}

.red {
    color: red;
}

個々のGulpタスクは、コマンドラインで gulp に続けてタスク名を入力すれば単独で実行できます。Sassタスクを試すには gulp sass と打ち、エラーが出ずに最小化された dist/style.css が生成されるか確認しましょう。

うまくいけば、コマンドラインに次のような表示が出ます。

[15:04:53] Starting 'sass'...
[15:04:53] Finished 'sass' after 121 ms

distフォルダを確認すると、確かにstyle.cssが存在し、開いてみると正しく最小化されたCSSになっています。

div{display:block}div.content{position:relative}.red{color:red}

これでSassタスクは完成です。次はJavaScriptに進みましょう!

JSタスク

JavaScriptのGulpタスクもSassタスクと似ていますが、いくつか異なるポイントがあります。

まずタスクを作成して「js」という名前を付け、ソースファイルを指定します。src()関数で複数のファイルを指定する方法はいくつかあります。

ひとつはワイルドカード(*)を使い、拡張子が.jsのすべてのファイルを対象にする方法です。

gulp.src('app/*.js')

ただしこの方法では、ファイルがアルファベット順にコンパイルされます。あるスクリプトが別のスクリプトに依存している場合、読み込み順序によってはエラーが発生する可能性があります。

スクリプトファイルの数が多くないなら、配列で個別に指定して順序を制御できます。src()関数は角括弧を使って配列を受け取れます。

gulp.src(['app/script.js', 'app/script2.js'])

JSファイルが多い場合は、依存ライブラリを「app/js/plugins」のような専用サブフォルダに分けておき、通常のスクリプトは親フォルダ「app/js」に置く方法がおすすめです。

そうすれば、ワイルドカードでライブラリ系スクリプトを先に読み込み、その後に通常のスクリプトを読み込む、といった制御ができます。

gulp.src(['app/js/lib/*.js', 'app/js/script/*.js'])

どの方法を選ぶかは、JSファイルの数や種類によって変わってきます。

ソースファイルを指定したら、残りの処理をpipe()で繋ぎます。まずconcat()でファイルを1つの大きなJSファイルに連結します。concat()には、出力ファイル名を引数として渡します。

その後、uglify()でJSファイルを最小化し、dest()で出力先に保存します。

JavaScriptタスクの完全なコードはこちらです。

gulp.task('js', function(){
    return gulp.src(['app/js/plugins/*.js', 'app/js/*.js'])
        .pipe(concat('all.js'))
        .pipe(uglify())
        .pipe(gulp.dest('dist'));
});

Sassタスクと同じように、コマンドラインで gulp js と入力すればテストできます。

[14:38:31] Starting 'js'...
[14:38:31] Finished 'js' after 36 ms

2つのメインタスクが完成したので、次はWatchタスクに進みます。

Watchタスク

Watchタスクは、指定したファイルの変更を監視します。変更を検知すると、指定されたタスクを実行し、その後も監視を続けます。

ここではwatch関数を2つ作成します。1つはSCSSファイル用、もう1つはJSファイル用です。

watch()関数は2つの引数を取ります。監視対象のパスと、変更検知時に実行するタスクです。

Sass用のwatch関数は、appフォルダ内のSCSSファイルを監視し、変更を検知したらSassタスクを実行します。

gulp.watch('app/*.scss', ['sass']);

JavaScript用のwatch関数では、Nodeの非常に便利な機能「globbing(グロブ)」を活用します。globbingとは、「**」という記号をフォルダとサブフォルダのワイルドカードとして使う手法です。app/jsフォルダ直下とapp/js/pluginsフォルダの両方にJSファイルがあるため、これが必要になります。

gulp.watch('app/js/**/*.js', ['js']);

glob(**)は、app/jsフォルダ内のどこにあるJSファイルでも探し出します。フォルダ直下でも、pluginsフォルダのような子フォルダの中でも見つけてくれます。これのおかげで、サブフォルダごとに個別にwatch()へ指定する手間が省けます。

Watchタスクの完全なコードはこちらです。

gulp.task('watch', function(){
gulp.watch('app/*.scss', ['sass']);
gulp.watch('app/js/**/*.js', ['js']);
});

もう少しで完成です!最後に作成するのは、デフォルトのGulpタスクです。

デフォルトGulpタスク

デフォルトタスクは、コマンドラインで gulp とだけ入力したときに実行されるタスクです。Gulpに「これを実行してほしい」と認識させるには、タスク名を必ず「default」にする必要があります。

やりたいことは、SassタスクとJSタスクを一度実行し、その後Watchタスクを走らせて以降のファイル変更に対応することです。

gulp.task('default', ['sass', 'js', 'watch']);

もちろん、default以外の名前で別のタスクを作ることもできます。たとえば、普段はCSSやJSを最小化せず、本番環境向けのビルド時だけ最小化したいとしましょう。

その場合は「minifyCSS」「minifyJS」というタスクを別途作成し、defaultタスクには含めず、defaultと同じ内容に加えてminifyタスクも実行する「prod」という新しいタスクを作ればよいのです。

index.htmlでの参照を確認する

Gulpの処理が正常に動くようになったら、index.htmlが正しいCSS・JSファイルを参照しているか確認しましょう。

今回の例では、<head>内に dist/style.css へのCSS参照を追加します。

<link rel="stylesheet" href="dist/style.css">

そして<body>内に、dist/all.js を参照するscriptタグを追加します。

<script src="dist/all.js"></script>

まとめ

最後までお疲れさまでした!このGulp入門チュートリアルが皆さんのお役に立てば幸いです。

冒頭でも述べたように、今回はnpmとGulpのごく基本的な部分だけを扱うシンプルなチュートリアルでした。

実際のところ、多くの開発者はGulpfileにさらに多くのタスクを追加しています。より高度なトピックについての記事もぜひ見てみたい、という方はコメントでお知らせください!

なお、このチュートリアルの全コードはGitHubアカウントで公開しています。

このチュートリアルが役に立ったと思ったら、ぜひシェアしたり、コメントで感想を聞かせてください!

  1. 【初心者向け】Androidブロードキャストレシーバーの基礎と実装入門

    安定したインターネット接続が不可欠なアプリケーションを開発しているとしましょう。ネットワーク接続の状態が変化した際に、そのことをアプリへ通知させたい——そんなとき、どうすればよいのでしょうか?一つの解決策として、常時インターネット接続を監視し続けるサービスを実装する方法が考えられます。しかし、この実装にはさまざまな問題があるため、検討する価値すらありません。この問題に対する正しい答えがブロードキャストレシーバー(Broadcast Receiver)です。ブロードキャストレシーバーは、指定したイベントの変化を常にリッスンしてくれます。ブロードキャストレシーバーは、アプリケーションの状態に関わら

  2. 初心者向け Jetpack Compose チュートリアル – コンポーザブルと再構成(リコンポジション)の基本を理解しよう

    このチュートリアルでは、AndroidのJetpack Compose UIライブラリに関する基本的な概念と用語をわかりやすく解説します。本記事はComposeの初心者向けガイドですが、Android開発自体の初心者向けガイドではありません。そのため、少なくとも1〜2個程度はアプリケーションを開発した経験があること(必ずしもComposeを使った開発である必要はありません)を前提としています。始める前にひとつだけ補足します。当初は、より経験豊富な開発者向けの続編記事を書くつもりでしたが、Leland Richardson氏による2部構成の記事シリーズに出会い、方針を転換しました。Leland氏