音声書き起こし 1. オープニング 00:00 @TheoSteiner 00:08 こんにちは、UITのテオです。ユーザーインターフェースとテクノロジーを愛する開発者のためのポッドキャスト「UIT INSIDE」、今回もやっていきたいと思います。今回sapphi-redさん、緑さんをゲストとして招待しまして、彼とVite 8について話していきたいと思います。よろしくお願いします。
@sapphi-red 00:29 よろしくお願いします。
2. ゲスト自己紹介 00:31 @TheoSteiner 00:32 早速なんですけど、多分フロントエンド界隈でsapphi-redさんのハンドルとか見たことない人はおそらくいないかなと思ってるんですけど、Viteのコアメンテナーとして大活躍してる方なんですけど、軽く自己紹介していただいてもいいですか?
@sapphi-red 00:50 はい。Viteのコアチームメンバーをしてます、みどりです。GitHubだとハンドルがsapphi-redでやってます。
@TheoSteiner 00:58 いつからViteのメンテナンスなんですか?
@sapphi-red 01:00 多分今年で3、4年目くらいになると思いますね。
@TheoSteiner 01:08 割とプロジェクトの初期から関わってる感じですよね。
@sapphi-red 01:12 実はそうでもなくて、多分活動をし始めたのが大体Vite 3あたりなんで、一番最初のEvanの開発がずっと1のなんとかで、1のRCが来てそのまま2に飛んだんですけど、リリースはなんでも2のいろいろあって、その後の3って感じなんで、ある程度、なんだろう、最初の開発は一通り落ち着いたくらいのタイミングですね。
@TheoSteiner 01:44 バージョン3からいるってことは、何をきっかけにViteのメンテナンスをするようになったんですか? 最初のコミットとか覚えてたりしてますか?
@sapphi-red 01:56 一番最初のコミットで言うと、コミットというかPRで言うと、3よりもちょっと前に、ちょうどそのVue CLIをViteにするのかしないのかくらいの時期の時にViteを試して、ハマったバグを直したPRを出したんですけど、多分それが一番最初のやつで。それ自体は結構たくさんコントリビュートするよりも前の時に、単発のものがあった感じ。
@TheoSteiner 02:31 ってことは、Viteのメンテナンスをする前まではVueの開発とかを主にされてて、それでViteを知ったっていう、家で使って開発しててViteを知ったと。
@sapphi-red 02:41 そう。
@TheoSteiner 02:45 そもそも、みどりさんの背景ってどういうご背景ですか?
@sapphi-red 02:48 その時は僕は大学生で、自分は東京工業大学、今は東京科学大学になっちゃってるんですけど、東工大のtraPっていうサークルがあるんですけど、そこで、そのサークルの中で使うコミュニケーションツールを作ってて、それでVueを使ってフロントを書いてたので、そこがきっかけ。
@TheoSteiner 03:21 そこでVueを知って、Vueに貢献したいと思ってVue関連のリポジトリに関わった経由でViteにたどり着いた感じ?
@sapphi-red 03:30 そういうわけではないですね。単純にViteを使ってて、その中でバグ見つけたんで、直さないと使えないなってなって直した。
@TheoSteiner 03:38 ここで自分から直しに行くのもすごいと思うんですけど。さすがtraPだなって。実は僕も2年前ぐらいに同期と一緒にISUCONに出たんですけど、その時すごいtraPさんが作った資料とかお世話になったので、ありがとうございます。
3. Vite がなぜ流行ったか 03:56 @TheoSteiner 03:56 で、Vite 3からだいぶ時間が経ってきたと思いますが、Viteとはバンドラのこと、今一番多分フロントエンド界隈で使われているバンドラということは多分視聴者の皆さんが知ってると思いますけど、バンドルっていうのは、多分みんなわかると思うんですけど、開発時の、例えばVueの開発とかだったら、ファイルをいい感じにして、最終的にブラウザが読み込むHTMLとそこから参照されているJavaScript、CSSファイルをいい感じにする技術っていうのは多分みんな知ってると思いますけど、なんでViteがそこまで流行ったんですか? 前も別のバンドラとかいっぱいあったのに、なんでViteですか?
@sapphi-red 04:46 なぜ流行ったか。そうですね、やっぱり一番大きいのは設定のしやすさだと思いますね。しにくかった、エンドユーザーとしてしにくかったっていうのは多分ある程度解決はされてるんですけど、主に例えばVueだったらVue CLIが裏側の設定とかを全部いい感じにしたものを作ってくれるとか、ReactだったらCreate React Appが全部リセットみたいなコンフィギュアされてるものとかを提供してたりしたと思うんですけど、でもやっぱりちょっと変えようとした時とかも、結構その裏側の設定が複雑で、どうすればちょっと変えるかとかも、だいぶ難しかったりとかがあって。Viteだったら本当に、ちょっと変えるくらいだったら何かオプションをちょっと変えるとかは多分その頃よりも簡単にできるっていうのと、あとはもともと従来あったものよりも、デフォルト、最初から設定を変えなくても高速に動作したっていうこともあるのかなって思います。
@TheoSteiner 06:03 ある程度アウトオブザボックスで使えるようなバンドラーだったってことですね。
@TheoSteiner 06:10 僕もViteが登場するちょっと前から開発者として働いてるんですけど、当時Vueとかではなくて、僕Svelteを使ってたんですけど、その時はRollupをdevでも開発時でも使ってたんですけど、エディターで編集してからそれがブラウザに反映されるまでの時間が結構かかったりしてたので、Viteが初めて出た時のホットモジュールリロード、ちょっとだけモジュールをいじってそれが反映されるまでの時間がもう、すごい改善されてびっくりしてましたね。
@sapphi-red 06:46 そうですね。HMRに対応してるっていうのも一個メリットだと思いますね。やっぱwebpackで設定するってなってもHMRって、それそのためだけに別のローダーとかプラグインとか設定とかを設定しないと動かないんですよ。なので、そういう点でViteだと各フレームワーク用のプラグイン側で設定されてあるので、基本的に入れればHMRもちゃんとフレームワーク側が対応していれば動くっていうところも。
4. Vite 3 から 8 までの変化 07:34 @TheoSteiner 07:34 それが、ほとんどViteの3ぐらいの時からある機能なんですけど、最近になって、4月の頭ぐらいですかね、Vite 8がリリースされていて、Vite 3から8までってどういう動きがあったんですか? どうやって変わったんですか? 個人的な印象でも全然大丈夫。
@sapphi-red 07:52 その中で一番大きいのはEnvironment APIが導入されたことですね。
@TheoSteiner 08:00 Environment APIっていうと、それは例えばNode.jsじゃないenvironmentを簡単に開発時でもターゲティングできるような仕組みのこと、でありますか?
@sapphi-red 08:21 それもそうですね、導入された目的の一つとしてはそれが一つで、APIそのもので言うと、もっとViteをclientサイドレンダリングだけじゃないっていう形にリアーキテクトしたっていうのが多分良い捉え方かなって思います。もともとAPIの導入前からもSSRの対応っていうものはあったんですけど、どうしても中心にclientサイドレンダリングのSPAがあって、それに付随してSSRの機能が付いてくるよっていう形が実装になってて、APIはこれをどっちかというと両方とも対等に扱えるようになった。これを導入することでもっと広げるというか、Viteの抽象度を上げて、今まで主にclientが中心だったんですけど、clientと同じくらい中心にSSRのユースケースとかも置いて。
@TheoSteiner 09:33 主に多分メタフレームワークとかを作ってる人向けのAPIっていう理解でやってますか?
@sapphi-red 09:38 そうですね。多分Svelteとかだったらそれを使って、SvelteKitの場合はサーバーのランタイムにより合わせやすくするための使い方が多いんですけど、必ずしもそういう使い方じゃなくて、単純にSSRとclientの両方のユースケースをViteの配下に収めるためのAPIだったというのが企画。
@TheoSteiner 10:08 そうですね。それがVite 6ですか?
@sapphi-red 10:10 そうですね、6がとりあえずexperimentalで挿入されて。
@TheoSteiner 10:17 Vite 8となってもうstabilizeとかされたんですかね?
@sapphi-red 10:23 まだされてない状況なんです、そうです。まだされてないよ。
@TheoSteiner 10:26 だいぶ近づいてはいる。
5. 統合されたバンドラー 10:30 @TheoSteiner 10:30 じゃあVite 8でAPIのところが割とステーブル化に近づいたんですが、それよりコアな変更が今回もあって、それが統合化、内部の統合化なんですけど、何がどう統合されたんですか?
@sapphi-red 10:49 そうですね。もともとViteって7までは主にその2つのツールを内部的に使ってて、名前を挙げるとesbuildとRollupっていう2つのツールを使ってたんですけど。なんで使ってたかっていうと、大きくViteを使うときにあたって2つの使い方があると思ってて、1個目が通常の開発のときにいわゆるHMRが効いたり編集して変更が反映されてっていうような場合と、実際にエンドユーザーに届けるためにソースコードをビルドして最終成果物を得るっていう、2通りがあるときに、これらってビルドする目的が違ってて、開発の時はできる限り早く開発者が変更した結果の反映を得たいっていうポイントがあって、逆にビルド時っていうのは最終的な成果物がエンドユーザーの操作だったりとかの体験が良くなってほしいっていう別の目的があって。開発時の方に関しては、できる限りこの反映を速くしたいっていうところにフォーカスを当てて、Viteではesbuildっていうものを部分的に使って、最終的なバンドルサイズを小さくするという目的のためにRollupというesbuildとは違うビルドツールを使ってました。この別のツールを使ったのはそれぞれ特性が違ってて、esbuildは速いけどバンドルサイズをあまり小さくできない、Rollupは逆にちょっと遅いけどバンドルサイズを小さくすることができるっていう点でそれぞれ別のものを使ってました。ただ、ここで問題になるのが、別のものを使うと挙動が違ったりするんですね。仕様があるものっていうのは割とその動作を合わせるとかがしやすいんですけど、例えばJavaScriptは僕ら書いてると思うんですけど、JavaScriptには仕様があって、この仕様に沿って各ブラウザがJavaScript Engineを実装して、統一されたテストとかが書いてあって、あるブラウザに対して書いたコードが他のブラウザでも同様に動くっていうのが担保されてるっていうのがある。こういう場合だったら別のツールを組み合わせてもそんなに大きな差は生まれなくて困らないんですけど、ただ、バンドラーって問題があって、JavaScriptの部分に関しては仕様があってそれに沿うっていうのは当然なってるんですけど、仕様がないものが、主に、例えば例で挙げるとCommonJSのモジュールからESMのモジュールを読み込んだときどうなるかっていうのは、権威のある仕様としては決まってないんですね。一応Node.jsはこうやって処理するよとか、今まではこういう風に処理をしていたよっていうのはあるんですけど、なおかつこれらのデファクトな挙動っていうのはコンフリクトしてたりするんですね。なので、別のツールを使うとそれぞれが思ったベストな方法でやるので若干挙動が違うっていうのが発生します。とはいえ、これはそういう不整合があったところでしか起きない問題ではあるので、すごいよく発生するってわけでもないんですけど、ただ、発生したときは何でそれが起きてるかよくわからないし、なんなら開発時は動いてたのに本番で動かないっていうのはデバッグもしにくいし、実際その開発で動いてたからプロダクションにリリースしたのにエンドユーザーでは壊れてるっていうのは当然やりたくない。こういう問題があったっていうのが背景としてあって、Vite 8ではこのesbuildとRollup、それぞれメリット・デメリットがあった中、いいとこ取りをして一つに置き換えてそれを使おうっていうので作った、このRolldownというesbuildの速さとRollupのバンドルの小ささをうまく組み合わせて作ろうと言って作ったRolldownを中で開発時とビルド時両方ともで使うようになったっていうのがVite 8の統合。
@TheoSteiner 15:48 かなり大きい変更ですよね。今まで2つの目的で開発時とビルド時のツールチェーンを分けたところを、Rolldownっていう新しいツール、ネイティブの力を使ってすごく早く動くツールを使って、その2つのツールチェーンを統合させるっていう大きな変更ですね。
@sapphi-red 16:06 そうですね。でも、今までに開発時とビルド時の挙動が違うとは言いつつ、本当によくできてて、普通の開発でほとんどそういう挙動が違うバグにはぶつからないことが、今までのViteのコアチームの凄さと言ってもいいと思うんですけど、たまに、本当に少ないんですけど、たまにあるんですよね。開発時にesbuildがちょっとtree shakingとかを行わない、tree shakingっていうのが使われないJavaScriptの削除とかを行わないのに、ビルド時にRollupがそれを削除したせいで何か振る舞いが違うとか、そういうバグはたまに、本当に滅多にないと思うんですけど、あったりするんですけど。
@TheoSteiner 17:00 今後はビルド時もdev時も全く同じツールチェーンが動くからそういうことが起きないはずっていう理解でやってますか? 全く一緒ですか? ビルド時と。
@sapphi-red 17:21 全く一緒っていうのは僕らが頑張ってもできなくて。っていうのも、例えばライブラリによっては開発時とビルド時で違うファイルを使ってねって書いてあるライブラリとかあるんですよ。node_modulesは、developmentだとこっちのファイルを読んで、productionだとこっちのファイルを読んでって書いてあるんですよ。ってなると、当然違うファイルなんで違う動作をして、当然その結果が違うっていうのが発生し得るっていうのが一つの例だし。もう一つの例だと、tree shakingって結構難しいところがあって、開発時は物によってはするけどしないっていうこともあって、当然解析をしないといけなくて、解析をするのはコストがかかるので、それをしない場合は安全に倒して残すってなるので、開発時には残ってて本番時にはなくなるっていうのは発生し得る、同じものを使ってたとしても、っていうのがある。なので、完全に消し去ることはできない。ただ、そのカテゴリーのものを最低限にまで落とすことができるっていうことはあり起こすことができる。
6. 統合についてメンテナンスの観点から 18:38 @TheoSteiner 18:38 というのが多分ユーザーからの観点。で、開発、Viteのメンテナンスの観点もありそうだなと今思ってたんですけど、Rollupとesbuildっていう2つのツールをできるだけ近い動作にするのも大変なので、メンテナンスの観点から一つのツールにした方が作りやすいとかっていうのもありますか?
@sapphi-red 18:56 そうですね、割と頑張ってこう挙動を揃えてるっていうところはあったので、多分Vite 7とかのコードを読みに行くと、この特定の条件でこの特定のことが発生した場合はうまくいかないけど大抵の場合はうまくいくから、こういうワークアラウンドがあるよ、みたいなコメントとかをちょこちょこ書いてあったりするので、そういうようなものもだいぶ書かなくてもいいし、考える必要のあることが減ったのでメンテナンスも楽に。あと、これ自体は実際に一つになったからっていうところが理由ではないんですけど、Vite側で必要なものがあったっていうときに、Rolldown側で変更するっていう選択肢が生まれたことは大きいですね。外部ツールを内部ツールにしたから、Viteチームが「これ変えた方がいい」って言ったらRolldown、Viteとほとんど同じなので関係性が近いから、もっとそういった変更も取り入れやすいっていうところ。
@TheoSteiner 20:19 内部のツールをRolldownに変える背景としては、RolldownがRollupより圧倒的に早く、Rollupとほぼ同じような処理ができるっていうことが多分あると思いますけど、なぜRolldownがRollupよりあんなに早いんですか? どこでトレードオフしてるんですか?
@sapphi-red 20:55 そうですね、一番大きいのはそのコアがRustで書かれていることは大きいと思いますね。というのも、JavaScriptって本質的に並列化が難しくて、というのも同じ情報をコピーせずに並列でアクセスすることができないんですね、JavaScriptって。Rustはそれができるんです。情報をコピーするのって結構重い処理で、ってなると、JavaScriptは並列でやらない、あるいはコピーをして並列っていうどっちかしか取れなくて、いずれの路線を行ったとしてもRustのコピーせずに並列で処理するっていうのにはかなわなくて、そこが一番大きいと思いますね。特に最近のパソコンはコアの数が増えてるので、そこでのスケールも大きくなってきてるっていうのもあります。
@TheoSteiner 21:54 ネイティブでRustで書かれてるってなると、今までViteのプラグインってJavaScriptで書くじゃないですか。フロントエンド開発者でもこれからRustを勉強してViteとかをRustで書く必要、ではないですよね。そこのやりとりってどうしてるんですか?
@sapphi-red 22:12 そうですね、Rustでプラグインを書く必要はなくて、なおかつ現状はRust側にRustでプラグインを書いてそれをRolldownで使うっていうのは現状できなくて、Rolldownは現状JSのプラグインしか受け入れられない形になってます。読み込みのもの以外どうなってるか、そこの部分の仕組みとしては、Node.jsでファイルの読み書きをするときの内部的な処理と同じような仕組みが。詳しく話すと、Node.jsでファイルを読み書きするときって、`import fs`で書いて、`fs.readFileSync`とかを呼ぶと思うんですけど、こうやって全部JavaScriptで処理されているわけではなくて、っていうのも、OS、WindowsだったりMacだったりLinuxっていうのは別にJavaScriptからアクセスできるものをAPIとして提供してなくて、基本的にはC言語だったりでしかアクセスができない形になってて、なので、`fs.readFileSync`とかを呼んだ時はNode.jsが内部的にこの関数が呼ばれたらC側の何らかの関数を呼んでるっていうのをやってるんですけど、これと似た仕組みでRolldownでもJavaScriptからRust側を呼ぶだったり、JavaScriptから渡したコールバック関数をRust側から呼ぶっていうことを内部的にやることで、JavaScriptで書いたプラグインがRolldownで動作するっていうことが成り立つ。
@TheoSteiner 23:43 だから、Viteのプラグインですごい遅く処理されるJavaScriptの処理があったとしてもそれが今回早まらずに普通のJavaScriptで実行されるので今まで通りの時間かかっちゃうけど、そのプラグインを組み込むフレームというか、プラグインが実行される環境がRolldownに変わっていて、すごく早まったって言ったでしょうですかね? プラグイン側の速度は変わらない、バンドラーそのものの処理は早くなった。そのバンドラーは裏で色々してると思うんですけど、例えばAbstract Syntax Treeとかを作ったりするんですけど、それがネイティブになったから前よりすごい早まっているけど、プラグインのところに関してはあまり前と変わらない。
@sapphi-red 24:37 そうですね、プラグインの部分の処理速度は変わらなくて、ただ、プラグインの処理を減らすために追加されているRolldownの機能を。
@TheoSteiner 25:06 よく覚えてるかどうかわかんないんですけど、例えばMagicStringとかをプラグインの中で使えば、Rolldownが提供するネイティブのMagicString関数とかが増えたりしたみたいな。
@sapphi-red 25:24 そうですね、RolldownはMagicStringの処理を効率よくできるためのAPIを今はexperimentalで提供していて、それを使うとRolldownでJS側の通常のMagicStringを使うよりも確か10%くらい早く処理ができて、それも一つのそういったAPIだし、これは結構アドバンストなもの。もっと多分よく使うんだろうっていうのはplugin hook filterっていうのがあって、これは何かっていうと、まず前提としてRust側からJSを呼ぶっていうのは遅い処理なんですね。なんでかっていうのは、当然そもそもその言語間を超える呼び出しっていうのが遅いっていうのがそもそもあるんですけど、これが遅いっていうのもあるし、JavaScript側は基本的にはシングルスレッドで動いているので並列に呼び出すことができないから、Rust側で例えば8スレッド同時に計算している中、その8スレッドが全てJavaScriptに同時に呼び出した時って、8個の呼び出しが直列に呼び出されざるを得なくて、それでこの前の呼び出しが帰ってくるまで待って呼び出してっていうのを8回繰り返すっていうことでより遅くなるっていう話があって、なので、このRust側からJavaScriptを呼び出すっていうのはできる限り減らしたいんですね。これどうやって減らすかっていうのに、このplugin hook filterっていうのが出てきて、これはプラグインにはhookっていう挙動を変えるために関数でコードを変えたりとか、プラグインのメソッドみたいなのがたくさん提供できて、これを呼び出すためのfilterを指定するっていうのがplugin hook filterなんですけど、正規表現で、例えばあるモジュールにこの文字列が含まれているときだけ呼び出すようにするっていうのが指定できる。このフィルターは元々はなかったですけど、Rolldownには存在してて、これを指定することで、このフィルター自体をRust側で処理して、条件にマッチした場合だけJS側のhookを呼び出す関数を呼び出すっていうことで、このJS側に対しての呼び出しの回数を減らすっていうことができます。そうすると当然JS側の呼び出しのオーバーヘッドを減らすことができて嬉しい。
@TheoSteiner 28:06 そういう風に直接ユーザーには関わらないけど、プラグイン作者にプラグインをより速くするようなAPIが今回結構増えた。
@TheoSteiner 28:16 逆にユーザーが気にしないといけない破壊的変更とかって今回のVite 8のリリースにありましたか? 結構大変そうですか?
@sapphi-red 28:25 7から8に関しては基本的には何もしなくても動くはずで、当然非推奨化とかで警告が出ることはあると思うんですけど、内部の変換レイヤーを実装したので、多くの人はあんまりそもそもコンフィグを変えてないっていうことがあると思うんですけど、仮に変えてたとしても内部的な変換レイヤーで、esbuildのこのオプションはRolldownのこのオプションに値するから内部的にこれをこれに変えておいたよ、とかは設定されているので、おそらくそのまま動くと思ってます。
7. 統合に伴う課題 29:09 @TheoSteiner 29:09 今回バンドラ変わるじゃないですか、RollupからRolldownに変わるんですけど、最終的に出来上がるバンドルってどれぐらい違いますか? これって多分いろいろテストしてて壊れないようにはしてるんですけど、実際に今1ヶ月ぐらい出ててユーザーからのフィードバックはいかがですか? どれくらい違うか、前と挙動が違うんだけどとか、そういうissueって?
@sapphi-red 29:45 結構大きく困ったっていうのは多くはないですね。当然ちょこちょこ細かいケースで違うっていうのはあります。やっぱり一つのツールを別のツールで置き換えるっていうのは言ってしまえば難しくなくて、なんで簡単かって、まあその前の挙動をこうしてれば似たものは作れるっていうのが。ただ、今回のこのViteでの難しいところは、これ2つのものを1つにしてるんですね、っていうことは当然この2つのツールっていうのは差異があって、となると、どっちかに寄せないといけなかったり、両方を組み合わせた結果独自の挙動が生まれるっていうところもあって、なので、そういった点を考えると十分に影響を小さくできたかなと思ってますね。
@TheoSteiner 30:35 なんかその挙動が前とちょっと違うところは、多分CommonJSの解釈、default exportをどうやって解釈するかというところにあると思いますが、そこってどういう挙動になったんですか? さっきもちょっと触れたと。
@sapphi-red 30:52 そうですね、これの原因は多分5、6年前ぐらいのことが原因で。というのも、Node.jsがESMの対応を導入した時、なんで5、6年以上前か、が発端ですね。というのも、Node.jsがESMを導入する前は、人々がESMとCJSを利用してwebpackとかを使ってバンドルして利用してたんですけど、その時は全てのESMのファイルはCJSに変換されてから利用されてた。当然それもそのはずで、そのままESMを実行できる環境がなかったので実行できるCJSに変換して利用してたんですけど、この際にESMをCJSに変換する時に、若干CJSとESMの、ESMでexportされている値のマッピングをする必要があって、1個大きなCJSとESMの大きな違いとしては、動的にexportを生やすことができる、なので例えばif文の中で`exports.pekepeke`を何個入っても何個でも生やすみたいなことができるのに対して、ESMではそれができない、トップレベルのexportしか許されてない、exportをif文の中で書くとかができない。なので、CJSもESMもどっちも複数のexportを持つことができるけど、CJSは動的にできちゃうので、CJSのexportをそのままESMのexportにマッピングするっていうことはできなくて、動的にexportが生やせちゃうからESMのexportの対応するものを作れないところがあって。ただ、バンドラの時代っていうのはこれは問題にならなくて、というのもESMは全てCJSに変換されてたから動的なexportっていうのを扱えちゃってたんですね、全部一緒に落ちちゃう、変換されるので。ただ、Node.jsではESMをESMとして実行するので、CJSからESMから、CJSを読み込む際にnamedなimportでCJSのexportを読み込むっていうのはできないから、そこで何をしたかっていうとCJSのexportは全部defaultのimportにマッピングする、だからdefaultのimportを参照するとCJSのexportが入ったオブジェクトが取れるっていう形にマッピングをすると決めた。ここで2つの解釈の仕方が生まれて、バンドラー上ではCJSに対するdefaultのimportの結果はCJSの中にある`exports.default`っていうこの名前で定義されたexportを参照するに対して、Node.js上ではこのdefaultを参照した時にCJSの全てのexportが入ったオブジェクトを参照するっていう解釈の違いが出て、今も人々が困っているというのが現状としてあります。で、この2つの不整合、解釈の違いを、RollupとesbuildではこれらのRollupとesbuildではこの解釈のやり方が違っていて、Rolldownは大体esbuildと同じような形にすることに決めたんですけど、これはすなわち、開発時に動いているものは大体ビルド時には同じ解釈がされている、されるViteの開発時とVite 8のビルド時、開発時が解釈をして、Vite 7のビルド時とVite 8のビルド時は違う解釈をするっていうのがその影響。
@TheoSteiner 34:50 つまりRolldownをesbuildの解釈に寄せたってことですかね。
@sapphi-red 34:54 そうですね。
8. CommonJS の解釈問題 35:07 @TheoSteiner 35:07 多分今となってそこまでCommonJSが使われる人がいないと言いたいんですが、エンタープライズとかの中だとそううまくはいかないので、それで困ったらどうしたらいいんですかね?
@sapphi-red 35:25 そうなんですよね。これの一番の困ったポイントは、ユーザー側でなんとかするっていうのがちょっと大変っていう点なんですよね。なんでかっていうと、これって各importの部分がどっちの意図で書かれたかっていうのをユーザー側で各importの挙動変換、統合するようなコンフィグを書くっていうのは現実的じゃなくて、かつそんなの書きたくないっていうのがあって。なので、一応ワークアラウンドとしては、問題を先送りにするだけで良いのであれば、一応Vite 8ではフラグを用意してて、そのフラグをつけるとRollupの挙動に寄せた解釈を常にすることができる。ただ、これも当然問題はあって、あくまでもテンポラリーなものだし、最初上げてみて動かなかったら一旦フラグをオンにしてみてこれが原因か見てみるっていうのは使い方が良いと思うんですけど、常に使い続けられるものではないんで、実際にどうするかっていうと、もしそのimportが自分のソースコードの中にあるなら別にその読み込み方を変えれば、つまりimportをdefaultをdefaultじゃなくて`* as`風にするか、importしてあるものをその後に`const foo2 = foo.default`ってすると、当然その違う形での解釈の結果を、ごにょっと変えることができるので、できる。もし依存関係にあった場合は結構困りで、おすすめはmigration guideにこうこうこういう理由でこういう問題があってっていうのをつらつらと僕が書いた説明があるので、それをリンクして一筆添えて、これどうにかできないかなって、issueを立てるのが多分長期的には良くて、短期的なワークアラウンドとしては手元でパッチを当てる形になっちゃいます。
@TheoSteiner 37:25 そうですよね、どっちかというとエコシステムの問題なので、こういう問題にぶつかるたびに声をあげて、that's a common issueでかっていければ解決するんですけど、そこまでの道がまだまだ長いと思いますが、にしても、ここはViteの問題っていうよりJavaScriptの歴史的な問題ですよね、CommonJSとESMっていう互換性のない2つのモジュールシステムができちゃった上の。
@sapphi-red 37:55 そうですね、Vite側でなんとかできたらいいんですけど、どうしても両立することができないんですよね。これは同時に成り立たせるためにはある値がプリミティブであるかつオブジェクトであるっていう条件を満たせないといけないんですけど、そんな値はJavaScriptにないので。
9. Dead Code Elimination 38:20 @TheoSteiner 38:20 それが解釈、前と結構大きく変わったところだと思いますけど、それ以外、Rolldownを導入できてこういうことできるようになりましたとか、そういうのって、エピソードの前の前Discordで話したとき、例えばdead code eliminationについてみどりさんがちょっと話してたんですけど、dead code eliminationって何ですか、そもそも? Rolldown導入できて、これってどういう仕組みで使えますか?
@sapphi-red 38:56 dead code eliminationはRollupにもあるんですけど、端的に言うと、使われてないコードを削除するっていう処理で、例えばexportが3つぐらい関数がexportされてて、その関数の中から参照されてる関数が3つそれぞれあるとしたときに、このうち1個のexportされている関数しか使われてないんだったら、当然そのexportされてるけど使われてない2つの関数が消せるっていうのはできるし、さらにそれらの2つの関数からしか参照されてなかった2つの関数も削除できるので、元々6つあった関数がバンドルの中には2個だけで済むっていうのがdead code eliminationですね。RollupとRolldownだとdead code eliminationはどっちもやってて、Rollupの方が若干アグレッシブに消しますね。なので、普通は踏まないと思うんですけど、稀にdead code eliminationの結果処理が変わることは多分あった。Rolldownは若干安全めに寄っているので、若干それでバンドルが大きくなっているところは多分あるかもしれない。ただ、もっと細かい判定を入れて改善していくつもりはありますね。
@TheoSteiner 40:08 なるほど。じゃあRollupよりちょっと緩和されて、Rollupほどアグレッシブに消さないでより安全なバンドルが手に入る?
@sapphi-red 40:26 そうですね。Rollupのdead code eliminationはかなり優秀なんで、ちょっとだけRolldownに実装されてない部分があるんで、純粋にそれが優秀でRollupの方がアウトプットが小さいという場合も中にはあります。逆にVite 8になってデフォルトのminifierがesbuildからOXCに変わっているんですけど、そこの部分の改善でものによってはVite 8の方が小さくなるというものもあるはずです。なので、小さくなることもあれば稀に大きくなる場合もあるっていう感じですね。
10. OXC とは何か 41:11 @TheoSteiner 41:11 今、minifierがesbuildからOXCに変わったっておっしゃったんですけど、このOXCっていうのは何のことですか? また長くなってきてますね。
@sapphi-red 41:25 OXCはJavaScriptのツールを作るためのライブラリかな、Rustのcrateですかね。
@TheoSteiner 41:35 そうですね、Rustのパッケージで、RolldownとかOxlintとか、そういうプロダクトも内部で使っている。
@sapphi-red 41:41 そうですね。
@TheoSteiner 41:43 それはJavaScriptをAbstract Syntax Treeに変えるためのツールっていう理解でやってますか?
@sapphi-red 41:50 JavaScriptをAbstract Syntax Treeに変換するところもあるし、その解析に使うパッケージとかもわかると内部的にはあったりして、これを使ってさっき言ったminifierだったり、Rolldownの中でもRolldown側にないといけない解析っていうのもあって、例えばクロスモジュールな最適化とかはminifierでは担えないので、というのもminifierは基本的には1個のファイルを受け取って1個のファイルを出力するので、他のファイルの情報を知れないので、それをRolldownでやってたりするんだけど、なので、そのパッケージ群を使って、そのパッケージ群の中にあるminifierが多い。
11. VoidZero のプロダクト群 42:44 @TheoSteiner 42:45 で、なんかちょっと話変わるんですけど、ViteっていうのがOSSなんですけど、そのViteの作者であるEvan Youさんが2年前ぐらいに会社を立ち上げて、その会社がオープンソースコミュニティに大きく貢献してて、例えばOXCの開発だったり、ViteのRolldownの開発だったりと貢献してるんですけど、そのVoidZeroっていう会社にみどりさんも勤めてるんですけど、日本でみどりさんだけ、他に?
@sapphi-red 43:21 いや、実は4人いますね。
@TheoSteiner 43:24 4人? 優秀すぎる日本。で、そのVoidZeroがViteのメンテナンスもしてるんですけど、それ以外どういうプロダクトがありますか?
@sapphi-red 43:32 まずViteから入りますかね。なのでコアチームメンバー何人かいるんですけど、そのうちの僕とVitestにも所属してる2人、名前出すとブラダミアとヒロシさん、Hiroshi Ogawaさんの3人がフルタイムに所属してます。他にもViteじゃないメンバーもいて、Vitestはさっき言ったようにその2人がいて、VitestもVoidZero以外の方が何人かチームにいるのかな。次に進むと、さっき言ったRolldownは人数が結構いるんだけど、VoidZeroの方が多いので主に作っていて。OXCはさっき言った基盤的なもので、主にVoidZeroに所属している人とプラスアルファで、確かコントリビューターの方がいて。OXCの方はもうちょっと触れておくと、Parser、minifier以外にもRolldownでも使われているTransformer、TypeScriptをJavaScriptにするだったり、JavaScriptの新しい構文を古い構文にするっていう部分があったり、あとはOxlint、OxfmtっていうFormatterもこのOXCの。ここまでいったものを、あともう1個言っていいの? あと、tsdownっていうRolldownの上に作られたライブラリ用のバンドラがあって、これはtsupの後継。これでここまでいったものを全部1個のものに入れて使いやすくするっていうプロジェクトがあって、これがvite+っていうものがあって、これもVoidZeroに所属してる人が中心で。
@TheoSteiner 45:19 OSSだとそんなもの? vite+っていうの、僕実は先週初めて使ってみたんですけど、最近になってMITのライセンスに変わったんですよね。もともとちょっと別のビジネスモデルだったんですけど、最近になってMITライセンスに変わったので、こういうエンタープライズの環境でも気軽に導入できるようになったんですけど、これまでにTurborepoとかを使ってきたんですけど、vite+がVite関連のツールを全部いい感じにラッピングしてるのが本当に使いやすいなと思ってて、ちょっと触ってみたんですけど、まだアルファ段階ですが、これから結構期待できるプロダクト。
12. vite+ が MIT ライセンスへ 45:23 @sapphi-red 46:10 Nodeの25からCorepackが入らなくなる話があるんですけど、なんで、何にせよそのパッケージマネージャーをどうするという問題があると思う。なんでまだ実装されてないし、特に実装されるかと聞いてないんですけど、vite+は多分パッケージマネージャーマネージャーは多分やる気がしてるんで、その時にCorepackの代わりに使ったりとか。
@TheoSteiner 46:34 そうですよ、ちょうどいいかなって。Nodeバージョンとかを管理するためのツールがもう多すぎて、nvmもあればVoltaとかそういったツールもあるんですよね。最近になってpnpmでもNodeのバージョンを管理するようになったし、それいい感じに統合するとユーザーとして結構嬉しい分野なんじゃないかなと。
13. void.cloud 47:05 @TheoSteiner 47:05 で、そういったオープンソースのプロダクト以外にも、最近になってクラウドのものが発表されたんですけど、まだそれもかなり早い段階、まだ発表したくらい。それもなんか面白そうですね、Viteのどうやって使われているかを分析して、それを元にいい感じにインフラを提供するようなプロダクトになるんですか? 話せる範囲で。
@sapphi-red 47:40 気持ちとしてはあんまり意識しなくていいっていうのが多分一番コアにあると、インフラがあるっていうことを意識しなくていい、it just works。そうですね、ボタンを押しといたらインフラがあるな、っていうくらいのものを目指して。
@TheoSteiner 48:00 すごい理想的なアイデアだな。
14. Lightning CSS 48:04 @TheoSteiner 48:04 Vite 8のリリースノート読んだら、Lightning CSSか、新しくなんか、前も入ってた気がするんですけど、なんかピースとして増えるみたいな話を読んでたんですけど、そのLightning CSSが導入される背景って軽く触れてもらってもいいですか?
@sapphi-red 48:23 そうですね。Vite 7はCSSのminifyをesbuildを使ってたんですけど、ただ今回esbuildはJS側で使われなくなるんで、なので、CSSのminifyのデフォルトをLightning CSSにしようっていうことで、オプショナルだったのが必須のディペンデンシーに変わりました。
@TheoSteiner 48:41 なるほど、割とシンプルな背景だったんですね。esbuildからOXCっていう。なんか本当に色々知れて、僕も知らないトピックとかいっぱい触れたので、本当に来てくださってありがとうございます。
15. クロージング 49:01 @TheoSteiner 49:01 というわけで、今回はみどりさんと話してきました。LINEヤフーのフロントエンドコミュニティUITではこのようなフロントエンドに関わる議論や意見交換を日々行っています。過去のエピソードでは社内勉強会などから発生したものも多くあります。今後も積極的に情報を発信していきたいと思います。また、このポッドキャストに関するご意見、ご感想があれば、ハッシュタグ #UIT_INSIDE にてつぶやいていただけるとスタッフで確認いたします。ありがとうございました。
@sapphi-red 49:32 ありがとうございました。