yarn pnp 環境化で VSCode 拡張機能の prettier を動かす
yarn pnp で作成したプロジェクトで VSCode 拡張機能の prettier が動かなかったので対応方法を紹介します。
やりたいこと
yarn pnp で作成したプロジェクトでプロジェクトの prettier とフォーマットルールを使って VSCode 拡張機能の prettier (prettier-vscode) を動かしたかったのですが、ハマったので事象と対応方法をメモしておきます。
環境
- OS
- Microsoft Windows 22H2
- Node.js
- v22.12.0
- yarn
- v4.5.3
- prettier
- v3.4.2
- prettier-vscode
- v11.0.0
事象
以下の手順でセットアップしたのですが prettier-vscode が動きませんでした。
yarn プロジェクト作成と prettier インストール
-
yarn プロジェクト作成
yarn init -
prettier インストール
yarn add --dev --exact prettier -
フォーマットルール作成
.prettierrc { "singleQuote": true } -
この時点で
yarn prettier . --writeはワークしている
VSCode 拡張機能 prettier-vscode のインストールとセットアップ
-
VSCode 拡張機能 Prettier - Code formatter - Visual Studio Marketplace をインストールする
-
前節で作成した yarn プロジェクトルートに
.vscodeフォルダを作成し、settings.jsonファイルを作成し以下内容で保存する{ // フォーマッターを prettier-vscode にする // https://github.com/prettier/prettier-vscode?tab=readme-ov-file#default-formatter "editor.defaultFormatter": "esbenp.prettier-vscode", // 保存時に自動フォーマットをオンにする // https://github.com/prettier/prettier-vscode?tab=readme-ov-file#format-on-save "editor.formatOnSave": true, }時々プロジェクトの
.prettierrcを prettier-vscode に認識させるために"prettier.configPath": ".prettierrc"のような設定が必要と記載されているサイトがあったりしますが、prettier-vscode はデフォルトでプロジェクトにある prettier が許容しているルールファイル (Configuration File · Prettier)を参照してくれるので不要です。 -
npm プロジェクトではこれで動くはずですが、
.jsファイルを作成して適当なスクリプトを書いて保存してみても全くフォーマットされません
原因
VSCode で prettier-vscode のログを見てみると以下のエラーが出ていました。
["ERROR"] Failed to load module. If you have prettier or plugins referenced in package.json, ensure you have run `npm install`prettier-vscode の仕様はプロジェクトの package.json に prettier があれば、プロジェクトの node_modules 内の prettier を使用し、VSCode の設定で prettier.resolveGlobalModules が true になっていればユーザーグローバルにインストール (npm install -g) された prettier を使用し、何れにも当てはまらなければ prettier-vscode にバンドルされている prettier が使用されるようです。
This extension will use prettier from your project’s local dependencies (recommended). When the
prettier.resolveGlobalModulesis set totruethe extension can also attempt to resolve global modules. Should prettier not be installed locally with your project’s dependencies or globally on the machine, the version of prettier that is bundled with the extension will be used.
- GitHub - prettier/prettier-vscode: Visual Studio Code extension for Prettier
上記エラーは package.json に prettier があるのに node_modules 内の prettier が見つからなかったので発生しているようです。
yarn pnp (Plug’n’Play: プラグアンドプレイ)では npm の node_modules のようにインストールしたパッケージをプロジェクト毎に展開しません。インストールしたパッケージはユーザーグローバル (%LOCALAPPDATA%\Yarn\Berry\cache) で保有し、各プロジェクト内の .pnp.cjs を通じて必要なパッケージがロードされます。
ちょっと長いですが、公式ドキュメントの説明を引用しておきます。
If you look into the files in your project, you may notice the absence of a
node_modulesfolder. This is unusual! We regularly get asked on Discord where the folder is, by people thinkingyarn installsilently failed.
The thing is, this is actually expected! The way Yarn PnP works, it tells Yarn to generate a single Node.js loader file in place of the typicalnode_modulesfolder. This loader file, named.pnp.cjs, contains all information about your project’s dependency tree, informing your tools as to the location of the packages on the disk and letting them know how to resolve require and import calls.
- Plug’n’Play | Yarn
さて yarn pnp では各プロジェクトにパッケージを展開せず、.pnp.cjs を通じてパッケージがロードされるという部分を何とかしないと prettier-vscode は動きそうにないですね。
対応
プロジェクトの .yarnrc.yml に nodeLinker: node-modules を設定すれば node_modules に展開されるようになりますが、これは pnp の恩恵 (Plug’n’Play | Yarn) が失われ本質的ではありません。
Define how Node packages should be installed.
Yarn supports three ways to install your project’s dependencies, based on thenodeLinkersetting. Possible values are:
- If
pnp, a single Node.js loader file will be generated.- If
pnpm, anode-moduleswill be created using symlinks and hardlinks to a global content-addressable store.- If
node-modules, a regularnode_modulesfolder just like in Yarn Classic or npm will be created.
どうしたものかと色々調べていたところ公式ドキュメントにこんなページが。
Why are SDKs needed with Yarn PnP?
Yarn PnP works by generating a Node.js loader, which has to be injected within the Node.js runtime. Many IDE extensions execute the packages they wrap (Prettier, TypeScript, …) without consideration for loaders. The SDKs workaround that by generating indirection packages. When required, these indirection automatically setup the loader before forwarding therequirecalls to the real packages.
- Editor SDKs | Yarn
Editor SDK なるものが用意されており、まさに「yarn pnp では各プロジェクトにパッケージを展開せず、.pnp.cjs を通じてパッケージがロードされる」という部分を何とかしてくれると書かれています。
早速上記ページに沿って Editor SDK をインストールします。
yarn dlx @yarnpkg/sdks vscode適当な JavaScript を保存してみると、無事にフォーマットされました!
prettier-vscode のログを見てみると prettier がプロジェクトの .yarn/sdks/prettier に解決されるようになっていることが確認できます。
["INFO"] PrettierInstance:
{
"modulePath": "c:\\path\\to\\project\\.yarn\\sdks\\prettier\\index.cjs",
"messageResolvers": {},
"version": "3.4.2"
}あとがき
yarn pnp のプロジェクトで VSCode 拡張機能の prettier-vscode をプロジェクトの prettier を使って動かす方法を紹介しました。Editor SDK は yarn dlx でインストールするのでプロジェクトのパッケージ依存関係に影響を与えませんが、その分各開発者のプロジェクトインストール作業がひと手間増えます。プロジェクトでエディタが固定されている場合はひょっとするとプロジェクトの依存に入れちゃってもよいのかもしれませんが、yarn add でインストールした場合も、問題なく動くかは検証できていません。