Skip to content
Created: July 24, 2024

🎯 Overall goal ​

Understand what is going on inside the Vite development server (Dev Server)?Why fast?

There are three core issues of concern:

  1. What happens at startup?
  2. How does Vite handle when the browser requests a file?
  3. What is the HMR (hot update) workflow?

🧱 1. Overview of the core architecture of Vite Dev Server ​

The Vite development server essentially consists of three parts:

          ┌──────────────────────────┐
          │          Vite            │
          │     (开发服务器)        │
          └──────────────────────────┘
              │        │          │
              ▼        ▼          ▼
      File Resolver    Transforms (Plugin Pipeline)
         (路径解析)      (插件转换:ts/vue/jsx/css等)

              │
              ▼
      Native ESM Server
  (用浏览器原生 ES Modules 提供模块)

The two most critical points of the development environment:

✔ No-Bundle development (not packaged) ​

✔ HMR Server (ultra-fast hot update) ​

🚀 2. Vite development server startup process ​

When you run:

npm run dev

Its core process:

🔸 Step 1: Parse configuration ​

vite.config.ts → Load plugin → Parse plugin hook → Merge default configuration.

🔸 Step 2: Build plugin container (plugin container) ​

The plug-in container is implemented by Vite and is used to execute Rollup-style plug-ins:

  • resolveId()
  • load()
  • transform()

All files are processed through this "plugin pipeline".

🔸 Step 3: Start a Connect middleware server ​

Vite implements a middleware server based on connect (similar to Express):

const server = connect()

Then register various middleware:

  • Handle static resources
  • Handling HMR WebSockets
  • Processing module analysis
  • Handle transform
  • Handling Vue compilation
  • Process TS to JS
  • Working with CSS/PostCSS

🔸 Step 4: Start WebSocket (for HMR) ​

HMR pushes updates via WebSocket:

ws.send(JSON.stringify({
  type: "update",
  path: "...",
  timestamp: ...
}))

After receiving it, the HMR client in the browser will execute:

  • reload component
  • refresh css
  • update module graph

🔸 Step 5: Print server address ​

Local: http://localhost:5173/

At this point, the Vite Dev Server has been started.

🔥 3. How does Vite work when the browser accesses the page? ​

When the browser accesses:

/src/main.ts

Vite does not return this file directly from disk. It will be processed through the plugin pipeline and returned.

The process is as follows:

📌 Step 1: Path resolution (resolveId) ​

For example:

ts
import { createApp } from 'vue'

The browser will request:

/node_modules/.vite/deps/vue.js?v=xxxx

Vite's resolver is responsible for:

  • Change the bare module name 'vue' into the actual path
  • "Dependency pre-building" (optimization) for third-party dependencies
  • Caching parsing results

📌 Step 2: transform (plug-in processing) ​

Each file goes through the complete plugin chain:

source → load() → transform() → transformIndexHtml() → 返回浏览器

For example:

  • TS → JS(esbuild)
  • Vue → JS(@vitejs/plugin-vue)
  • JSX → JS
  • CSS → JS module
  • PostCSS → Transform
  • Automatic dependency pre-building
  • Auto import plug-in
  • your custom transform plugin

Eventually everything becomes a native ESM JS module and returned to the browser.

📌 Step 3: Return ESM response ​

The returned JS module is with ESM import:

js
import { createApp } from "/node_modules/.vite/deps/vue.js?v=xxxx"

The browser initiates a new request again, and Vite parses, converts, and returns again.

This is why Vite does not need to package all modules at once.

⚡ 4. Why is the Vite development server extremely fast? ​

Reason = No bundle + ESM file loaded on demand.

⭐ Reason 1: Browsers support ESM, Vite is just a “router” ​

Vite does not need to be packed in advance.The browser will load the module only when it parses the import.

This means:

  • Startup time independent of project size
  • Cold start is almost instantaneous

Webpack requires:

构建依赖图 → 打包所有模块 → 输出 bundle

⭐ Reason 2: Use esbuild to do dependency pre-building (100 times faster) ​

Third-party dependencies (Vue, React, Lodash) are pre-built into ESM using esbuild, which is extremely fast.

The loading speed of imported modules is greatly improved.

⭐ Reason 3: Files are only converted and cached on the first request ​

Vite has strong caching internally:

if cache exists → return transformed result
else transform → cache → return

🔥 5. Vite HMR (hot update) core mechanism ​

This is the true heart of Vite Fast.

The process is as follows:

📌 Step 1: Watch files (fs watcher) ​

Vite uses chokidar to monitor file changes:

chokidar.watch(root)

📌 Step 2: Update module graph (Module Graph) ​

Each file will be recorded in ModuleGraph:

  • importers (who uses it)
  • imported modules (who it uses)
  • Dependencies

File changes → ModuleGraph updated.

📌 Step 3: Trigger the plug-in’s handleHotUpdate() ​

Each plugin determines:

  • Which modules require HMR
  • Return to the updated section

For example Vue plugin:

ts
handleHotUpdate(ctx) {
  if (file ends with .vue) {
    return [template part, script part]
  }
}

📌 Step 4: Vite pushes updates to the browser (WebSocket) ​

json
{
  "type": "update",
  "path": "/src/App.vue",
  "timestamp": 1234567
}

📌 Step 5: Execute HMR on the browser side ​

Vite comes with its own client module:

@vite/client

Handle various types of HMR:

  • Vue: hot update components without refreshing the page
  • React:react-refresh
  • CSS: Replace tag
  • JS: replace module
  • Full-reload: Refresh the page as a whole (only when it cannot be updated accurately)

🧠 6. Dev Server core code structure (source code perspective) ​

Exploding dry goods area ↓

Vite Dev Server code location:

packages/vite/src/node/server/index.ts
packages/vite/src/node/server/middlewares/
packages/vite/src/node/server/hmr.ts
packages/vite/src/node/server/moduleGraph.ts

The core modules:

✔ createServer() ​

Start the entire development server

✔ moduleGraph ​

Manage module dependencies

✔ pluginContainer ​

Run rollup style transform/load/resolve plugin

✔ middlewares ​

Process requests in order, such as:

  • transformMiddleware
  • serveStaticMiddleware
  • indexHtmlMiddleware
  • hmrMiddleware

🎉 7. A picture summarizing the core principles of Vite Dev Server ​

              Browser
                 │
                 ▼  (ESM import)
       HTTP Request /src/main.ts
                 │
                 ▼
     ┌────────────────────────┐
     │     Vite Dev Server    │
     ├────────────────────────┤
     │  1. Resolve (插件)     │
     │  2. Load (插件)        │
     │  3. Transform (插件链) │
     │  4. Return ESM code    │
     ├────────────────────────┤
     │ Cache / ModuleGraph    │
     └────────────────────────┘
                 │
                 ▼
      Browser executes ESM
                 │
          File change
                 │
                 ▼
      Vite detects change
                 │
        push HMR update
                 │
                 ▼
       Browser reload module

You now have a complete understanding of Vite Dev Server.