Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Prettier 3.0 の VSCode 拡張対応における技術的な意思決定~VSCode 拡...
Search
sosukesuzuki
September 06, 2023
1
1.8k
Prettier 3.0 の VSCode 拡張対応における技術的な意思決定~VSCode 拡張で dynamic import が動かない~
VSCode 拡張で dynamic import が動かない
sosukesuzuki
September 06, 2023
Tweet
Share
More Decks by sosukesuzuki
See All by sosukesuzuki
JavaScriptCoreのObject.groupBy/Map.groupByのバグを自分で報告して自分で直す
sosukesuzuki
1
410
「書いたJavaScriptがそのままブラウザで動く未来へ」スピーカーノート
sosukesuzuki
8
11k
ESM移行は無理だけどおれもSindreのライブラリが使いたい!
sosukesuzuki
2
1.2k
JavaScript エコシステムを維持する OSS の努力と課題
sosukesuzuki
14
9.1k
Prettierに従わなくてもいい場合
sosukesuzuki
7
3k
Prettier 2.0
sosukesuzuki
2
1.6k
Prettier の TypeScript 3.7 対応について
sosukesuzuki
0
370
Prettier のしくみ
sosukesuzuki
4
2.4k
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
65
4.4k
5 minutes of I Can Smell Your CMS
philhawksworth
202
19k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
329
21k
The Pragmatic Product Professional
lauravandoore
31
6.3k
GitHub's CSS Performance
jonrohan
1030
460k
Statistics for Hackers
jakevdp
796
220k
How to Ace a Technical Interview
jacobian
276
23k
Designing the Hi-DPI Web
ddemaree
280
34k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.8k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
840
GraphQLの誤解/rethinking-graphql
sonatard
67
10k
Fireside Chat
paigeccino
34
3k
Transcript
Prettier 3.0 の VSCode 拡張対応 における技術的な意思決定 ~ VSCode 拡張で dynamic
import が動かない~ 2023/09/06 nihonbashi.js
自己紹介 SUZUKI Sosuke • Ubie 株式会社プロダクト開発エンジニア • サイボウズ フロントエンドエキスパートチーム •
筑波大学 情報学群 情報科学類 B3 • Prettier メンテナー • Babel コミッター @__sosukesuzuki @sosukesuzuki
目次 1. Prettier 3.0 リリース 2. Prettier 3.0 はすべてが ECMAScript
Modules 3. prettier-vscode における ECMAScript Modulesの問題 4. 言語サーバーの開発と挫折 5. worker_threads による回避策 5. まとめ
Prettier 3.0 リリース
2023年7月5日、実に3年以上ぶりとなるPrettierのメジャーリリース Prettier 3.0 リリース
Prettier 3.0 リリース trailingCommaのデフォルト値がes5からallに Internet Explorer のサポート終了により、主流のウェブブラウ ザのすべてがtrailingComma: allのJavaScriptを解釈できる ようになった。
日本語とラテン文字の間にスペースを入れない Markdownのフォーマットで、日本語 /中国語とラテン文字の 間にスペースを挿入しないようになった。今回のリリースの中 で最も賛否が分かれるであろう変更。 .gitignoreのファイルを無視する .prettierignoreだけでなく.gitignoreのファイルもデフォルトで 無視するように。 --ignore-path=.prettierignoreをつければ今 まで通り。 *.d.tsファイルが本体パッケージに含まれる ライブラリとして使うときの型定義が本体パッケージに含まれ るようになった。 @types/prettier を別途インストールする必要 はもうない。 https://prettier.io/blog/2023/07/05/3.0.0.html Prettier 3.0 におけるユーザー影響が大きい変更4選
Prettier 3.0 はすべてが ECMAScript Modules
CommonJS から ECMAScript Modules へ Prettier 3.0 はすべてが ECMAScript Modules
• Prettier 2.x まではソースコードは CommonJS で書かれていた • Prettier 3.0 からはソースコードがすべて ESM になった ◦ 実行されるときもNode.jsのネイティブESM ◦ メリット ▪ (Prettierチームにとって)開発者体験が向上する ▪ Tree Shakingの精度が高くなる ▪ ビルドスクリプトの複雑さが軽減される ▪ Pure ESM パッケージのために使っていた workaround を除去できる ◦ dynamic import を使ってプラグインや設定ファイル (.prettierrc)を読み込む • 2.x ではrequireを使っている
CommonJS から ECMAScript Modules へ Prettier 3.0 はすべてが ECMAScript Modules
./node_modules/.bin/prettier ./bin/index.cjs ./internal/cli.mjs ./internal/internal.mjs 1. エントリポイントはCJSファイル 2. CLIの本体ファイル(ESM)を読み込む 3. コア実装(ESM)を読み込む 4. プラグインや設定ファイルも import で読み込む import(“./internal/cli.mjs”) import(“./internal/internal.mjs”) plugins .prettierrc import import
prettier-vscode における ECMAScript Modulesの問題
prettier-vscode prettier-vscode における ECMAScript Modulesの問題 • Prettierの公式VSCode拡張 • 正式な名前は「Prettier -
Code formatter」 ◦ 紛らわしいのでリポジトリ名から、 prettier-vscodeと呼ぶことにする • 開いているファイルをフォーマットしてくれる ◦ format on save を設定しておくと便利 ◦ Range formatting もサポートしている • なんとブラウザでも動く (= codespacesでも動く?)
prettier-vscodeのPrettier3.0対応 prettier-vscode における ECMAScript Modulesの問題 • Prettier 3.0からJavaScript APIはすべてPromiseを返す •
prettier-vscodeはPrettierのJavaScript APIを使うので、全部にawaitをつけて回る必要がある const formatted = prettier.format(text, options); const formatted = await prettier.format(text, options); Prettier 2.x Prettier 3.x
prettier-vscodeのPrettier3.0対応 prettier-vscode における ECMAScript Modulesの問題 • これくらいなら普通にサクッとやれば良い • シュッとやってBeta版を出してみた https://github.com/prettier/prettier-vscode/pull/2947
prettier-vscodeのPrettier3.0対応 prettier-vscode における ECMAScript Modulesの問題 • 本番ビルドした結果全然動いてなかった (debug モードだと動いていた )
• 調査の結果、dynamic importの実行が全部エラーになることがわかった ローカルで試したら 全然動かないです。多分 dynamic import が動いてな い...。 Prettierのビルドいじって頑張って みたけど動かない ...。 マジか
prettier-vscodeのPrettier3.0対応 prettier-vscode における ECMAScript Modulesの問題 ESLint の flat config も設定ファイ
ルを dynamic import してるはずだ けど、VSCode 拡張ちゃんと動いて いるよね。なんでだろう? たしかに 調べてみます
言語サーバーを使ったアーキテクチャ prettier-vscode における ECMAScript Modulesの問題 • vscode-eslintなどの一部のVSCode拡張は言語サーバーを使っている • VSCode拡張の本体は、その言語サーバーにとってはクライアントである •
クライアントと、別に立ち上がる Language Serverプロセスとが通信しあう ◦ LSP(Language Server Protocol) 言語サーバー vscode-eslint ESLint を実行してくれ foo.jsの3行目に ◯◯エラーが出てるよ
言語サーバーを使わないアーキテクチャ prettier-vscode における ECMAScript Modulesの問題 • prettier-vscode は言語サーバーを使わない • 全てを
VSCode 拡張本体の中で処理する prettier-vscode 今開いてるファイルに Prettierを実行して上書きす るぞ〜
言語サーバーからは dynamic import ができる prettier-vscode における ECMAScript Modulesの問題 • クライアント(拡張の本体)では
dynamic import ができない • しかし、言語サーバーからなら dynamic import ができる 言語サーバー VSCode拡張本体 foo.js dynamic import
prettier-vscode も言語サーバーがあれば dynamic import が使えるのでは? 😎
【余談】問題の原因を推測する prettier-vscode における ECMAScript Modules対応とその問題 • VSCode拡張クライアントでdynamic importしたときに起こるエラーは ◦ TypeError:
A dynamic import callback was not specified. • これは、Node.js の vm.Script 環境で dynamic import を呼び出したときに発生する ◦ つまり、VSCodeでは拡張を実行するときに vm.Script環境に隔離していそう • prettier-vscode開発中のデバッグモードではこの問題は起こらなかった ◦ 多分、デバッグモードではこの隔離が有効になっていない
言語サーバーの開発と挫折
prettier-vscodeにも言語サーバーを実装する計画 言語サーバーの開発と挫折 • dynamic importを使うために、eslint-vscodeと同じアーキテクチャに変更しようした • つまり ◦ 言語サーバーを導入し、 Prettierの実行はすべてサーバーで行う
◦ クライアントはそれを VSCodeに反映させるだけにする • しかし...
prettier-vscodeのメンテナが不在 😢
VSCode 拡張の経験者も 言語サーバーの経験者もいない 😢
挫折... 言語サーバーの開発と挫折 • イチから作れというのならまだ適当にやればよかった • が、prettier-vscodeの挙動を維持しながら言語サーバーを使ったアーキテクチャに移行するというのが 本当に困難だった ◦ 実装や仕様がわからないソフトウェアの挙動を維持しながらアーキテクチャを大幅に変えるのは一 般に困難な気がする
• 努力の残骸たち(マジで苦しかった) ◦ https://github.com/sosukesuzuki/vsce-doc-formatting-sample ◦ https://github.com/sosukesuzuki/prettier-language-server-vscode-client ◦ https://github.com/sosukesuzuki/prettier-language-server-deprecated • 言語サーバーを導入する方法は諦めた
worker_threads による 回避策
言語サーバーを使わずにdynamic importを実行する術 worker_threads による回避策 何も思いつかねえ ... VSCode拡張から新し いプロセス生やせばい けるらしいよ え?
child_processとかでプ ロセス作れば、そこから dynamic importできるら しい
worker_threads による回避策 worker_threads による回避策 • vm.Script環境ではdynamic importができない • が、vm.Script環境で新たにスレッドを立てれば、そのスレッド内からは dynamic
importができる ◦ (わざわざプロセスを作る必要はなかったので worker_threads を使うことにした) VSCode拡張 メインスレッド worker_threadで作った新しいスレッド foo.js dynamic import
これしかない 🔥
worker_threads による回避策 worker_threads による回避策 • worker_threads のスレッド内でのみ Prettier 3.0 を実行するアーキテクチャへ
◦ (Prettier 2.0 を使っている場合はメインスレッドで実行する ) prettier-vscode メインスレッド worker_threadで作った新しいスレッド .pretterrc プラグイン Prettier本体 dynamic import フォーマットした い フォーマットした よ
worker_threads による回避策 worker_threads による回避策 https://github.com/prettier/prettier-vscode/pull/3016
まとめ
まとめ まとめ • VSCode拡張でdynamic import が動かない • 言語サーバー導入しようとしたけど難しかった • だからworker_threadsでスレッド立てて、そこから
dynamic importするようにした • 今のところ重大なバグ報告は来ていないが、実装者的には普通にバグってそうな気がする • 怪しい挙動があったら教えて下さい https://opencollective.com/prettier か https://github.com/sponsors/sosukesuzuki から寄付をくれると、 メンテを継続しやすくなります。