Javascript

【2020年のタスクランナーはこれ!】npm scriptsを使ってみた【脱gulp】

2020年のタスクランナー、【脱gulp】でnpm scriptsを使っていくための導入記事です。sassの環境構築やローカルサーバーの立ち上げもnpm scriptsで対応可能なので説明していきます。

はじめに

以前、【Babel】を使ってES6をIE11に対応させる方法 で簡単なnpm scriptsを使用してみました。

以下は、その時のnpm scriptの例。

$ "babel": "./node_modules/.bin/babel src --out-dir js"

これで npm run babel を実行することでトランスパイルされるというものでした。

以前までタスクランナーにgulpを使用しているのですが、できれば脱gulp、そしてnpm scriptsに移行していきたいと考えていました。

今回はnpm scriptsについて深く知って、以下を目標に進めていきます。


sassの自動コンパイル&圧縮処理
babelを使用してjavascriptの自動トランスパイル&圧縮処理
browser-syncでブラウザリロード

npm scriptsとは

npmはpackage.jsonの「scripts」箇所に記述することで、シェルスクリプトやaliasコマンドを登録・実行することができます。

Frontend Developer Roadmap 2020版でも推奨

Frontend Developer Roadmap 2020版でもGulpよりnpm scriptsの使用が推奨されています。

Frontend Developer Roadmap 2020版を詳しく見たい方は以下から。

https://roadmap.sh/frontend

タスクランナー「gulp」との比較

以下、タスクランナーgulpとの比較です。

メリット

・豊富なnode_modulesをそのまま使用できる。
・npmのパッケージ更新でタスクランナーがエラーになることがない。
・タスクランナー(gulp,grunt等)を学ぶ必要がなくなる。

デメリット

・package.jsonの記述量が多くなる(肥大化する)
・可読性はタスクランナーの記述の方が高い気がする。
・タスクランナーに比べて柔軟性・拡張性が低い。

ディレクトリ構成を決める

今回は以下のディレクトリ構成で環境を構築していきます。

dist/css
dist/js
dist/index.html
src/sass/style.scss
src/js/index.js
package.json
node_modules
babel.config.json

srcフォルダ内のファイルをコンパイル・トランスパイルしてdistフォルダに生成する流れです。

npm scriptsの準備

以前【Babel】を使ってES6をIE11に対応させる方法 で作成した環境をもとにnpm scriptsを使用した環境構築をしたいと思います。

軽くおさらいですが、node.jsの準備ができた状態で、以下のコマンドを入力してpackage.jsonが作成します。(作成中の質問は全てenterでOK)

$ npm init

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

今回の環境構築の目標を再度確認します。


sassの自動コンパイル&圧縮処理
babelを使用してjavascriptの自動トランスパイル&圧縮処理
browser-syncでブラウザリロード

これに必要なnpmパッケージをインストールしていきます。

sassのコンパイル処理

node-sassのパッケージをインストールします。
以下のコマンドを実行します。

$ npm install node-sass --save-dev

npm scriptsの記述

package.jsonのscriptsに以下を記述を追加します。

"css:sass": "node-sass src/sass/style.scss -o dist/css --output-style expanded --source-map dist/css"

node-sassのオプション

-o,–output出力するディレクトリを指定
–output-style書き出しのスタイルを指定
(nested | expanded | compact | compressed)
–source-mapSourceMapの書き出し先ディレクトリを指定
–watchディレクトリ内・ファイルを監視し、更新されたらコンパイルする

ベンダープレフィックス付与と圧縮

node-sassでコンパイルしたCSSに、ベンダープレフィックスを自動的に付与、その後CSSを圧縮させます。
以下のコマンドで必要なパッケージをインストールします。

$ npm install postcss-cli cssnano autoprefixer --save-dev

postcss-cli

postcssの本体です。後述のパッケージを使用するために必要です。

cssnano

CSSファイルをminify(圧縮)してくれます。

autoprefixer

ベンダープレフィックスを自動で付与してくれます。

npm scriptsの記述

package.jsonのscriptsに以下を記述を追加します。

"css/postcss": "postcss dist/css/style.css -o dist/css/style.min.css"

postcss.config.jsの設定

PostCSS用の設定ファイルを作成します。

module.exports = {
    plugins: [
        require('autoprefixer')(),
        require('cssnano')({
            preset: 'default',
        })
    ]
}

browserslistを設定する

ベンダープレフィックスを付与する範囲を指定します。「browserslist」はpackage.jsonに記述します。

  "browserslist": [
    ">0.25% in JP",
    "not ie <= 10",
    "not op_mini all"
  ]

browserslistの記述については以下もご参考にください。


browserl.ist

sassの処理をまとめる

ここまでのタスクをまとめて1つのスクリプトで実行できるようにします。

流れを確認します。

SCSSファイルをコンパイルする

CSSファイルにベンダープレフィックスを付与する

CSSファイルを圧縮する

実行順序について(補足)

タスク連結の際の補足です。

npm scriptsは「&」や「&&」を使い分けることで実行順序を指定することができます。(今回は次項でnpm-run-allを使用します。)

並列に実行

「&」で繋げるとそれぞれのscriptを並列に実行。

直列に実行

「&&」で繋げるとそれぞれのscriptを直列に実行。

npm-run-allを利用する

今回はタスクをまとめる際に便利な「npm-run-all」を利用します。
以下のコマンドでnpm-run-allをインストールします。

$ npm install npm-run-all --save-dev

npm scriptsの記述

package.jsonのscriptsに以下を記述を追加します。

"css": "npm-run-all -s css:*"

内容の意味としては、

npm-run-allを使用して、「css:」とついたタスク名を記述の順番通りに実行する。

という感じです。

npm-run-allのオプションの説明です。

-p, –parallelタスクを並行処理
-s, –sequentialタスクを順次処理*
*順次とは、package.jsonのscriptの記述順になります。

Javascriptを圧縮するタスクを作成する

次にJavascriptのタスクを作成していきます。JSを圧縮するため、uglify-jsをインストールします。以下のコマンドでインストールします。

$ npm install uglify-js --save-dev

npm scriptsの記述

package.jsonのscriptsに以下を記述を追加します。

"js/uglifyjs": "uglifyjs dist/js/index.js -o dist/js/index.min.js"

「dist/js/index.js」を圧縮処理して、「dist/js/index.min.js」として書き出すという感じです。

Babelを利用してトランスパイルをする

Babelの設定については以下をご覧ください。


【Babel】を使ってES6をIE11に対応させる方法

Babelでトランスパイルするタスクを以下のようにscriptsを変更します。

"js:babel": "./node_modules/.bin/babel ./src/js --out-dir ./dist/js"

Javascriptの処理をまとめる

Sassの処理をまとめる同様、Javascriptの処理をnpm-run-allを使用してまとめます。流れの確認です。

BabelでJavascriptコードをトランスパイルする。

Javascriptファイルを圧縮する。

以下をscriptsに追加します。

"js": "npm-run-all -s js:*"

これで npm run js コマンドで、JSのトランスパイルと圧縮処理ができるようになりました。

ファイルを監視する

ここからは毎回、処理の時にコマンドを打つ必要をなくすため、ファイルをwatch(監視)するようにして、変更がある度に自動的に処理するようにしていきます。

brwser-syncでサーバーを立ち上げる

browser-syncでサーバーを立ち上げます。
以下のコマンドでインストールします。

$ npm install browser-sync --save-dev

npm scriptsの記述

package.jsonのscriptsに以下を記述を追加します。

"watch:server": "browser-sync start --server dist --files 'dist, **/*.html, !node_modules/**/*'"

使用しているオプションです。

–server, -sローカルサーバーを実行します。
–files, -f監視するファイルパス

その他、browser-syncのオプションについては以下のページをご参考ください。


Browsersync Command Line Usage

SASSとJavascriptファイルを監視する

watchパッケージをインストールします。

$ npm install watch --save-dev

npm scriptsの記述

src/sass」フォルダ内のファイルを監視対象にします。

"watch:css": "watch 'npm run css' ./src/sass"

JSの監視も同様に「src/js」フォルダ内のファイルを監視対象にします。

"watch:js": "watch 'npm run js' ./src/js"

監視用タスクをまとめる

最後に監視用タスクをまとめてしまいます。
以下をscriptsに追加します。

"watch": "npm-run-all -p watch/*"

これで、開発を開始する際に、npm run watch のコマンドで「watch:server」「watch:css」「watch:js」の監視タスクがひとまとめで実行することができます。

補足

npm scriptsの予約語

npm scriptsには予約語があります。予約語は「run」をつけずに実行することができます。

$ npm start
$ npm restart
$ npm stop
$ npm test

例えば、「npm run watch」を→「npm start」にすることでコマンド入力がさらに楽になります。

コードまとめ

ここまでのscriptsをまとめたpackage.jsonが以下になります。

{
  "name": "babel_test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "css:sass": "node-sass src/sass/style.scss -o dist/css --output-style expanded --source-map dist/css",
    "css:postcss": "postcss dist/css/style.css -o dist/css/style.min.css",
    "css": "npm-run-all -s css:*",
    "js:babel": "./node_modules/.bin/babel ./src/js --out-dir ./dist/js",
    "js:uglifyjs": "uglifyjs dist/js/index.js -o dist/js/index.min.js",
    "js": "npm-run-all -s js:*",
    "watch:server": "browser-sync start --server dist --files 'dist, **/*.html, !node_modules/**/*'",
    "watch:css": "watch 'npm run css' ./src/sass",
    "watch:js": "watch 'npm run js' ./src/js",
    "watch": "npm-run-all -p watch:*"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "^7.9.0",
    "@babel/preset-env": "^7.9.5",
    "browser-sync": "^2.26.7",
    "node-sass": "^4.13.1",
    "npm-run-all": "^4.1.5",
    "uglify-js": "^3.9.1",
    "watch": "^1.0.2",
    "autoprefixer": "^9.7.6",
    "cssnano": "^4.1.10",
    "postcss-cli": "^7.1.0"
  },
  "browserslist": [
    ">0.25% in JP",
    "not ie <= 10",
    "not op_mini all"
  ]
}

最後に

今回は、脱gulpに向けて、npm scriptsを使用して以下の処理をする環境構築を行いました。


sassの自動コンパイル&圧縮処理
babelを使用してjavascriptの自動トランスパイル&圧縮処理
browser-syncでブラウザリロード

前までは、npm scriptsの記述が難しいなと敬遠していたのですが、一つづつ紐解いていくとgulpの変わりに使えそうだなと感じました。

脱gulpを予定されている方は、是非npm scriptsへの移行をご検討ください。

関連リンク

【Babel】を使ってES6をIE11に対応させる方法
browserl.ist
Browsersync Command Line Usage