Open5
viteでvanilla-extractを使ったプロジェクトをビルドする時に何が行われているのか
混乱してきたので調べる。vanilla-extractのvite pluginの実装はここ
公式ドキュメント
内部的には、css.tsファイルからスタイルを抽出するため、esbuildによってcss.tsファイルがコンパイルされているらしい。
ミニマムのvite + vanilla-extract環境を作って動作を試す。
production build
- jsとcssファイルが生成される。cssの中には、vanilla-extractで定義したスタイルが入っている。クラス名はランダム文字列。jsの中では、そのクラス名のついた要素がrenderingされる。
- htmlにはjsとcssのタグが埋め込まれる。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
<script type="module" crossorigin src="/assets/index-42e9029d.js"></script>
<link rel="stylesheet" href="/assets/index-06480e79.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
dev server
- 以下のような感じで、vanilla-extractで定義したスタイルは直接styleタグで直接HTMLに書き込まれる。
<html lang="en"><script type="text/javascript" src="chrome-extension://mdnleldcmiljblolnjhpnblkcekpdkpa/libs/customElements.js" class="__REQUESTLY__SCRIPT"></script><head>
<script type="module">import { injectIntoGlobalHook } from "/@react-refresh";
injectIntoGlobalHook(window);
window.$RefreshReg$ = () => {};
window.$RefreshSig$ = () => (type) => type;</script>
<script type="module" src="/@vite/client"></script>
<meta charset="UTF-8">
<link rel="icon" type="image/svg+xml" href="/vite.svg">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite + React</title>
<style data-file="/Users/nariyuki.saito/study/vanilla-extract-vite-test/src/App.css.js.vanilla.js" type="text/css">.App_container__1rtl69e0 {
padding: 10px;
background: red;
}</style></head>
<body>
<div id="root"><div class="App_container__1rtl69e0"></div></div>
<script type="module" src="/src/main.jsx?t=1692701817621"></script>
</body></html>
vanilla-extractのvite pluginコードの理解のためには、viteのplugin APIを理解した方が良さそう。
devサーバの時に、htmlにstyleタグ入れる作業は下記でやっている。
productionビルドの際は、特にhtmlにlinkタグを入れる作業をやってるようなコードはなかった。おそらくvite側でやってると思われる。
そもそもviteがどんな処理をするのか。(主にdev serverの処理)
-
import { someMethod } from 'my-dep'
みたいなnpmでインストールしたdependencyを解決する。具体的にはインポート先のURLが/node_modules/.vite/deps/my-dep.js?v=f3sf2ebd
みたいに書き換わる。 - typescriptはtranspileしかしない
- jsxのトランスパイル
- js側で.cssファイルをインポートしているときに、そのスタイルを<style>タグでページに挿入する
- postcss
- .module.cssの処理
-
import imgUrl from './img.png'
みたいな画像読み込みのインポートを解決 - jsonのインポートを解決
- dynamic import
- wasmのインポートを解決
- ビルドの最適化 (cssファイルをいい感じに自動的に分割し、linkタグで挿入してくれる。プリロード付き)
- jsが複数chunkに分かれているときに、そのpreloadを賢く行なってウォーターフォールを減らす