Node.js
npm
npm-scripts

OSに依存しない形でnpm scriptsにglobを書く

2018/8/23追記

WindowsではGit bashを使うのがデフォになっていたので、powershellの存在をすっかり忘れていたことが今になって発覚。
powershell/bash v3/bash v4で動くように記事を訂正しました。

背景

Windowsで開発してたプロジェクトをMacのマシンで動かしたらnpm scriptsが思ったように動かなくて困った。
rm -rfなんかは気をつけていたけど、glob (src/**/*.jsみたいなやつ) がMacでちゃんと認識されなくて困った。

結論

2018/8/23 訂正
npm scriptsに出てくるglobはすべて「\"」(バックスラッシュ + ダブルクォーテーション)で囲む。

参考文献

ここを参考にしました。

https://medium.com/@jakubsynowiec/you-should-always-quote-your-globs-in-npm-scripts-621887a2a784

解決までの道のり

ぶち当たった問題

今回解決したかったのは、以下のようなglobの含まれるnpm scriptsでした。

  "scripts": {
    "test": "mocha src/**/*.spec.ts"
  },

このプロジェクトでは、当初Windowsマシンを使って開発を進めていました。
そのときのテスト結果がこちら。

  190 passing (277ms)
  2 pending

開発の途中でMacのマシンを購入することができたため、Macのマシンで開発を続けようと思い、環境セットアップしてテストを回すと…。

  72 passing (88ms)

少ない??

原因

普段意識せずに使っている、"**"と書けばネストしたディレクトリを含む、というようなglobはglobstarというシェル拡張を使っているそうです。

記事執筆時点のMacだとデフォルトでbashのバージョンが3系なので、そもそもglobstarが使えません。(globstarが追加されたのはバージョン4から)

その状態で"**"を含むglobを書くと、2段以上ネストされたディレクトリに対応できなくなったわけです。

ではBashのバージョンを4系に上げ、globstarを有効にすればそれだけで使えるようになるかというと、そういうわけでもありませんでした。

どうも、npm scriptsに書いたスクリプトはsh -cに続く形で渡されるようです。
このとき、元のシェルセッションでglobstarを有効にしていたとしても、新しく作られたシェルのセッションではglobstarが無効になってしまっていました。

この時点で上記の参考ブログに出会うわけですが、mochaなどのnpm moduleでは引数にglobが含まれる場合、node-globというモジュールで解決するそうです。

このnode-globというモジュールはglobstarにも対応しているため、npm scriptsに書くglobをglobとしてシェルに認識させないようにすると良いということが分かりました。

つまり、こうです。

  "scripts": {
    "test": "mocha 'src/**/*.spec.ts'"
  },

globをシングルクォーテーションで囲むことで、bashにとってはただの文字列として扱われるため、上記の場合だとmochaが使うnode-globで解決されるようになります。

2018/8/23 訂

上記スクリプトだと、Windowsのpowershell環境で正常に動かないことがわかりました。
その理由は、bashとpowershellではシングルクォーテーションの扱いが違うからだと思われます。(あんまり詳しくは分かってない)

なので、以下のように修正するとうまく動くようになりました。

  "scripts": {
    "test": "mocha \"src/**/*.spec.ts\""
  },

ここまで書いて考えたのですが、環境変数からglobを組み立てたり、ちょっと複雑なことしたくなったときは、powershellとbashを両立させるのはそもそも無理なのでは…?
(環境変数の参照の仕方が違う、bashだと$varでアクセスできるけどpowershellだと$env:varとしなければいけない…。)

まとめ

まさかOSが変わるとこんなところに影響があるとは思ってもいませんでした。
普段Windowsしか触らないといろいろ怖い。システムのデフォルトでIgnore Caseだったり、ついbashのスクリプト書いたら動かなかったり。UNIX系OS流行れ。

2018/8/23 訂正後に追記

そういえばpowershellというものがあったなぁ。
なんか使いにくくて敬遠してるけど。