Finite Clause

開発者はなぜnpmで小さなモジュールに依存しなければならないか

概要

最近、あるモジュール作者がnpmに公開している自身のモジュールをすべてnpmから削除した。 これによって、そのモジュールに依存しているライブラリやフレームワークなどがビルドできないという問題が起きていた。 それにはReactやBabelのようなものも含まれていたため、結構インパクトが大きかったように思う。

なぜこうなったのか経緯はnpmがブログに書いてる

この問題について、個人的にこれが問題だって思うことを書いておく。

なぜ小さなモジュールに依存するのか

この問題が起きたあとに、こんな記事があったりする。 ざっくり言うと、なんでそんな小さなモジュールすらてめーでかけないんだよっていうことだと思う。 まぁ、たしかになって思った、思ったが…

実装者の視点として結論からいうと、Node.jsのエコシステム上でライブラリやフレームワークを書くときのモジュール読み込みがイケてない。
いや、これがないとつらすぎてもうライブラリとか書きたくないのは確かなんだけどイケてない。

どこがイケてないか

上記の問題でユーティリティのようなモジュールを自分で書けっていうのはつまり、その小さなモジュールを、そのプロジェクトのどこかに入れないといけないってことだ。
そのプロジェクトのディレクトリ構造に関わるのはもちろんだが、
そこでモジュールを読み込む方法がイケてない。

例えば…

root
  |- src
      |- util
      |- core

のような構造があったとする。 ここで、util/left-pad.jscore/core.jsで使いたいとする。 そこでcore.jsでモジュールの読み込みは以下のようになる。

const leftPad = require('../util/left-pad.js');

これが例えばもっと深いcore配下のディレクトリで使うことになったとしよう。 するとそれはひたすら相対パスを続けて書いていかなければならない、以下のように。

const leftPad = require('../../../util/left-pad.js');

この頃にはもうどこまで階層をさかのぼればそのモジュールを読み込めるのかわからない。
確かにエディタの補完をつかえばある程度補助はできる。
でもそれ、エディタでやることなんだろうか?

他にも、この問題を解決するためのモジュールが用意されていたり、例えばprocess.cwd()を取ってきたりすればある程度解消するかもしれない。
でもそれって実際やってると疲れる。
別に誰も幸せになってない。

でもこれが、npmに公開されているモジュールであればどうだろうか。

const leftPad = require('left-pad');

これだけだ。
どこから参照しようともこれだけですむ。
じゃあこの小さな関数を組織でnpmに公開するか?
きっとしないだろう。
誰もが「これくらい自分で書けや」って思うからだ。

まとめ

CommonJSの仕様で決まっているから仕方ないのかもしれないが、このめんどくささからどうにか解放されたい。
いまNode.js, npmで問題なのはローカルのファイル読み込みの標準がないということだと思う。
ないというか、あるけど上記のようにイケてないのだ。

一番惜しいのがLocal Pathsってやつで、これがローカルの相対パス問題は解決してくれそうだが…
使ってる人をあまり見かけない気がする…
使う機会があれば使ってみたいと思うが、なんかちょっとつらそう

CommonJSやECMAScriptのimportなどモジュール読み込みをする方法は様々だが、
仕様よりもユーザーの使い勝手の良さを求めてほしい感じはある。
モジュールの読み込みの標準がもうちょっといい感じのものがあったら、
今回の問題も、これほどの影響は受けなかったかもしれない。