Yarn の Plug'n'Play でエディタが型を解決できず Cannot find module になる
Plug'n'Play では node_modules が作られないため、エディタの TypeScript や ESLint が Yarn のローダを通らず解決に失敗する。yarn dlx @yarnpkg/sdks で SDK を生成し、エディタにワークスペース版の TypeScript を使わせると解決する。
公開:
要約
yarn install は成功しているのにエディタだけが Cannot find module 'react' と言う場合、原因は依存の欠落ではなく Plug'n'Play(PnP)にエディタが対応していないことだ。
PnP は node_modules を作らず、Node.js のローダを差し込んで解決する。
エディタ拡張はそのローダを通さずに TypeScript や Prettier を直接起動するため、解決できない。
Yarn 公式が用意している SDK を生成すれば解消する。
yarn dlx @yarnpkg/sdks vscode生成された .yarn/sdks はリポジトリにコミットする。
よくある原因
- node_modules を前提にした探索: 多くのエディタ拡張は
node_modules直下からツール本体を探す。
PnP では実体がそこに無い。 - ローダを通らない起動: 拡張が包んでいる TypeScript や Prettier を素の Node.js で起動しており、PnP のローダが注入されない。公式ドキュメント(新しいタブで開く)は、この問題を回避するために SDK が「中継用パッケージ」を生成すると説明している。
- SDK 未生成・未コミット: 自分の環境では動いていても、SDK をコミットしていなければ他の開発者や CI で同じ症状が再発する。
- ワークスペース版 TypeScript が選ばれていない: SDK を入れても、VS Code が同梱版の TypeScript を使っていると効果が出ない。
解決策
1. エディタ SDK を生成する
使っているエディタを指定して実行する。
複数指定もできる。
yarn dlx @yarnpkg/sdks vscode
yarn dlx @yarnpkg/sdks vim
yarn dlx @yarnpkg/sdks base # 特定エディタ向け設定なしで SDK だけ入れるVS Code を指定すると .vscode/settings.json の typescript.tsdk も併せて設定される。
生成物はコミットして、チーム全員が同じ状態になるようにする。
2. ワークスペース版 TypeScript に切り替える
VS Code ではコマンドパレット(Ctrl+Shift+P / Cmd+Shift+P)で TypeScript: Select TypeScript Version を開き、Use Workspace Version を選ぶ。
ここを切り替えないと、SDK を入れても同梱版が使われ続ける。
3. コマンドラインでも yarn 経由で実行する
ターミナルから直接叩く場合も、ローダを通す必要がある。
yarn node script.js # node script.js ではなく
yarn tsc --noEmit # package.json の scripts 経由でも同じyarn を前置きすると PnP のローダが有効な状態で子プロセスが起動する。
4. どうしても合わないなら node_modules に戻す
対応していないツールが多く、当面 PnP を諦める判断もありうる。.yarnrc.yml にリンカを指定する。
nodeLinker: node-modulesこの設定では従来どおり node_modules が作られる。
PnP の起動速度や厳密さは失われるので、ツール側の対応状況を見て戻す前提で使う。