Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

Demystifying Vite Internals

Nozomu Ikuta
October 19, 2024

Demystifying Vite Internals

Slides for Vue Fes Japan 2024

Nozomu Ikuta

October 19, 2024
Tweet

More Decks by Nozomu Ikuta

Other Decks in Technology

Transcript

  1. How Vite dev server is bootstrapped How Vite config is

    resolved How Vite handles HTTP requests How Vite plugins are made available in dev mode How Vite manages caches How Vite manages HMR How Vite builds application etc. Introduction Topics
  2. How Vite dev server is bootstrapped How Vite config is

    resolved How Vite handles HTTP requests How Vite plugins are made available in dev mode How Vite manages caches How Vite manages HMR How Vite builds application etc. Introduction Topics
  3. Dev Server Bootstrap Overview • Initialization • Con fi g

    resolution • Connect server setup • Dependency pre-bundling • Starting connect server
  4. await createServer(inlineCon fi g) • Run Vite CLI or call

    exported function directly • These options are called inline con fi g in terms of con fi g resolution Vite CLI JavaScript API Pass 
 CLI options Call with options Dev Server Bootstrap Initialization
  5. loadCon fi gFromFile() Disk Dev Server Bootstrap Con fi g

    Resolution • Build user con fi g fi le by esbuild vite.con fi g.ts other.ts build() import .env
  6. loadCon fi gFromFile() Disk Dev Server Bootstrap Con fi g

    Resolution • Build user con fi g fi le by esbuild • Write the code to disk vite.con fi other.ts build() writeFile() import temporal fi le .env
  7. loadCon fi gFromFile() Disk Dev Server Bootstrap Con fi g

    Resolution • Build user con fi g fi le by esbuild • Write the code to disk and then import the fi le vite.con fi temporal fi le other.ts build() writeFile() import() import .env
  8. loadCon fi gFromFile() Disk Dev Server Bootstrap Con fi g

    Resolution • Build user con fi g fi le by esbuild • Write the code to disk and then import the fi le and delete it vite.con fi temporal fi le other.ts build() writeFile() import() unlink() import .env
  9. loadCon fi gFromFile() Disk Dev Server Bootstrap Con fi g

    Resolution • Build user con fi g fi le by esbuild • Write the code to disk and then import the fi le • Merge inline con fi g and user con fi g vite.con fi temporal fi other.ts build() writeFile() import() unlink() mergeCon fi g(userCon fi g, inlineCon fi g) import .env
  10. loadCon fi Disk Dev Server Bootstrap Con fi g Resolution

    • Build user con fi g fi le by esbuild • Write the code to disk and then import the fi le • Merge inline con fi g and user con fi g • Resolve user plugins vite.con fi temporal fi other.ts build() writeFile() import() unlink() mergeCon fi import fl atten / sort user plugins .env
  11. loadCon fi Disk Dev Server Bootstrap Con fi g Resolution

    • Build user con fi g fi le by esbuild • Write the code to disk and then import the fi le • Merge inline con fi g and user con fi g • Resolve user plugins • Load .env fi le vite.con fi temporal fi other.ts build() writeFile() import() unlink() mergeCon fi import fl loadEnv() .env
  12. Dev Server Bootstrap Connect Server Setup • timeMiddleware • corsMiddleware

    • cachedTransformMiddleware • proxyMiddleware • baseMiddleware • launchEditorMiddleware • viteHMRPringMiddleware • servePublicMiddleware • transformMiddleware • serveRawFsMiddleware • serveStaticMiddleware • htmlFallbackMiddleware • indexHtmlMiddleware • notFoundMiddleware • errorMiddleware
  13. Dev Server Bootstrap Connect Server Setup • timeMiddleware • corsMiddleware

    • cachedTransformMiddleware • proxyMiddleware • baseMiddleware • launchEditorMiddleware • viteHMRPringMiddleware • servePublicMiddleware • transformMiddleware • serveRawFsMiddleware • serveStaticMiddleware • htmlFallbackMiddleware • indexHtmlMiddleware • notFoundMiddleware • errorMiddleware
  14. Dev Server Bootstrap Dependency Pre-Bundling • Dependencies in node_modules are

    transformed by esbuild as ESM • The results are cached • type=“module” is written in package.json for deps to be recognized as ESM Deps- Optimizer Disk node_modules dep A .vite/deps package.json dep B dep C _metadata.json dep A’ dep B’ dep C’
  15. • Vite con fi g is built by esbuild •

    Dependencies are built by esbuild and stored as cache • No application build on dev server bootstrap
  16. indexHtml- Middleware GET /index.html Requesting index.html indexHtmlMiddleware • Replace environment

    variable placeholders with values • Transform other parts of index.html for performance (out of scope) Disk index.html Browser readFile() transform() send() index.html
  17. Requesting JS Files Native ESM Module Resolution • JavaScript fi

    les are requested according to src attribute • What to be returned from the URL depends on the server • This is the starting point of partial application build Browser GET index.html <script type=“module” src=“…”></script> Vite dev server
  18. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> index.ts a.ts GET

    /src/main.ts Vite Dev Server transformMiddleware import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) }
  19. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> index.ts a.ts Vite

    Dev Server transformMiddleware import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) } GET /src/main.ts
  20. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> index.ts a.ts Vite

    Dev Server transformMiddleware import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) } import A from ‘/src/a.ts’ function fn() { console.log(‘Hi’) } GET /src/index.ts
  21. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> Vite Dev Server

    transformMiddleware import A from ‘/src/a.ts’ function fn() { console.log(‘Hi’) } import A from ‘/src/a.ts’ index.ts a.ts import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) }
  22. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> Vite Dev Server

    transformMiddleware import A from ‘/src/a.ts’ function fn() { console.log(‘Hi’) } import A from ‘/src/a.ts’ GET /src/a.ts index.ts a.ts import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) }
  23. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> Vite Dev Server

    transformMiddleware import A from ‘/src/a.ts’ function fn() { console.log(‘Hi’) } import A from ‘/src/a.ts’ GET /src/a.ts index.ts a.ts import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) }
  24. Browser Disk src <script type=“module” src=“/src/main.ts” ></script> Vite Dev Server

    transformMiddleware import A from ‘/src/a’ function fn() { console.log(‘Hi’) } import A from ‘/src/a’ GET /src/a.ts Runnable JavaScript Code index.ts a.ts import A from ‘./a’ type MyType = true function fn(): void { console.log(‘Hi’) }
  25. • File contents are transformed by plugins • Vite does

    not build your application with Rollup
  26. Plugin System Vite vs. Rollup • Vite plugins extends Rollup's

    plugin interface • Most Rollup plugin can be used as Vite plugins: • if It doesn’t use moduleParsed hook • if it doesn't have strong coupling between bundle- phase hooks and output-phase hooks Rollup Plugins Vite Plugins https://vite.dev/guide/api-plugin.html
  27. Plugin C Plugin Container resolveId Hook • resolveId hook of

    plugins are called sequentially • First non-nullable result is used as module ID Plugin A resolveId() Plugin Container resolveId() Returns null Returns string Plugin B
  28. Plugin Container load Hook • load hook of plugins are

    called sequentially • First non-nullable result is used as source code Plugin C Plugin A load() Plugin Container load() Returns null Returns string Plugin B
  29. Plugin Container transform Hook • transform hook of plugins are

    called sequentially • Final result is used as actual code Plugin C Plugin A transform() Plugin Container Returns A Plugin B transform() Returns B
  30. • Vite makes up JavaScript code runnable in browser through

    3 plugin hooks • Vite provides some built-in plugins • TypeScript is transpiled by esbuild
  31. • Vite con fi g is built by esbuild •

    Dependencies are built by esbuild and stored as cache on dev server bootstrap • Vite does not build your application on dev server bootstrap, which is why it starts fast • index.html is the starting point from which your application is built • Plugin container makes it possible to partially build your application on demand
  32. Acknowledgements Vite Study Members • aki • Jabelic • Jumpei

    Yamada • keigo • shoma mano • taka • ubugeeei • Yuma • ͍ͪΉΒ Ώ͏· • ͓ʔ͍͐͡ • ͔Β͜Ζ • πϊ In alphabetical order