😭

VSCodeでprettier-plugin-tailwindcssを適用する際にをつけること

2023/10/15に公開

!!!注意!!!

概要

Tailwind CSS を使ったプロジェクトで、VSCodeでファイルを保存した時のフォーマットの際に prettier-plugin-tailwindcss を適用しようとしたところ、ちゃんと動かすまで時間がかかってしまったので、調べたことをまとめておく。

なお、CommonJS(以下CJS) や ES Modules(以下ESM) についてはあまり詳しくないため、間違っている箇所があるかもしれません。

TL;DR

  • 拡張機能がデフォルトで使用するPrettierのバージョンが安定していないため、プロジェクト側でインストールして使う方が良い
  • Prettier v3 を使う場合、configファイル の plugins"prettier-plugin-tailwindcss" を追加する必要がある
  • configファイルをjs形式で記述する場合は、CJS なのか ESM なのか意識して記述する必要がある
    • 拡張子が .mjs であるか、package.jsonに type: module が設定されていたらESM、そうでなければCJS...のはず

基本的にはプロジェクトにPrettier v3をインストールした上で、configファイルを以下のように書けば動くはず。

prettier.config.js
export default {
  ...,
  plugins: ["prettier-plugin-tailwindcss"],
}

環境

気にすべきポイントのまとめ

後述で色々説明してますが、長くなるので詰まりそうなポイントだけ記載します。

  • プロジェクトにPrettierがインストールされていない場合、拡張機能のデフォルトのバージョンが使用される
    • 2023/10/15 時点でのデフォルトバージョンはv2
    • 一度v3に上げられた後で問題があってv2に戻されている状態なので、今後どこかで正式に更新されると思われる
  • プロジェクトにPrettierがインストールされている場合は、拡張機能は自動的にそのバージョンを使用する
  • CJS(module.exports)での記述が必須。v3の場合はプロジェクトでの設定や拡張子に合わせて記述されていればどちらでも動く
  • Prettier v3を使う場合、config の plugins に "prettier-plugin-tailwindcss" を追記する必要がある
    • configファイルを書き換えたり名前を変えた場合に正しく再読み込みされないことがあるため、VSCodeを再起動して確認したほうが確実
    • 現時点ではconfigファイルのpluginsでprettier-pluginではないライブラリ名を指定してもエラーにならないため、OUTPUTタブでログを見て確認すると安心
  • prettier-plugin-tailwindcss のv5以降はPrettier v3以上が必須

調査したことメモ

1. 拡張機能内部のprettierのバージョンについて

一度v3に上げられたものの、何か問題があって現時点ではv2に戻されている。
今後の対応については以下の Issue を追えば良いと思われます。

https://github.com/prettier/prettier-vscode/issues/3142

2. Prettierのバージョンと、configファイルの形式の対応

Prettierはv3で正式にESM対応されたらしい。

参考: Prettier のあまりに行儀の悪い Pure ESM パッケージ対応

このため、v2の場合はESM

試しに色々な組み合わせで動作確認してみた結果は以下の通り。
なお、ログはVSCode の OUTPUT タブで Prettier を表示した状態で、適当なファイルをフォーマットした際に出力されたものを記述しています。

Prettier v2 の場合

prettier.config.cjs で module.exports

これは正常に動作する。

prettier.config.js で module.exports

これだとファイルを ESM として読み込もうとするが実際の記述が CJS なのでエラーになった。

これはエラーメッセージにもある通り、自分のプロジェクトの package.json に "type": "module" の記載があり、拡張子 .js のファイルは自動的に ESM として判別されるため。(type指定が無い場合の動作については未検証ですが、この記事の本題とちょっと逸れるので割愛)

Error [ERR_REQUIRE_ESM]: require() of ES Module b:\xxx\front\prettier.config.js from c:\yyy\.vscode\extensions\esbenp.prettier-vscode-10.1.0\node_modules\prettier\third-party.js not supported.
prettier.config.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename prettier.config.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in b:\xxx\front\package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

prettier.config.cjs で export default

当たり前だけどこれはエラー。拡張子でCJSと明示しているのに書き方が ESM になっているため

["ERROR" - 3:55:37 PM] Unexpected token 'export'
b:\xxx\front\prettier.config.cjs:1
(function (exports, require, module, __filename, __dirname) { export default {
                                                              ^^^^^^

SyntaxError: Unexpected token 'export'

prettier.config.js で export default

これもエラー。v2の場合はCJSで書いておく必要がありそう。

["ERROR" - 4:05:49 PM] require() of ES Module b:\xxx\muscle-record\front\prettier.config.js from c:\yyy\.vscode\extensions\esbenp.prettier-vscode-10.1.0\node_modules\prettier\third-party.js not supported.
Instead change the require of prettier.config.js in c:\yyy\.vscode\extensions\esbenp.prettier-vscode-10.1.0\node_modules\prettier\third-party.js to a dynamic import() which is available in all CommonJS modules.

Prettier v3の場合

prettier.config.js で export default

正常に動作する。
Prettier v3ではこれが一番正しい記述方法だと思われる。

prettier.config.cjs で module.exports

これはエラーになるのかと思ったけど正常に動作した。
以下の記事にもある通り、ESMからCJSを読み込む場合はmodule.exportsがdefault exportとしてみなされるため。

https://zenn.dev/uhyo/articles/typescript-module-option

逆に、ES ModulesからCommonJSモジュールをimportすることはできます。この場合、CommonJS側のmodule.exportsがdefault exportと見なされます

prettier.config.cjs で export default & prettier.config.js で module.exports

これはどちらもエラー。
プロジェクトでの指定・拡張子で指定した方式に合わせて記述することが必要。

3. Prettier v3からpluginsの自動検出が無効化された

この Issue コメントに書かれている通り、インストールされたプラグインを自動検出して適用する動作がv3で廃止されたらしい。

https://github.com/tailwindlabs/prettier-plugin-tailwindcss/issues/176#issuecomment-1743220914

The plugin search feature has been removed.

このため、前述したようにconfigファイルに plugins を明示する必要がある。

  "plugins": ["prettier-plugin-tailwindcss"],

ちゃんと読み込まれているかどうかは、VSCodeの OUTPUT タブで、任意のファイルをフォーマットした時に出るPrettierのログを見ると良い。

4. pluginsの記載が間違っている場合の動作

存在しないライブラリ名を指定した場合はエラーになってくれる。
※記述した直後はエラーが出なかったりするため、VSCodeを再起動して確認した方が安全

ただチェックしてくれるのは存在の有無だけで、pluginではないものを指定している場合はエラーにならないため注意。
以下は間違って "plugins": ["tailwindcss"] と書いてしまった場合のログ。

5. prettier-plugin-tailwindcss の v5 からは Prettier v3 が必須

README に以下の記載がある。

A Prettier v3+ plugin for Tailwind CSS v3.0+ that automatically sorts classes based on our recommended class order.

この PR で取り込まれたらしい。

https://github.com/tailwindlabs/prettier-plugin-tailwindcss/commit/cc5f3239d1f98ef3341e7092869edf824b5b956c

おわり

ここまで書き終わってから冒頭の話に気づいてしまい、絶望したよ!

でも調べた事自体は間違ってないと思うし、勉強にはなったから残しておくよ!

みんなは有限な時間を有効活用してね!じゃあね!!!!!😭

Discussion