🏃

ユーティリティ実行エンジンとしてのJSランタイム

2023/09/18に公開

まえがき

当記事では、パッケージマネージャ、あるいはユーティリティ実行エンジンとしての観点からJSランタイムについて比較、考察していきます。
具体的な用途としては、linter、formatter、git hook manager、その他、開発そのものには関与しない、ツール群及びそれらの動作環境を提供するためとします。
なお、今回の記事ではJavaScriptの開発には言及しません。そのため、たとえば今回比較対象として挙げるうちの一つのdenoには、組み込みでlinter、formatterがありますが、これは利用できないものとします。
あくまでツール実行エンジンとしてのみが今回の関心であり、温度感としてはUbuntuにおけるところのapt系列として考察します。
たとえば、markdownlintを使いたいときなどに当記事の比較を見るとよいでしょう。

結論

とりあえずNodeでyarnのv1を使おう。もうちょっと速くしたいならyarn v2のpnp入れよう。

前提

比較される際のパラメータとして、第一に優先されるのは安定性、信頼性です。実際に使用感が変わらなければ、ツールなんてなんでもいい、というのがエンドユーザの一般的な認識かと思います。
当記事のスタンスでも似たような温度感で比較します。多少の速度の差より、ドキュメントの充実度、利用のしやすさを重視し、さらにそれらも近しいのなら、メンテナンス間隔の頻繁さやハマりにくさ、導入の楽さを見ます。
ただし快適さが向上するレベルでの速度差があるのなら一考します。また安定性は古さ、枯れ具合とは直結せず、むしろ新たな世代のもののほうがよりエッジケースが少なくなる場合もあります。

比較

では実際に、各々のランタイムについて記述していきます。
なお、ツール実行環境としてはパッケージマネージャも重要な要素の一つですので、パッケージマネージャが複数あるものについては、その組み合わせ分だけ比較対象とします。
また重要視する点として、マルチプラットフォームであることも見ます。Macなどのシェルが変更しやすいOSならある程度合わせることもできるでしょうが、Windowsではなかなか厳しいものがあるため、Windowsに対応しているものの評価は高くなります。
Windowsに関して、WSLで対応すればよいという意見もあることでしょう。これに対しては、なるべくネイティブに近い状態のほうが望ましい場合が多い、という考えを返答とします。

Node

言わずと知れたデファクトスタンダードです。
基本的にはこれを使えば安泰ですし、現状他のランタイムがチャレンジングな状態ですので、これ以外については選びようがないというのが素直なところです。
ツール利用としてのランタイムという観点から競合先を見るのなら、Pythonが真っ先に挙げられるでしょう。
おなじくインタープリタであり、動的型付け言語であり、シェルスクリプトとしても活用が可能という点で類似しています。
ただし、Pythonではライブラリの管理についてあまりエコシステムが成熟していない印象です。
その点で、パッケージマネージャと実行環境という形の評価を与えるのなら、Nodeを利用することは有用な選択肢の一つです。

npm

Nodeに付属するデフォルトのパッケージマネージャです。
単刀直入に言ってクセが強く、扱いづらいというのが筆者の正直な感想です。
古いCLIツールにありがちな特徴である、省略記法、ショートカットが複数あり、使い手の表記によって同じ動作でもかなりコマンドが変わりがちです。またこれも古いツールあるあるですが、テキストによるリフレクションが多く用いられている印象で、なんとなく名前を付けたタスクの名前が偶然npmの予約語で勝手に動き出すこともしばしばでした。
パフォーマンス周りも総じて優れる部分が少なく、DXの向上を掲げた際にnpmを選ぶことはまずないでしょう。
デフォルトで含まれているというメリットも、Nodeと合わせて導入されるcorepackにyarnが含まれるようになってからは随分と薄れているようにも見えます。

yarn

Nodeのcorepackに付属するパッケージマネージャです。
追加のインストールなどは必要なく、数回コマンドを叩くだけで利用することができます。
v2は性能などが向上するのと引き換えにかなりクセが強くなりましたが、それでも悪くない選択肢です。
またv1はnpmの正統スーパーセットといった印象で、npmの使いにくかった部分などがかなりマイルドになって、更にはv2とも互換性があるので、とりあえずで選びやすい候補となります。
またv2はpnpという機能を利用することでインストール時の速度向上が見込めます。
ただしpnpはpnp独自の要素が強く、ややメンテナンスに手間がかかる印象です。その分リターンも多く、インストールの快適さ、node_modulesという巨大ディレクトリと今後関わらなくてよいという安心感は良いものです。
更にはZero-Installsと呼ばれる機能もありますが、ここでは割愛します。pnpを利用している時点で、利用しているライブラリがそこそこあっても10秒程度でインストールできるので、これ以上速くなってもそこまで恩恵はないでしょう。

pnpm

ディスク容量軽減、及び実行速度の向上を謳うライブラリマネージャです。
複数のワークスペースで独立してライブラリをインストールする、という流れを前提に、ライブラリをキャッシングして各ワークスペースにはハードリンクのみ置くという興味深い動作をします。
これはこれで便利でしょう。しかしながら、今回はツールランタイムとして見ています。
その場合、グローバルにツールをインストールすることも稀ではないでしょう。ハードリンクでやりくりするpnpmの旨味はほぼありません。
また個人の開発環境では顕著ですが、コードは書いたらgithubに上げればよいし、記憶媒体の容量の圧迫が気になるなら、触っていないプロジェクトを消せばよいのです。githubに上げさえすれば、もうあまり触らないのにメインPCにリポジトリを置く意味がありません。せいぜい置くとしてもバックアップ用の外付けHDDなどに保存しておけば十分です。
よって、複数の巨大なOSSのコミッターを継続的に兼任でもしない限りはオーバーエンジニアリング気味と言えます。

deno

Nodeの後継的な立ち位置のランタイムです。
基本的によく纏まっており、まだ実運用は厳しいですが時折チェックはしておきたいプロジェクトの一つです。
しかし当記事の主題であるツール利用のためのランタイムとしては、力不足であるところが否めません。
あくまで開発用のエンジン兼、プロジェクトの実行環境としての意味合いが強く、パッケージの扱いが上手いとは言えないのです。
パッケージマネージャもありませんし、CLIツールとして実行するのが難しい設計をしているのが現状です。筆者が確認したところ、単なるコードから呼び出すライブラリはホストさえされていればどんな場所にアップロードされていても問題ありませんが、逆説的にパッケージを検索できるような機能はありません。
またdenoからパッケージを利用しようとした場合、そのパッケージをimportし、コールするスクリプトを毎回書かなければなりません。
これはパッケージのランタイムとしてはかなり致命的で、インストール用のコマンドを一回叩けば使えるようになり、また管理も楽、といったマネジメントユーティリティとしての側面が完全に死んでいるのです。
ですので、PythonやShellなどが可能な拡張機能、追加機能の導入、管理という面でdenoがNodeを超えるのは今しばらく時間を要するでしょう。
またライブラリ群のバージョンを眺めてみると、少し前のRustのエコシステムを彷彿とさせるような番号の若さが目立ちます。利用するには少しの不安が付きまとうことでしょう。

bun(おまけ)

筆者はつい最近耳にし出したJSランタイムです。
実は調査があまりできておりませんので、深く述べることはできません。
なぜなら安定版でwindowsに対応していないからです。
そのレベル感での発展途上ですので、正直ツールランタイムとしての利用はまだまだ厳しいのでしょう。

まとめ

各々について、一定の観点から論じました。これらをテーブルに纏めますと以下のようになります。
なお、表中における表現は以下の意味を持ちます。

  • good
    • 良い
  • fair
    • そこそこ
  • poor
    • あんまり
runtime Node - - - deno bun
manager npm yarn yarn v2 pnpm - -
useful fair good good fair poor poor
spec fair good good good good good
easy fair good fair fair poor poor

これらを元にすると、yarnのv1をまず選ぶとよいでしょう。そこから更にもう一歩踏み込みたい型はyarn v2にグレードアップすれば、マイグレーションは簡単に進められるはずです。

あとがき

筆者が記事を書く環境を再整備しようと思ったとき、JSのものしかないパッケージのいくつかに依存していることに気付きました。
ではこのパッケージをdeno、あるいはbunで動かしたらもっと速くなって快適だろうか、と思いついたのが、当記事を記述するきっかけでした。結果的にdenoもbunもWindowsのパッケージ動作環境として不適切だった訳ですが。
ただ本音を言うなら、こういうツール群はインタープリタを介して利用するのではなく、適当な実行ファイルに固め、各OSのストアから落としてくるような形になればいいのに、とは思います。
その点としても、RustとCargoには期待しているところです。できることなら、当記事が必要ないようなZero-Configの風潮が強まることを願うばかりです。

参考

GitHubで編集を提案

Discussion