The Module Graph is a core data structure in Vite's development server that tracks the relationships between modules, their metadata, and their transformation state. In Vite 8, each environment (client, SSR, or custom) maintains its own isolated EnvironmentModuleGraph that maps URLs to EnvironmentModuleNode instances, tracks import relationships, and manages Hot Module Replacement (HMR) state.
For information about the transform pipeline that populates the module graph, see Transform Pipeline (4.3). For HMR propagation that uses the module graph, see Server-Side HMR (5.1).
Sources: packages/vite/src/node/server/index.ts97-98 packages/vite/src/node/server/environment.ts62-64 packages/vite/src/node/server/moduleGraph.ts14-36
Each DevEnvironment instance owns an EnvironmentModuleGraph that provides methods for module lookup, invalidation, and dependency tracking. The graph is environment-specific to ensure proper isolation between client and SSR builds.
The module graph maintains multiple indexed maps for efficient lookups:
| Map | Key | Value | Purpose |
|---|---|---|---|
urlToModuleMap | URL string | EnvironmentModuleNode | Fast lookup by request URL (with query). packages/vite/src/node/server/moduleGraph.ts93 |
idToModuleMap | Module ID | EnvironmentModuleNode | Lookup by resolved absolute file path. packages/vite/src/node/server/moduleGraph.ts94 |
fileToModulesMap | File path | Set<EnvironmentModuleNode> | Maps a file system path to all associated nodes (e.g. same file with different queries). packages/vite/src/node/server/moduleGraph.ts97 |
etagToModuleMap | ETag string | EnvironmentModuleNode | Supports browser caching via If-None-Match headers. packages/vite/src/node/server/moduleGraph.ts95 |
Sources: packages/vite/src/node/server/moduleGraph.ts90-98 packages/vite/src/node/server/middlewares/transform.ts91-94
Each EnvironmentModuleNode represents a single module in the graph with its transformation state, dependencies, and HMR metadata.
| Property | Type | Description |
|---|---|---|
url | string | Public served url path, starts with /. packages/vite/src/node/server/moduleGraph.ts19 |
id | string | null | Resolved file system path + query. packages/vite/src/node/server/moduleGraph.ts23 |
file | string | null | Resolved file system path without query. packages/vite/src/node/server/moduleGraph.ts24 |
importers | Set<EnvironmentModuleNode> | Modules that import this module. packages/vite/src/node/server/moduleGraph.ts28 |
importedModules | Set<EnvironmentModuleNode> | Modules imported by this module. packages/vite/src/node/server/moduleGraph.ts30 |
transformResult | TransformResult | null | Cached transformation result (code, map, etag). packages/vite/src/node/server/moduleGraph.ts36 |
lastInvalidationTimestamp | number | Timestamp used to compare against pending requests. packages/vite/src/node/server/moduleGraph.ts51 |
isSelfAccepting | boolean | Whether module accepts its own updates. packages/vite/src/node/server/moduleGraph.ts35 |
invalidationState | TransformResult | 'HARD_INVALIDATED' | Tracks soft vs hard invalidation status. packages/vite/src/node/server/moduleGraph.ts62 |
Sources: packages/vite/src/node/server/moduleGraph.ts14-82 packages/vite/src/node/server/transformRequest.ts106-127
Sources: packages/vite/src/node/server/middlewares/transform.ts80-109 packages/vite/src/node/server/moduleGraph.ts123-135 packages/vite/src/node/server/transformRequest.ts78-207
The module graph tracks both static and dynamic import relationships to support HMR propagation and circular dependency detection.
Import relationships are populated during the transformation phase. In Vite 8, the EnvironmentPluginContainer manages the lifecycle of these relationships:
EnvironmentModuleNode with the latest imported modules. packages/vite/src/node/server/pluginContainer.ts182-185transformResult for the next request. packages/vite/src/node/server/moduleGraph.ts57-62Sources: packages/vite/src/node/server/pluginContainer.ts175-224 packages/vite/src/node/server/moduleGraph.ts166-210
When a file changes, the EnvironmentModuleGraph handles recursive invalidation.
Sources: packages/vite/src/node/server/moduleGraph.ts145-154 packages/vite/src/node/server/moduleGraph.ts166-210
Vite uses the module graph to implement two layers of caching:
transformResult on EnvironmentModuleNode avoids re-running the plugin pipeline if the module is not invalidated. packages/vite/src/node/server/moduleGraph.ts36etag in the transformResult allows the server to respond with 304 Not Modified via the cachedTransformMiddleware. packages/vite/src/node/server/middlewares/transform.ts89-106Sources: packages/vite/src/node/server/middlewares/transform.ts76-110 packages/vite/src/node/server/moduleGraph.ts205-206
For backward compatibility with legacy plugins, Vite 8 maintains a ModuleGraph class (imported from ./mixedModuleGraph) that can represent a combined view of modules across environments, though modern Vite 8 logic primarily uses the per-environment EnvironmentModuleGraph.
Sources: packages/vite/src/node/server/index.ts97-98 packages/vite/src/node/server/moduleGraph.ts14-15
Refresh this wiki