Node.jsの環境をSSDに引越しして動作を確認していたところ、yo
がインストールできない・動かないという謎の現象に見舞われた。実は自分の環境が悪いのではなく、タイムリーにyo
が依存するたった1行の関数を提供するis-promise
が壊れた直後にインストールしたことが原因と分かった。
オープンソースの怖さを思い知るとともに、何か起きたらエラーの発生元を確認しにいかないといけないなと思った事件だった。(あとはバージョン違いを考慮したテストの自動化も大事)
起きた現象
yo
をインストールすると、ちゃんと動くかをチェックするYeoman Doctorが実行される。ここで、yo --version
でエラーが起きてしまっている。この後yo
を実行しても、同じエラーで起動すらしない状況となった。
> yo@3.1.1 postinstall K:\nodejs\npm_global\node_modules\yo
> yodoctor
Yeoman Doctor
Running sanity checks on your system
√ No .bowerrc file in home directory
√ Global configuration file is valid
√ NODE_PATH matches the npm root
√ No .yo-rc.json file in home directory
√ Node.js version
Error: Command failed: C:\WINDOWS\system32\cmd.exe /s /c "yo "--version""
internal/modules/cjs/loader.js:584
if (e.code !== 'ERR_PACKAGE_PATH_NOT_EXPORTED') throw e;
^
Error [ERR_INVALID_PACKAGE_TARGET]: Invalid "exports" main target "index.js" defined in the package config /K:/nodejs/npm_global/node_modules/yo/node_modules/is-promise\package.json
at resolveExportsTarget (internal/modules/cjs/loader.js:542:13)
at resolveExportsTarget (internal/modules/cjs/loader.js:581:20)
at applyExports (internal/modules/cjs/loader.js:455:14)
at resolveExports (internal/modules/cjs/loader.js:508:23)
at Function.Module._findPath (internal/modules/cjs/loader.js:632:31)
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:1001:27)
at Function.Module._load (internal/modules/cjs/loader.js:884:27)
at Module.require (internal/modules/cjs/loader.js:1074:19)
at require (internal/modules/cjs/helpers.js:72:18)
at Object.<anonymous> (K:\nodejs\npm_global\node_modules\yo\node_modules\run-async\index.js:3:17) {
code: 'ERR_INVALID_PACKAGE_TARGET'
}
エラーの原因
エラーメッセージにある通り、run-async
が利用するis-promise
で、ERR_INVALID_PACKAGE_TARGET
が起きてしまっているのが原因。npmのis-promiseのページを見てみると、以下のようにビルドエラーが起きたと表示されている。30分ほど前にPublishされたバージョンで何が起きたのか…
is-promise
のGitHubにはIssueが既に投稿されていて、同じエラーが起きていることが分かった。(ここで初めて、自分の環境が問題ではないかも…と分かった)
原因はPackage.json incorrectly formatted #12に投稿されていた(ejs/cjsといった、Javascriptのモジュールの形式の指定が間違っていたとのこと…あまり理解できていないが、ejsをサポートするNode.jsのバージョンでNGになるそう)。今回のバージョンで追加された機能が悪さをしてしまった模様。
その後、[BUGFIX] Use correct paths for CJS and ESM compatibility #15で修正があり、プルリクエストが発行されていた。
とりあえず、少し待てば反映されるかもしれないので待ってみる。Weekly download 1000万超の定番モジュールがほんの少しのミスで色々なモジュールに影響を与えてしまうとは…
暫定対策
とりあえず問題が起きているのはyo
のグローバルインストールが使っているrun-async
なので、yo
のnode_modules以下のrun-async
のpackage.json
を変更して、is-promise
のバージョンを2.1.0に固定する。package.json
を変更したらrun-async
のフォルダでnpm install
を実行し、is-promise
の2.1.0をインストールする。
"dependencies":{"is-promise":"2.1.0"←元々は"^2.1.0"だった},
この処置の後、yo
を実行したら動くようになった。
>yo
? 'Allo! What would you like to do? (Use arrow keys)
Run a generator
> Code
──────────────
Update your generators
Install a generator
Find some help
Get me out of here!
(Move up and down to reveal more choices)