Windowsのzenn-cliの話
序
先日、Windowsでzenn-cliが動かなくてissueをあげた話です。issue自体は以下。
見れば分かるとおり既にZennの開発者様のご尽力により既にcloseされていますが、今回はどんな問題だったのかを多少解説してみます。
1. 現象
issueをあげたときはzenn-cliの手順通りに進めた場合、以下のようになっていました(現在はなりません)。
npm init --yesnpm install zenn-clinpx zenn init
→ここでエラー
node:internal/url:1489
throw new ERR_INVALID_FILE_URL_PATH('must be absolute', url);
^
TypeError [ERR_INVALID_FILE_URL_PATH]: File URL path must be absolute
at getPathFromURLWin32 (node:internal/url:1489:11)
at fileURLToPath (node:internal/url:1613:35)
at C:\zenn-cli-example\node_modules\zenn-cli\dist\server\zenn.js:272:1660
at C:\zenn-cli-example\node_modules\zenn-cli\dist\server\zenn.js:293:2027
at Object.<anonymous> (C:\zenn-cli-example\node_modules\zenn-cli\dist\server\zenn.js:293:2031)
at Module._compile (node:internal/modules/cjs/loader:1706:14)
at Object..js (node:internal/modules/cjs/loader:1839:10)
at Module.load (node:internal/modules/cjs/loader:1441:32)
at Function._load (node:internal/modules/cjs/loader:1263:12)
at TracingChannel.traceSync (node:diagnostics_channel:328:14) {
code: 'ERR_INVALID_FILE_URL_PATH',
input: file:///home/runner/work/zenn-editor/zenn-editor/node_modules/.pnpm/open@10.2.0/node_modules/open/index.js
}
Node.js v22.21.1
2. 原因
2-1. 既存の推定原因
この時点で既に記事にしていた方がいました。
この人はopenに行きついていましたね。まあ出力されているのでってだけですが。
この人はnode.js22系でのURL→パス変換のバグと断定していますが、node.js22系でそういう変更が行われたという事実は私の方では確認できていません。
そしてどちらもWSL、つまりWindows Nativeを諦めLinuxを使うという消極的な対応をしています。
つまり、既存の調査では原因がWindowsにあり、ロードのタイミングで問題があることは分かっていたものの、それ以上は不明だったということです。
2-2. issueをあげた理由
誰もあげておらず、このままではWindows Nativeに対するzenn-cliの対応状況が不明確になるため。
2-3. Windowsでどこまで動作していたのか?
現象発生時は、0.2.3までは動作していました。このバージョンはnode.js20系での最高バージョンになります。なので、node.js22系を疑うのも無理はありません。
2-4. どうして落ちているのか?
コールスタックを見る限り、不思議なURL(file:///home/runner/work/zenn-editor/zenn-editor/node_modules/.pnpm/open@10.2.0/node_modules/open/index.js)が埋め込まれ、それをパスに変換する(fileURLToPath())際に例外が発生しています。
こんなURLが出てくるからにはimportの際に落ちてるのかと思うのですが、調べるとzenn-cliはrspackでちゃんとbundleされています。何故にbundleしてるのにそんなURLが必要になっているのか、どう見てもビルド環境と思しきURLが埋め込まれるのも不自然です。その理由は(issueを上げた当時は気付いていませんでしたが、開発者様が対策後に調べた)bundle対象コードにこんな部分があったからでした。
import.meta.urlというやつです。
このESM固有のメタ情報をrspackが件のURLとして展開し直したため、ビルド環境のパスがURLとして埋め込まれた、というわけです。そしてWindows環境でドライブ名を含まないfileプロトコルのURIは不正とされ、例外が発生した、ということになります。
なお、ESM対応もこのURIを不正とする仕様もnode.js22系からではありません。
2-5. 本当にrspackのせいなのか?
実際に簡単な再現スクリプトを書いてesbuildとrspackで実験してみたところ、esbuildではimport.meta.urlがそのままで、rspackでは展開されてました。
展開さえされなければbundle先のURLになるので、色々変わってしまうもののビルド環境よりはマシなディレクトリが取れるでしょう。
3. 対策
これはzennの開発者様が取ってくださった対応です。
これにより、openモジュールの場合bundle対象外となり、
import()関数からopen関数が読み込まれす。
すると、import.meta.urlの展開も(ファイルごと)されなくなり、rspackでも現象を回避できます。
4. その他
そもそも今回の問題はロード時に発生するものだったので、Windows Native環境がテストされていないことは明らかでした。なので、そもそもWindows対応してくれない可能性も視野に入れてたのですが、幸運にも見捨てられることなく(何度か対策が変わりながら)rspack設定で特定モジュールの外部化など割と特殊な対応までしてもらった感じです。issueコメントによると実際開発側にWindows環境はないそうで、今後も同じような問題が起こる可能性があるでしょう。そうした状況を鑑みてか、折衷案的な再発防止策として(推測)、Github Actionを使った起動確認(E2Eテスト)を入れてくれたようです。
ただ、Windows以外の環境に向けたより細かい本来のテストコードは別にあります(私がWindowsで動かした限りでは2割程度失敗する)。これらをWindowsで動くようにまではしていないということで、その理由は私にも分かりません。問題を見つけても修正をするための環境がないのでは、それらのテストコードのメンテナンスコストまではかけられないという判断なのかもしれません。今回ビルドやらテストやらは、ある程度できるように修正を入れてくださっているようなので、Windowsのバグを発見して余力のある方はPRまで書けば喜ばれるかもしれません。
5. 最後に
Zenn開発者の皆様、お忙しい中issueにご対応いただき、ありがとうございました。
Discussion
Issueにあげて解決までありがとうございます!
私の記事も見てくださっていたようで。
私がZenn初心者でよくわかっていなかったところもありつつ、はやく記事を書きはじめたいという気持ちもありWSLへ逃げてしまいましたが、皆さんWindows使ってないんですかね。。
いえ、こちらこそコメントまでしてくれてありがとうございます。私は問題報告しただけですよ。
ほとんどの人はWSLもしくはVMに逃げてると思います(私はデュアルブートしたLinuxからも使えるのでVMにしてます)。私も今まではLinuxで使ってましたが、最近PCを変えたのもあって、今回 たまたまLinuxがなかった だけなのです。