💍

npm-run-allを使って理想のコーディング環境を整える

2021/11/28に公開

現状について

これまで、コーディングを行う環境として、

  • Sass -> LiveSassCompile(VScodeの拡張機能)
  • Autoplefixer -> Autoprefixer(VScodeの拡張機能)
  • JavaScript -> Webpack + babel
    を使用していたのですが、辛さを感じてきました。

辛いと感じたポイント

  1. Sassのコンパイルが遅い
  2. Autoprefixerを自動で使用できない
  3. Sassのコンパイル結果が表示される画面とJSのコンパイル結果が表示される画面が分かれている
  4. ↑に加え起動するためのコマンドだったりが分かれてる
  5. 将来的に別のエディタに乗り換えた際に拡張機能を探さないといけなくなってしまう

要件の設定

上記のポイントを解決するために、前提としてコマンド1つでjsのバンドル・Sassのコンパイル・PostCSSの適用すべてを行うことができるようにしないといけないと感じました。
そこで、今回はタイトルにもある通りnpm-run-allを使用することを決めました。

npm-run-allの詳しい使い方はこちら

なぜ既存のタスクランナーは使用しないのか

先日Twitterでこのようなつぶやきを拝見しました。
https://twitter.com/ixkaito/status/1460913947893444613

たしかに僕も以前はGulpを使用していたのですが、Gulp用の設定ファイルを用意したりと不便さを感じて結局使わなくなったので、今回はタスクランナー以外で使用することにしました。

必要なパッケージのインストール

コマンドでいろいろやる設定をする前に、必要なパッケージをインストールしていきます。

Sass

node-sassが非推奨になったので、Dart-sassをインストールします。
node-sassからの変更点についてはすでにいくつもまとめられた記事があるので各々ググってください。

yarn add -D sass

PostCSS

自動でベンダープレフィックスつけたりいろいろできるすごいやつ
今回はプラグインとしてベンダープレフィックスを付けるAutoprefixerとcssを圧縮するcssnanoを使用します。

yarn add -D postcss postcss-cli autoprefixer cssnano

PostCSSの設定も今のうちにやっておきます。
package.jsonと同じディレクトリにpostcss.config.jsを用意します。

module.exports = {
  plugins:[
    require('autoprefixer')({
      //Autoprefixerの設定
      //この辺はお好みで
      cascade: false,
      grid: 'autoplace'
    }),
    require('cssnano')({
      preset: 'default'
    })
  ]
}

次に、Autoprefixerをどのブラウザに対応させるかの設定をしていきます。
package.jsonの中にblowserslistの項目を設定し、中身を記述していきます。
(別途.blowserslistrcを用意する方法もありますが、設定ファイルが増えすぎるのは好きではないのでこのやり方で)

{
  ///前略
  "blowserslist":[
    "> 0.25% in JP",
    "ie >= 11",
    "not op_mini all"
  ]
}

対象ブラウザの設定方法はいろいろあるので分からない方は調べてみてください。

Webpack + babel

yarn add -D webpack webpack-cli babel-loader @babel/core @babel/preset-env @babel/cli @babel/runtime @babel/plugin-transform-runtime core-js 

webpackの説明は長くなるので割愛させていただきます。

というのも味気ないので、参考記事を置いておきます。

npm-run-all

npm-run-allは備え付けの機能ではないので、こちらもパッケージをインストールします。

yarn add -D npm-run-all

これで設定に必要なパッケージは一通りインストールできました。
ゼロベースでパッケージをインストールするとどうしても時間がかかってしまいますが、2回目以降はpackage.jsonの中身をコピペして

npm i --only=dev

とかでまとめてパッケージをインストールできるので活用していきましょう。

本題のコマンド設定

インストールしたパッケージを利用してpackage.jsonにnpmスクリプトを設定していきます。
まずはCSSから

{
  ...
  "scripts": {
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map -w",
    "watch:postcss": "postcss path/to/output.css -o path/to/output.min.css -w"
  },
  ...
}

※path/to/のところは自分の環境に合わせて適宜変更
簡単に解説すると、watch:sassでsassファイルの変更を監視しコンパイル
watch:postcssでsassが出力したファイルの変更を監視しコンパイル
という処理を行っています。

次にJavaScript

{
  ...
  "scripts": {
      ...
      "watch:js": "webpack -w",
      "build": "wabpack --mode=production"
    },
  ...
}

webpackについは上の2つ
ファイルの変更を監視するスクリプトと本番用の出力を行うスクリプトの2種類です。

現時点で下のようになっています。

{
  ...
  "scripts": {
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map -w",
    "watch:postcss": "postcss path/to/output.css -o path/to/output.min.css -w",
    "watch:js": "webpack -w",
    "build": "wabpack --mode=production"
  },
  ...
}

最後にこれらのスクリプトをまとめていきます。

{
  ...
  "scripts": {
    "watch": "npm-run-all -p watch:*"
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map -w",
    "watch:postcss": "postcss path/to/output.css path/to/output.min.css -w",
    "watch:js": "webpack -w",
    "build": "wabpack --mode=production"
  },
  ...
}

これで完成!

と言いたいところですが、実はこのスクリプトには欠陥があります。
それは実行時にpostcssに監視させるcssファイルがなかった時にエラーを吐いてcss->min.css変換の監視が止まってしまうことです。
(それでも基本的に必要なsass変換とwebpackでのバンドルは普通に動きます。
2回目以降の実行では(ファイルを消してたりしなければ)全部問題なく動くので、気にしないよ!って方はここで終わってヨシ!)

エラーを解消する

今回のエラーの原因としは先に記述したとおり、postcssで監視するファイルがないため発生しています。
なので、監視させる前に先にsass->css変換を1度行うことで防ぐことができます。

{
  ...
  "scripts": {
	"watch": "npm-run-all -s sass path/to/bofore-compile.sass path/to/output.css --no-source-map -p watch:*"
	...
  },
  ...
}

と書くこともできますが、記述が長ったらしくなってしまうのと、(個人的に)ダサい文になってしまうのでこれ以外の方法を考えます。

sass->css変換を行うだけのスクリプトを用意して、あとからコマンドライン引数で-wを指定して監視させることができればいいのですが、そんな都合のいい方法…

ありました。
公式ドキュメント

Run with arguments
We can enclose a script name or a pattern in quotes to use arguments. The following 2 commands are similar.
$ npm-run-all --parallel "build:* -- --watch"
$ npm run build:aaa -- --watch & npm run build:bbb -- --watch

要約するとダブルクォーテーションで括った中なら通常のnpmスクリプトと同様の形で引数を渡す[1]ことができるみたいです。
つまりこう

{
  ...
  "scripts": {
    "watch": "npm-run-all "-p watch:* -- -w""
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map",
    "watch:postcss": "postcss path/to/output.css -o path/to/output.min.css",
    "watch:js": "webpack",
    "build": "wabpack --mode=production"
  },
  ...
}

ただ、これだとダブルクォーテーションの中にダブルクォーテーションが入っているのでエディタ上で警告が表示されます。
なので中のダブルクォーテーションをエスケープさせます。

{
  ...
  "scripts": {
    "watch": "npm-run-all -p \"watch:* -- -w\""
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map",
    "watch:postcss": "postcss path/to/output.css -o path/to/output.min.css",
    "watch:js": "webpack",
    "build": "wabpack --mode=production"
  },
  ...
}

監視の前にsass->css変換を行う処理を追加します。

{
  ...
  "scripts": {
    "watch": "npm-run-all -s watch:sass -p \"watch:* -- -w\""
    "watch:sass": "sass path/to/bofore-compile.sass path/to/output.css --no-source-map",
    "watch:postcss": "postcss path/to/output.css -o path/to/output.min.css",
    "watch:js": "webpack",
    "build": "wabpack --mode=production"
  },
  ...
}

これで完成です!
(監視させてないのにwatch:sassとなってますが目をつぶってください…)

最後に

npmスクリプトは事前に準備されてたものを使うことが多くて自分で制作するのは初めてだったので、結構苦労しました。
あと、書いた後に知ったんですが、postcss-scssなるプラグインも存在しているみたいです。
公式ドキュメントが英語だけなので理解するまで時間がかかりそうですが、もしそちらのほうが構築のコストとか楽そうであれば記事にしようと思います。

脚注
  1. yarnでは引数の前に--は不要ですが、付けてても警告が出るだけでエラーにはなりませんのでnpmを使用している方も想定して付けたまま記述していきます。
    警告が鬱陶しいかたは削除してください。 ↩︎

Discussion