できない.dev

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 はリポジトリにコミットする。

よくある原因

  1. node_modules を前提にした探索: 多くのエディタ拡張は node_modules 直下からツール本体を探す。
    PnP では実体がそこに無い。
  2. ローダを通らない起動: 拡張が包んでいる TypeScript や Prettier を素の Node.js で起動しており、PnP のローダが注入されない。公式ドキュメント(新しいタブで開く)は、この問題を回避するために SDK が「中継用パッケージ」を生成すると説明している。
  3. SDK 未生成・未コミット: 自分の環境では動いていても、SDK をコミットしていなければ他の開発者や CI で同じ症状が再発する。
  4. ワークスペース版 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.jsontypescript.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 の起動速度や厳密さは失われるので、ツール側の対応状況を見て戻す前提で使う。

この記事は役立ちましたか?