タスクランナーとしてのnpm-scripts(パート2)

前回(パート1)の記事では、npm-scriptsをタスクランナーとして使う方法の前置きと、用意したサンプルプロジェクトにCSSのビルドタスク機能を実装しました。

パート2ではそのサンプルプロジェクトにJavaScriptのビルドタスク、画像圧縮、またそれらの処理をまとめて並列実行する機能を追加していきたいと思います。

JavaScriptのビルドタスク

実現したいJavaScriptの処理として、ES6仕様で書かれたJavaScriptコードをrequire()で記述された依存解決を行い結合し、さらにES5の標準仕様に変換しつつコードを圧縮&難読化して出力することとします。

必要なツールは下記の通りです。

  • browserify
  • babelify
  • uglify-es
  • mkdirp
browserify
依存解決を行い、Node.jsのrequire()をブラウザで動作可能にするツール。
browserify - npm
Browserify
babelify
BabelのBrowserfy用transformモジュール。browserifyの-tオプションで指定する。
babelify - npm
Babel · The compiler for writing next generation JavaScript
uglify-es
ES6+をサポートするJavaScriptの圧縮・最適化ツール。
uglify-es - npm
mkdirp
指定したディレクトリが存在しない場合、ディレクトリを再帰的に作成する。mkdir -p のNode.js版。
mkdirp - npm

まとめてインストールします。

$ npm i -D browserify babelify uglify-es mkdirp

そして次のようにタスクを記述します。

"scripts": {
    "build:js": "mkdirp dist/js && browserify -t babelify src/js/main.js | uglifyjs -c -m > dist/js/main.js"
},

まず、出力先を確保するためにmkdirpでフォルダを作成します。それから直列でタスクを実行するために&&で繋ぎ、browserifyの-t(--transform)オプションでbabelifyをtransformモジュールとして指定して処理を行います。 シェルスクリプトでは、タスクを連結して処理する場合、&&&が使えますが、それぞれ直列、並列で実行します。

次に実行結果をパイプでuglifyjsに渡します。-c(--compress)-m(--mangle)オプションを付けることで圧縮と難読化の処理を行い、最後にリダイレクションを使ってdist/js/main.jsとして出力します。

下記コマンドで上記のタスクを実行できます。

$ npm run build:js

これでJavaScriptのビルドタスクが完成しました。

画像圧縮

Webサイトのパフォーマンス性の向上に画像の圧縮は欠かせないタスクです。今回導入するimgaemin-cliは、JPG、PNG、GIF、SVGに対応した画像圧縮ツールです。

imgaemin-cli
画像圧縮ツール。imageminのCLI。
imagemin-cli - npm

imagemin-cliをインストールします。

$ npm i -D imagemin-cli

scriptsにタスクを追加します。

"scripts": {
    "build:images": "imagemin src/images/* -o dist/images"
},

imagesタスクで、src/imagesフォルダにある画像を圧縮処理した後、dist/imagesフォルダに出力します。シンプルですね。

distフォルダの初期化

画像のタスクができたところでちょっと工夫してみましょう。開発中src/imagesフォルダに画像を追加・削除していると、distフォルダにはsrcから既に削除されたはずの画像が残ってしまうことも考えられます。このままリモートレポジトリにプッシュして汚してしまうことを避けるために、distフォルダをリセットする処理を組み込みたいと思います。

次のツールを導入します。

rimraf
ディレクトリ内を再帰的に強制削除します。rm -rf のNode.js版。
rimraf - npm

rimrafをインストールします。

$ npm i -D rimraf

scriptsにタスクを追加します。

"scripts": {
    "clean": "rimraf dist/{css/*,js/*,images/*}"
},

このタスクを実行すると、dist以下の、css、js、imagesフォルダの中身が空になります。

npm-run-all

これまで作成した、JavaScript、CSS、画像のタスクを次のように一つにまとめたいと思います。→ distフォルダをリセットした後、JavaScriptとCSSのビルドタスク、および画像圧縮タスクを並列で実行。

次のツールを使います。

npm-run-all
複数のnpm-scriptsをまとめて並列・直列で実行できる。
npm-run-all - npm

npm-run-allをインストールします。

$ npm i -D npm-run-all

次のようにタスクをまとめます。

"scripts": {
        "build": "npm run clean & npm-run-all -p build:*"
},

最初にdistファルダをリセットした後、後続する処理をまとめて実行します。

タスクを並列に実行するために、-p(--parallel)オプションを付けます。またワイルドカードを使って、build:cssbuild:jsbuild:imagesをまとめて指定します。

これで、下記のコマンド一つでビルド時に必要な処理を実行できるようになりました。

$ npm run build

現時点のpackage.jsonはこのようになっています。

{
  "name": "sample",
  "version": "1.0.0",
  "scripts": {
    "clean": "rimraf dist/{css/*,js/*,images/*}",
    "build:css": "postcss src/css/main.pcss -o dist/css/main.css --no-map",
    "build:js": "mkdirp dist/js && browserify -t babelify src/js/main.js | uglifyjs -c -m > dist/js/main.js",
    "build:images": "imagemin src/images/* -o dist/images",
    "build": "npm run clean & npm-run-all -p build:*"
  },
  "devDependencies": {
    "babelify": "^7.3.0",
    "browserify": "^14.4.0",
    "cssnano": "^3.10.0",
    "imagemin-cli": "^3.0.0",
    "mkdirp": "^0.5.1",
    "npm-run-all": "^4.0.2",
    "postcss-cli": "^4.1.0",
    "postcss-cssnext": "^3.0.2",
    "postcss-import": "^10.0.0",
    "rimraf": "^2.6.1",
    "uglify-es": "^3.0.26"
  }
}

残りのタスクは次回パート3の記事に続きたいと思います。