マシンを活用する方法:タスクランナーで生産性を高める
公開: 2022-03-10タスクランナーは、ほとんどのWebおよびモバイルアプリケーションの背後で静かに苦労しているヒーロー(またはあなたの視点によっては悪役)です。 タスクランナーは、ファイルの連結、開発サーバーの起動、コードのコンパイルなど、多数の開発タスクの自動化を通じて価値を提供します。 この記事では、Grunt、Gulp、Webpack、npmスクリプトについて説明します。 また、開始するために、それぞれの例をいくつか示します。 最後に、この投稿のアイデアをアプリケーションに統合するための簡単な勝利とヒントをいくつか紹介します。
タスクランナーとJavaScriptの進歩は一般的に、フロントエンドの状況を過度に複雑にしているという感情があります。 ビルドスクリプトを微調整するのに1日を費やすことが必ずしもあなたの時間を最大限に活用するとは限らないことに同意しますが、タスクランナーは、適切かつ適度に使用するといくつかの利点があります。 これがこの記事の目標であり、最も人気のあるタスクランナーの基本をすばやくカバーし、これらのツールがワークフローにどのように適合するかについての想像力を刺激するための確かな例を提供します。
SmashingMagの詳細:
- Oh-My-ZSHとZでコマンドラインパワーユーザーになる
- PostCSSの紹介
- Gruntで立ち上がって実行する
- ガルプで構築
コマンドラインに関する注意
タスクランナーとビルドツールは、主にコマンドラインツールです。 この記事全体を通して、コマンドラインを操作する上での適切なレベルの経験と能力を前提としています。 cd
、 ls
、 cp
、 mv
などの一般的なコマンドの使用方法を理解している場合は、さまざまな例を見ていくうちに大丈夫です。 これらのコマンドの使用に不安がある場合は、SmashingMagazineにすばらしい紹介記事があります。 それらすべての祖父であるGruntと一緒に物事を始めましょう。
グラント
Gruntは、最初の人気のあるJavaScriptベースのタスクランナーでした。 私は2012年から何らかの形でGruntを使用しています。Gruntの背後にある基本的な考え方は、特別なJavaScriptファイルGruntfile.js
を使用して、タスクを実行するためのさまざまなプラグインを構成することです。 プラグインの広大なエコシステムがあり、非常に成熟した安定したツールです。 Gruntには、プラグインの大部分(現在約5,500)のインデックスを作成する素晴らしいWebディレクトリがあります。 Gruntの単純な天才は、JavaScriptと、共通の構成ファイル(makefileなど)のアイデアの組み合わせです。これにより、より多くの開発者がGruntに貢献し、プロジェクトで使用できるようになりました。 また、Gruntをプロジェクトの他の部分と同じバージョン管理システムの下に配置できることも意味します。
Gruntは戦闘テスト済みで、安定しています。 執筆の頃、バージョン1.0.0がリリースされました。これは、Gruntチームにとって大きな成果です。 Gruntは主にさまざまなプラグインを連携して動作するように構成しているため、非常にすばやく絡み合う可能性があります(つまり、変更が面倒で混乱する可能性があります)。 ただし、少しの注意と整理(タスクを論理ファイルに分割する!)を行うことで、どのプロジェクトでも驚異的なことを実行できます。
必要なタスクを実行するためのプラグインが利用できないというまれなケースでは、Gruntが独自のプラグインを作成する方法に関するドキュメントを提供しています。 独自のプラグインを作成するために知っておく必要があるのは、JavaScriptとGruntAPIだけです。 独自のプラグインを作成する必要はほとんどないので、非常に人気があり便利なプラグインでGruntを使用する方法を見てみましょう。
例

Gruntが実際にどのように機能するかを見てみましょう。 コマンドラインでgrunt
を実行すると、ディレクトリのルートでGruntfile.js
を検索するGruntコマンドラインプログラムがトリガーされます。 Gruntfile.js
には、Gruntが行うことを制御する構成が含まれています。 この意味で、 Gruntfile.js
は、料理人(つまり、プログラムであるGrunt)が従う一種の料理本と見なすことができます。 そして、他の優れたクックブックと同様に、 Gruntfile.js
には多くのレシピ(つまりタスク)が含まれます。
Grunticonプラグインを使用して、架空のWebアプリのアイコンを生成することにより、Gruntのペースを調整します。 GrunticonはSVGのディレクトリを取り込んで、いくつかのアセットを吐き出します。
- SVGがbase-64であるCSSファイル-背景画像としてエンコードされています。
- 背景画像としてbase-64でエンコードされたSVGのPNGバージョンを含むCSSファイル。
- アイコンごとに個別のPNGファイルを参照するCSSファイル。
3つの異なるファイルは、ブラウザとモバイルデバイスのさまざまな機能を表しています。 最新のデバイスは、高解像度のSVGを単一のリクエスト(つまり、単一のCSSファイル)として受信します。 SVGを処理しないが、base-64でエンコードされたアセットを処理するブラウザーは、base-64PNGスタイルシートを取得します。 最後に、これら2つのシナリオを処理できないブラウザは、PNGを参照する「従来の」スタイルシートを取得します。 これはすべて、SVGの単一のディレクトリからのものです。
このタスクの構成は次のようになります。
module.exports = function(grunt) { grunt.config("grunticon", { icons: { files: [ { expand: true, cwd: 'grunticon/source', src: ["*.svg", ".png"], dest: 'dist/grunticon' } ], options: [ { colors: { "blue": "blue" } } ] } }); grunt.loadNpmTasks('grunt-grunticon'); };
ここでさまざまな手順を見ていきましょう。
- Gruntをグローバルにインストールする必要があります。
- プロジェクトのルートに
Gruntfile.js
ファイルを作成します。npm i grunt grunt-grunticon --save-dev
を介して、Grunticonと一緒にpackage.json
ファイルにnpm依存関係としてGruntをインストールすることもお勧めします。 - SVGのディレクトリと宛先ディレクトリ(ビルドされたアセットが配置される場所)を作成します。
- HTMLの
head
に小さなスクリプトを配置します。これにより、ロードするアイコンが決まります。
Grunticonタスクを実行する前のディレクトリは次のようになります。
|-- Gruntfile.js |-- grunticon | `-- source | `-- logo.svg `-- package.json
|-- Gruntfile.js |-- grunticon | `-- source | `-- logo.svg `-- package.json
これらのものをインストールして作成したら、上記のコードスニペットをGruntfile.js
にコピーできます。 これで、コマンドラインからgrunt grunticon
を実行して、タスクの実行を確認できるようになります。
上記のスニペットはいくつかのことを行います。
-
grunticon
という名前の32行目のGruntに新しいconfig
オブジェクトを追加します。 -
icons
オブジェクトにGrunticonのさまざまなオプションとパラメータを入力します。 - 最後に、loadNPMTasksを介して
loadNPMTasks
プラグインをプルします。
Grunticon後のディレクトリは次のようになります。
|-- Gruntfile.js |-- dist | `-- grunticon | |-- grunticon.loader.js | |-- icons.data.png.css | |-- icons.data.svg.css | |-- icons.fallback.css | |-- png | | `-- logo.png | `-- preview.html |-- grunticon | `-- source | `-- logo.svg `-- package.json
|-- Gruntfile.js |-- dist | `-- grunticon | |-- grunticon.loader.js | |-- icons.data.png.css | |-- icons.data.svg.css | |-- icons.fallback.css | |-- png | | `-- logo.png | `-- preview.html |-- grunticon | `-- source | `-- logo.svg `-- package.json
どうぞ—終了しました! 数行の構成といくつかのパッケージのインストールで、アイコンアセットの生成が自動化されました。 うまくいけば、これはタスクランナーの力、つまり信頼性、効率性、移植性を示し始めます。
Gulp:ビルドシステム用のLEGOブロック
Gulpは、Gruntの後に登場し、すべての構成ではなく実際のコードであるビルドツールを目指していました。 設定より規約の背後にある考え方は、コードが無限の設定ファイルの変更よりもはるかに表現力があり、柔軟性があるということです。 Gulpのハードルは、Gruntよりも多くの技術的知識が必要なことです。 Node.jsストリーミングAPIに精通し、基本的なJavaScriptの記述に慣れている必要があります。
GulpがNode.jsストリームを使用することが、Gruntよりも高速である主な理由です。 ストリームを使用するということは、ファイルシステムをファイル変換の「データベース」として使用する代わりに、Gulpがメモリ内変換を使用することを意味します。 ストリームの詳細については、Node.jsストリームAPIのドキュメントとストリームハンドブックをご覧ください。
例

Gruntセクションと同様に、JavaScriptモジュールを単一のアプリファイルに連結するという簡単な例を使用して、Gulpのペースを説明します。
Gulpを実行することは、Gruntを実行することと同じです。 gulp
コマンドラインプログラムは、それが実行されているディレクトリでレシピのクックブック(つまりGulpfile.js
)を探します。
各ページが行うリクエストの数を制限することは、Webパフォーマンスのベストプラクティスと見なされます(特にモバイルで)。 ただし、機能が複数のファイルに分割されている場合は、他の開発者とのコラボレーションがはるかに簡単になります。 タスクランナーを入力します。 Gulpを使用して、アプリケーション用にJavaScriptの複数のファイルを組み合わせることができるため、モバイルクライアントは多数ではなく単一のファイルをロードする必要があります。
Gulpには、Gruntと同じプラグインの大規模なエコシステムがあります。 したがって、このタスクを簡単にするために、gulp-concatプラグインを使用します。 プロジェクトの構造が次のようになっているとしましょう。
|-- dist | `-- app.js |-- gulpfile.js |-- package.json `-- src |-- bar.js `-- foo.js
2つのJavaScriptファイルがsrc
ディレクトリにあり、それらを1つのファイルapp.js
に結合してdist/
ディレクトリに配置します。 これを実現するには、次のGulpタスクを使用できます。
var gulp = require('gulp'); var concat = require('gulp-concat'); gulp.task('default', function() { return gulp.src('./src/*.js') .pipe(concat('app.js')) .pipe(gulp.dest('./dist/')); });
重要なビットはgulp.task
コールバックにあります。 そこで、 gulp.src
APIを使用して、 src
ディレクトリで.js
で終わるすべてのファイルを取得します。 gulp.src
APIはこれらのファイルのストリームを返し、それを( pipe
APIを介して)gulp-concatプラグインに渡すことができます。 次に、プラグインはストリーム内のすべてのファイルを連結し、それをgulp.dest
関数に渡します。 gulp-dest
関数は、受け取った入力をディスクに書き込むだけです。
Gulpがストリームを使用して、タスクの「ビルディングブロック」または「チェーン」を提供する方法を確認できます。 典型的なGulpワークフローは次のようになります。
- 特定のタイプのすべてのファイルを取得します。
- それらのファイルをプラグイン(concat!)に渡すか、何らかの変換を行います。
- それらの変換されたファイルを別のブロック(この場合、チェーンを終了する
dest
ブロック)に渡します。
Gruntの例のように、プロジェクトディレクトリのルートからgulp
を実行するだけで、 Gulpfile.js
ファイルで定義されているdefault
のタスクがトリガーされます。 このタスクはファイルを連結し、アプリまたはWebサイトの開発に取り掛かりましょう。

Webpack
JavaScriptタスクランナークラブに新しく追加されたのはWebpackです。 Webpackは、それ自体を「モジュールバンドラー」と呼んでいます。つまり、CommonJSパターンなどのモジュールパターンを使用して、複数の個別のファイルからJavaScriptコードのバンドルを動的に構築できます。 Webpackには、ローダーと呼ばれるプラグインもあります。
Webpackはまだかなり若く、かなり密度が高く、紛らわしいドキュメントがあります。 したがって、公式ドキュメントに飛び込む前の出発点として、PeteHuntのWebpackリポジトリをお勧めします。 また、タスクランナーに慣れていない場合や、JavaScriptに習熟していない場合は、Webpackをお勧めしません。 これらの問題はさておき、GruntとGulpの一般的な広さよりもさらに具体的なツールです。 多くの人がこの理由でGruntまたはGulpと一緒にWebpackを使用し、Webpackがモジュールのバンドルに優れ、GruntまたはGulpがより一般的なタスクを処理できるようにします。
Webpackを使用すると、最終的にブラウザー用のNode.jsスタイルのコードを記述できるようになり、生産性が大幅に向上し、モジュールを介してコードの関心の分離が明確になります。 Webpackを使用して、Gulpの例で行ったのと同じ結果を達成し、複数のJavaScriptファイルを1つのアプリファイルに結合してみましょう。
例

Webpackは、ES6コードをES5にトランスパイルするためにBabelでよく使用されます。 コードをES6からES5にトランスパイルすることで、開発者は新しいES6標準を使用しながら、ES6をまだ完全にサポートしていないブラウザーまたは環境にES5を提供できます。 ただし、この例では、Gulpの例から2つのファイルの単純なバンドルを作成することに焦点を当てます。 まず、Webpackをインストールし、構成ファイルwebpack.config.js
を作成する必要があります。 ファイルは次のようになります。
module.exports = { entry: "./src/foo.js", output: { filename: "app.js", path: "./dist" } };
この例では、Webpackをsrc/foo.js
ファイルにポイントして、依存関係グラフのウォークを開始します。 また、 foo.js
ファイルを次のように更新しました。
//foo.js var bar = require("./bar"); var foo = function() { console.log('foo'); bar(); }; module.exports = foo;
そして、 bar.js
ファイルを次のように更新しました。
//bar.js var bar = function() { console.log('bar'); }; module.exports = bar;
これは非常に基本的なCommonJSの例です。 これらのファイルが関数を「エクスポート」していることに気付くでしょう。 基本的に、CommonJSとWebpackを使用すると、アプリケーション全体でインポートおよびエクスポートできる自己完結型のモジュールにコードを編成し始めることができます。 Webpackは、importおよびexportキーワードに従い、すべてを1つのファイルdist/app.js
にバンドルするのに十分なほどスマートです。 連結タスクを維持する必要はなくなり、代わりにコードの構造を順守する必要があります。 ずっといい!
拡張
Webpackは、「単なるJavaScript」という点でGulpに似ています。 ローダーシステムを介して他のタスクランナータスクを実行するように拡張できます。 たとえば、css-loaderとsass-loaderを使用して、SassをCSSにコンパイルしたり、 require
CommonJSパターンをオーバーロードしてJavaScriptでSassを使用したりすることもできます! ただし、私は通常、JavaScriptモジュールを構築するためだけにWebpackを使用し、タスクを実行するために別のより汎用的なアプローチを使用することを推奨しています(たとえば、Webpackとnpmスクリプト、またはWebpackとGulpを使用して他のすべてを処理します)。
npmスクリプト
npmスクリプトは最新の流行に敏感な流行であり、それには正当な理由があります。 これらすべてのツールで見たように、プロジェクトに導入される可能性のある依存関係の数は、最終的には制御不能になる可能性があります。 ビルドプロセスのエントリポイントとしてnpmスクリプトを提唱しているのを最初に見たのは、JamesHallidayによるものでした。 彼の投稿は、npmスクリプトの無視された力を完全に要約しています(私の強調):
JavaScriptプロジェクトでビルド自動化を行うための優れたツールがいくつかありますが、あまり知られていないnpm run
コマンドは、非常に小さな構成フットプリントを維持しながら、必要なすべてのことを完全に実行できるため、魅力を感じたことはありません。
最後にその最後のビットをキャッチしましたか? npmスクリプトの主な魅力は、「構成のフットプリントが非常に小さい」ことです。 これが、npmスクリプトが普及し始めた主な理由の1つです(ほぼ4年後、悲しいことに)。 Grunt、Gulp、さらにはWebpackを使用すると、最終的には、バイナリをラップしてプロジェクト内の依存関係の数を2倍にするプラグインに溺れ始めます。
Keith Cirkelには、GruntまたはGulpの代わりにnpmを使用するためのチュートリアルがあります。 彼は、npmスクリプトの力を完全に活用する方法の青写真を提供し、不可欠なプラグインであるParallel Shell(およびそれと同じような他の多くのプラグイン)を紹介しました。
例
Gruntに関するセクションでは、人気のあるモジュールGrunticonを使用して、GruntタスクでSVGアイコン(PNGフォールバック付き)を作成しました。 これは、私にとってnpmスクリプトの1つの問題点でした。 しばらくの間、Grunticonを使用するためだけに、プロジェクト用にGruntをインストールしたままにしておきます。 npmタスクでGruntに文字通り「シェルアウト」して、タスクランナーの開始を実現します(または、仕事でそれを呼び出し始めたときに、ビルドツールターダッキン)。 ありがたいことに、Grunticonの背後にある素晴らしいグループであるThe Filament Groupは、ツールのスタンドアロン(つまり、Gruntフリー)バージョンであるGrunticon-Libをリリースしました。 それでは、それを使用してnpmスクリプトでいくつかのアイコンを作成しましょう!
この例は、一般的なnpmスクリプトタスクよりも少し高度です。 典型的なnpmスクリプトタスクは、適切なフラグまたは構成ファイルを使用したコマンドラインツールの呼び出しです。 SassをCSSにコンパイルするより一般的なタスクは次のとおりです。
"sass": "node-sass src/scss/ -o dist/css",
さまざまなオプションを備えた1行だけであることがわかりますか? タスクファイルやスピンアップするビルドツールは必要ありません。コマンドラインからnpm run sass
だけで、SassがCSSになります。 npmスクリプトの非常に優れた機能の1つは、スクリプトタスクをチェーン化する方法です。 たとえば、Sassタスクを実行する前にタスクを実行したいとします。 次のような新しいスクリプトエントリを作成します。
"presass": "echo 'before sass',
そうです: pre-
はプレフィックスを理解します。 また、 post-
プレフィックスも理解します。 pre-
プレフィックスまたはpost-
プレフィックスが付いた別のスクリプトエントリと同じ名前のスクリプトエントリは、そのエントリの前または後に実行されます。
アイコンを変換するには、実際のNode.jsファイルが必要です。 しかし、それはそれほど深刻ではありません。 tasks
ディレクトリを作成し、 grunticon.js
やicons.js
など、プロジェクトで作業している人にとって意味のある名前の新しいファイルを作成するだけです。 ファイルが作成されたら、Grunticonプロセスを起動するJavaScriptを記述できます。
注:これらの例はすべてES6を使用しているため、タスクを実行するためにbabel-nodeを使用します。 ES5とNode.jsの方が快適であれば、簡単に使用できます。
import icons from "grunticon-lib"; import globby from "globby"; let files = globby.sync('src/icons/*'); let options = { colors: { "blue": "blue" } }; let icon = new icons(files, 'dist/icons', options); icon.process();
コードに入り、何が起こっているのかを理解しましょう。
-
grunticon-lib
とglobby
の2つのライブラリをimport
ます(つまり、必要とします)。 Globbyは私のお気に入りのツールの1つであり、ファイルやグロブの操作がとても簡単になります。 Globbyは、PromiseをサポートしてNode.js Glob(./*.js
。jsを介してすべてのJavaScriptファイルを選択)を拡張します。 この場合、これを使用してsrc/icons
ディレクトリ内のすべてのファイルを取得しています。 - これを行ったら、
options
オブジェクトにいくつかのオプションを設定し、次の3つの引数を指定してGrunticon-Libを呼び出します。- アイコンファイル、
- 目的地、
- ライブラリがこれらのアイコンを引き継いでかみ砕き、最終的に必要なディレクトリにSVGとPNGバージョンを作成します。
- ほぼ完了です。 これは別のファイルにあることを忘れないでください。このファイルをnpmスクリプトから呼び出すには、
"icons": "babel-node tasks/icons.js"
ように「フック」を追加する必要があります。 - これで、
npm run icons
を実行でき、アイコンは毎回作成されます。
npmスクリプトは、プラグインの負担なしに、他のタスクランナーと同じレベルのパワーと柔軟性を提供します。
ここで取り上げるタスクランナーの内訳
道具 | 長所 | 短所 |
---|---|---|
グラント | 実際のプログラミング知識は必要ありません | ここで取り上げるタスクランナーの中で最も冗長なもの |
ゴクゴク | 実際のJavaScriptとストリームを使用してタスクを構成する | JavaScriptの知識が必要です |
プロジェクトにコードを追加します(バグが増える可能性があります) | ||
Webpack | モジュールバンドルでクラス最高 | より一般的なタスク(たとえば、SassからCSSへ)ではより困難 |
npmスクリプト | コマンドラインツールとの直接対話。 | 一部のタスクは、タスクランナーなしでは実行できません。 |
いくつかの簡単な勝利
これらの例とタスクランナーはすべて圧倒されるように見えるかもしれないので、それを分解してみましょう。 まず、現在使用しているタスクランナーやビルドシステムを、ここに記載されているものに即座に置き換える必要があることを、この記事から離れないでください。 このような重要なシステムの交換は、あまり考慮せずに行うべきではありません。 既存のシステムをアップグレードするための私のアドバイスは次のとおりです。段階的に実行します。
ラッパースクリプト!
漸進的なアプローチの1つは、既存のタスクランナーの周りにいくつかの「ラッパー」npmスクリプトを記述して、実際に使用されるタスクランナーの外にあるビルドステップの共通語彙を提供することです。 ラッパースクリプトは、次のように単純にすることができます。
{ "scripts": { "start": "gulp" } }
多くのプロジェクトでは、 start
およびtest
のnpmスクリプトブロックを利用して、新しい開発者がすぐに順応できるようにしています。 ラッパースクリプトは、タスクランナーのビルドチェーンに別の抽象化レイヤーを導入しますが、npmプリミティブ(例: test
)を標準化できる価値があると思います。 npmコマンドは、個々のツールよりも長持ちします。
小さなWebpackを振りかける
あなたやあなたのチームがJavaScriptの脆弱な「バンドル順序」を維持することに苦痛を感じている場合、またはES6へのアップグレードを検討している場合は、これを既存のタスク実行システムにWebpackを導入する機会と考えてください。 Webpackは、必要なだけ使用したり、使用したりすることができ、それでもそこから価値を引き出すことができるという点で優れています。 アプリケーションコードをバンドルするだけで開始し、次にbabel-loaderをミックスに追加します。 Webpackには非常に豊富な機能があるため、かなりの期間、ほぼすべての追加機能や新機能に対応できます。
npmスクリプトでPostCSSを簡単に使用
PostCSSは、CSSが作成されて前処理されると、CSSを変換および拡張するプラグインの優れたコレクションです。 言い換えれば、それはポストプロセッサです。 npmスクリプトを使用してPostCSSを活用するのは簡単です。 前の例のようなSassスクリプトがあるとします。
"sass": "node-sass src/scss/ -o dist/css",
npmスクリプトのlifecycle
キーワードを使用して、Sassタスクの後に自動的に実行されるスクリプトを追加できます。
"postsass": "postcss --use autoprefixer -c postcss.config.json dist/css/*.css -d dist/css",
このスクリプトは、Sassスクリプトが実行されるたびに実行されます。 別のファイルで構成を指定できるため、postcss-cliパッケージは優れています。 この例では、新しいタスクを実行するために別のスクリプトエントリを追加していることに注意してください。 これは、npmスクリプトを使用する場合の一般的なパターンです。 アプリに必要なさまざまなタスクをすべて実行するワークフローを作成できます。
結論
タスクランナーは実際の問題を解決できます。 私はタスクランナーを使用して、ターゲットが本番環境であるかローカル開発であるかに応じて、JavaScriptアプリケーションのさまざまなビルドをコンパイルしました。 また、タスクランナーを使用して、Handlebarsテンプレートをコンパイルし、Webサイトを本番環境にデプロイし、Sassで欠落しているベンダープレフィックスを自動的に追加しました。 これらは簡単なタスクではありませんが、タスクランナーにまとめられると、簡単になります。
タスクランナーは絶えず進化し、変化しています。 私は現在の時代精神で最も使用されているものをカバーしようとしました。 しかし、ブロッコリー、ブランチ、ハープなど、私が言及していないものもあります。 これらは単なるツールであることを忘れないでください。他のすべての人が使用しているためではなく、特定の問題を解決する場合にのみ使用してください。 ハッピータスク実行中!