Open5

viteでvanilla-extractを使ったプロジェクトをビルドする時に何が行われているのか

nakaakistnakaakist

ミニマムのvite + vanilla-extract環境を作って動作を試す。

https://github.com/nakaakist/vanilla-extract-vite-test

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>
nakaakistnakaakist

vanilla-extractのvite pluginコードの理解のためには、viteのplugin APIを理解した方が良さそう。

https://vitejs.dev/guide/api-plugin.html

devサーバの時に、htmlにstyleタグ入れる作業は下記でやっている。
https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/vite-plugin/src/index.ts/#L55-L56
https://github.com/vanilla-extract-css/vanilla-extract/blob/master/packages/css/src/injectStyles.ts

productionビルドの際は、特にhtmlにlinkタグを入れる作業をやってるようなコードはなかった。おそらくvite側でやってると思われる。

nakaakistnakaakist

そもそもviteがどんな処理をするのか。(主にdev serverの処理)

https://vitejs.dev/guide/features.html

  1. import { someMethod } from 'my-dep'みたいなnpmでインストールしたdependencyを解決する。具体的にはインポート先のURLが/node_modules/.vite/deps/my-dep.js?v=f3sf2ebdみたいに書き換わる。
  2. typescriptはtranspileしかしない
  3. jsxのトランスパイル
  4. js側で.cssファイルをインポートしているときに、そのスタイルを<style>タグでページに挿入する
  5. postcss
  6. .module.cssの処理
  7. import imgUrl from './img.png'みたいな画像読み込みのインポートを解決
  8. jsonのインポートを解決
  9. dynamic import
  10. wasmのインポートを解決
  11. ビルドの最適化 (cssファイルをいい感じに自動的に分割し、linkタグで挿入してくれる。プリロード付き)
  12. jsが複数chunkに分かれているときに、そのpreloadを賢く行なってウォーターフォールを減らす