DenoのモジュールのURLを考える
DenoはESMモジュールをURLから読み込むことが出来る これはとても画期的なことで、この方向性は必ずやプログラミングを進化させると思っている
んでんで
DenoのモジュールをWebで公開する際、そのURLはどうなるべきか?どうすれば使いやすいか?と一年くらい考えた
code:js
import * as React from "react"
import * as ReactDOMServer from "react-dom/server"
CommonJSの場合、こういう読み込み方が普通になる
"react"はreactのpackage.jsonに書かれた"main"のファイルが読み込まれる
"react-dom/server"はreact-domのpackage.jsonがあるディレクトリをルートにして"server"というファイルが解決される
server.js or server/index.js
前者が一般的であり後者はあまり見ない。単に前者のほうが使いやすいからだ
aws-sdkなど全体が大きなモジュールではバンドラーの出力サイズを抑える目的で後者のようなマイクロモジュールを推奨するものもある
がやはり参照は一個にまとまっていたほうが楽である
さてDenoではどうなっているのか
Denoのモジュールシステムはモジュール解決に曖昧さを残さないため、以下から始まるモジュールしか読み込めない
/, ./, ../, file://, http://, https://
つまりファイルパスか、URL
code:ts
Denoではこういうふうに書くのが普通
ここまではいいのだけど、実際servestにはserver.ts以外にもたくさんのファイルがある そうなると現実的にはこういう記述が必要になってくる
code:ts
....
これはIDEのサポートがない現状では実際かなり大変な作業である。どのファイルに何があるかを把握していないとこのimport文は書けないからである
CommonJSの場合はとりあえずrequireしておけばあとはなんとかなるという緩さがあった
Denoの場合URLすなわちファイル名がモジュールの識別子になっているので、ファイル名を変えてしまうとURLが失効してモジュールが使えなくなってしまう
これは結構な問題で、自分で管理しているファイルならともかく誰かが管理しているファイルの名前が変わることにビクビクするのは馬鹿らしい話である
とはいえWebってそういうものでしょURLって全然パーマネントじゃないでしょというのはそうっちゃあそう
DenoはJavaScriptランタイムだが、その設計思想はWebセントリックな時代のためのプログラミングパラダイムである
Denoの設計のPros/Consは、Webとブラウザのそれとおなじになるだろう
のだがそういうのはおいておいてReal Worldのソフトウェア開発は尋常じゃない数のimprot文を日々書かないといけないのでこういう小さなことでもストレスは溜まってしまう
んでんで
今年の最初の方にdenoのstdモジュールのイシューで、こんな話があった
要約すると、
stdには結構色々なモジュールがある
そのURLとなるファイル名をどう決めるか
モジュールの分類をディレクトリ("fs", "http")などにして、そのモジュールメインとなるファイルをmod.tsにしよう
ということに最初なった
のだが、このmod.tsの役割がイマイチ定まらなかった
fsのようにディレクトリの下に沢山ファイルが有るモジュールでは、mod.tsはこのようになっていた
code:fs/mod.ts
export * from "./copy.ts"
export * from "./exists.ts"
....
一方wsのような比較的小さなモジュールでは、mod.tsは実装ほとんどを含むファイルだったりする
んで、mod.tsがある場合mod.ts以外のファイルはどう扱うべきかという話になってくる
mod.tsはあくまでexport aggregationを記述するだけのファイルにすべきか否か
その場合その他のファイルはどうするのか?
僕は最初fsじゃなくてfs.tsというファイルをmod.tsのように使えばいいと思ったんだけど、その意見は通りませんでしたとさ
理由はトップディレクトリにファイルを持ちたくないから by Ryan
code:ts
fs.ts
fs/
copy.ts
exists.ts
このレイアウトはDenoのモジュールシステムともかち合わないしこうできたらurlにも一貫性が出来るのだけどなぁ
stdがコアに入った今別にこれでもいいと思うのだけど
https://deno.land/std/fs.ts
こうしたい
いっそ全部のモジュールをいれたhttps://deno.land/std.tsを作ってもいいかもしれない
でもこれはコンパイルの段階でstdのコード隅から隅まで落とす必要があるので微妙かもしれない
いやでもCommonJSはそうなのか…
うーん難しい