Skip to content

Commit 80f53db

Browse files
committed
feat: add build moduleGraph
1 parent 9c7f704 commit 80f53db

File tree

4 files changed

+256
-7
lines changed

4 files changed

+256
-7
lines changed

packages/vite/src/node/build.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ import type { RollupPluginHooks } from './typeUtils'
9393
import { buildOxcPlugin } from './plugins/oxc'
9494
import type { ViteDevServer } from './server'
9595
import { getHmrImplement } from './plugins/clientInjections'
96+
import { buildModuleGraphPlugin } from './server/buildModuleGraph'
9697

9798
export interface BuildEnvironmentOptions {
9899
/**
@@ -648,6 +649,10 @@ async function buildEnvironment(
648649
injectEnvironmentToHooks(environment, chunkMetadataMap, p),
649650
)
650651

652+
if (server) {
653+
plugins.push(buildModuleGraphPlugin(server))
654+
}
655+
651656
const rollupOptions: RolldownOptions = {
652657
// preserveEntrySignatures: ssr
653658
// ? 'allow-extension'
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import type { ModuleInfo } from 'rolldown'
2+
import type { ViteDevServer } from "..";
3+
import type { Plugin } from '../plugin'
4+
import { cleanUrl } from "../../shared/utils";
5+
import type { TransformResult } from './transformRequest'
6+
import type { EnvironmentModuleNode, ResolvedUrl } from "./moduleGraph"
7+
8+
export class BuildModuleNode {
9+
_id: string
10+
_file: string
11+
_importers = new Set<BuildModuleNode>
12+
constructor(id: string, file: string) {
13+
this._id = id
14+
this._file = file
15+
}
16+
17+
// TODO using id also could be work
18+
get url(): string {
19+
return this._id
20+
}
21+
set url(_value: string) {
22+
throw new Error("BuildModuleNode set url is not support");
23+
}
24+
25+
get id(): string | null {
26+
return this._id
27+
}
28+
set id(_value: string | null) {
29+
throw new Error("BuildModuleNode set id is not support");
30+
}
31+
get file(): string | null {
32+
return this._file
33+
}
34+
set file(_value: string | null) {
35+
throw new Error("BuildModuleNode set file is not support");
36+
}
37+
// eslint-disable-next-line @typescript-eslint/class-literal-property-style
38+
get type(): 'js' | 'css' {
39+
return 'js'
40+
}
41+
// `info` needs special care as it's defined as a proxy in `pluginContainer`,
42+
// so we also merge it as a proxy too
43+
get info(): ModuleInfo | undefined {
44+
throw new Error("BuildModuleNode get info is not support");
45+
}
46+
get meta(): Record<string, any> | undefined {
47+
throw new Error("BuildModuleNode get meta is not support");
48+
}
49+
get importers(): Set<BuildModuleNode> {
50+
throw this._importers;
51+
}
52+
set importers(importers: Set<BuildModuleNode>) {
53+
this._importers = importers;
54+
}
55+
get clientImportedModules(): Set<BuildModuleNode> {
56+
throw new Error("BuildModuleNode get clientImportedModules is not support");
57+
}
58+
get ssrImportedModules(): Set<BuildModuleNode> {
59+
throw new Error("BuildModuleNode get ssrImportedModules is not support");
60+
}
61+
get importedModules(): Set<BuildModuleNode> {
62+
throw new Error("BuildModuleNode get importedModules is not support");
63+
}
64+
get acceptedHmrDeps(): Set<BuildModuleNode> {
65+
throw new Error("BuildModuleNode get acceptedHmrDeps is not support");
66+
}
67+
get acceptedHmrExports(): Set<string> | null {
68+
throw new Error("BuildModuleNode get acceptedHmrExports is not support");
69+
}
70+
get importedBindings(): Map<string, Set<string>> | null {
71+
throw new Error("BuildModuleNode get importedBindings is not support");
72+
}
73+
get isSelfAccepting(): boolean | undefined {
74+
throw new Error("BuildModuleNode get isSelfAccepting is not support");
75+
}
76+
get transformResult(): TransformResult | null {
77+
throw new Error("BuildModuleNode get transformResult is not support");
78+
}
79+
set transformResult(_value: TransformResult | null) {
80+
throw new Error("BuildModuleNode set transformResult is not support");
81+
}
82+
get ssrTransformResult(): TransformResult | null {
83+
throw new Error("BuildModuleNode get ssrTransformResult is not support");
84+
}
85+
set ssrTransformResult(_value: TransformResult | null) {
86+
throw new Error("BuildModuleNode set ssrTransformResult is not support");
87+
}
88+
get ssrModule(): Record<string, any> | null {
89+
throw new Error("BuildModuleNode get ssrModule is not support");
90+
}
91+
get ssrError(): Error | null {
92+
throw new Error("BuildModuleNode get ssrError is not support");
93+
}
94+
get lastHMRTimestamp(): number {
95+
throw new Error("BuildModuleNode get lastHMRTimestamp is not support");
96+
}
97+
set lastHMRTimestamp(_value: number) {
98+
throw new Error("BuildModuleNode set lastHMRTimestamp is not support");
99+
}
100+
get lastInvalidationTimestamp(): number {
101+
throw new Error("BuildModuleNode get lastInvalidationTimestamp is not support");
102+
}
103+
get invalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined {
104+
throw new Error("BuildModuleNode get invalidationState is not support");
105+
}
106+
get ssrInvalidationState(): TransformResult | 'HARD_INVALIDATED' | undefined {
107+
throw new Error("BuildModuleNode get ssrInvalidationState is not support");
108+
}
109+
}
110+
111+
112+
export class BuildModuleGraph {
113+
idToModuleMap = new Map<string, BuildModuleNode>()
114+
fileToModulesMap = new Map<string, Set<BuildModuleNode>>()
115+
116+
// eslint-disable-next-line @typescript-eslint/no-empty-function
117+
constructor() {}
118+
119+
getModuleById(id: string): BuildModuleNode | undefined {
120+
return this.idToModuleMap.get(id);
121+
}
122+
123+
async getModuleByUrl(
124+
_url: string,
125+
_ssr?: boolean,
126+
): Promise<BuildModuleNode | undefined> {
127+
throw new Error("BuildModuleGraph getModuleByUrl is not support");
128+
}
129+
130+
getModulesByFile(file: string): Set<BuildModuleNode> | undefined {
131+
return this.fileToModulesMap.get(file);
132+
}
133+
134+
onFileChange(_file: string): void {
135+
throw new Error("BuildModuleGraph onFileChange is not support");
136+
}
137+
138+
onFileDelete(_file: string): void {
139+
throw new Error("BuildModuleGraph onFileDelete is not support");
140+
}
141+
142+
143+
invalidateModule(
144+
_mod: BuildModuleNode,
145+
_seen = new Set<BuildModuleNode>(),
146+
_timestamp: number = Date.now(),
147+
_isHmr: boolean = false,
148+
/** @internal */
149+
_softInvalidate = false,
150+
): void {
151+
throw new Error("BuildModuleGraph invalidateModule is not support");
152+
}
153+
154+
invalidateAll(): void {
155+
throw new Error("BuildModuleGraph invalidateAll is not support");
156+
}
157+
158+
159+
async ensureEntryFromUrl(
160+
_rawUrl: string,
161+
_ssr?: boolean,
162+
_setIsSelfAccepting = true,
163+
): Promise<BuildModuleNode> {
164+
throw new Error("BuildModuleGraph invalidateAll is not support");
165+
}
166+
167+
createFileOnlyEntry(_file: string): BuildModuleNode {
168+
throw new Error("BuildModuleGraph createFileOnlyEntry is not support");
169+
}
170+
171+
async resolveUrl(_url: string, _ssr?: boolean): Promise<ResolvedUrl> {
172+
throw new Error("BuildModuleGraph resolveUrl is not support");
173+
}
174+
175+
updateModuleTransformResult(
176+
_mod: BuildModuleNode,
177+
_result: TransformResult | null,
178+
_ssr?: boolean,
179+
): void {
180+
throw new Error("BuildModuleGraph updateModuleTransformResult is not support");
181+
}
182+
183+
getModuleByEtag(_etag: string): BuildModuleNode | undefined {
184+
throw new Error("BuildModuleGraph getModuleByEtag is not support");
185+
}
186+
187+
getBackwardCompatibleBrowserModuleNode(
188+
_clientModule: EnvironmentModuleNode,
189+
): BuildModuleNode {
190+
throw new Error("BuildModuleGraph getBackwardCompatibleBrowserModuleNode is not support");
191+
}
192+
193+
getBackwardCompatibleServerModuleNode(
194+
_ssrModule: EnvironmentModuleNode,
195+
): BuildModuleNode {
196+
throw new Error("BuildModuleGraph getBackwardCompatibleServerModuleNode is not support");
197+
}
198+
199+
getBackwardCompatibleModuleNode(_mod: EnvironmentModuleNode): BuildModuleNode {
200+
throw new Error("BuildModuleGraph getBackwardCompatibleModuleNode is not support");
201+
}
202+
203+
getBackwardCompatibleModuleNodeDual(
204+
_clientModule?: EnvironmentModuleNode,
205+
_ssrModule?: EnvironmentModuleNode,
206+
): BuildModuleNode {
207+
throw new Error("BuildModuleGraph getBackwardCompatibleModuleNodeDual is not support");
208+
}
209+
}
210+
211+
export function buildModuleGraphPlugin(server: ViteDevServer): Plugin {
212+
return {
213+
name: 'build-module-graph-plugin',
214+
renderStart() {
215+
const moduleGraph = server.moduleGraph as BuildModuleGraph
216+
for (const id of this.getModuleIds()) {
217+
// const moduleInfo = this.getModuleInfo(id)!
218+
const file = cleanUrl(id)
219+
const moduleNode = new BuildModuleNode(id, file);
220+
moduleGraph.idToModuleMap.set(id, moduleNode)
221+
222+
moduleGraph.fileToModulesMap.set(file, new Set([moduleNode]))
223+
let fileMappedModules = moduleGraph.fileToModulesMap.get(file)
224+
if (!fileMappedModules) {
225+
fileMappedModules = new Set()
226+
moduleGraph.fileToModulesMap.set(file, fileMappedModules)
227+
}
228+
fileMappedModules.add(moduleNode)
229+
}
230+
for (const id of this.getModuleIds()) {
231+
const moduleInfo = this.getModuleInfo(id)!
232+
const moduleNode = moduleGraph.idToModuleMap.get(id);
233+
moduleNode!.importers = new Set(moduleInfo.importers.map((importerId) => moduleGraph.idToModuleMap.get(importerId)!))
234+
}
235+
}
236+
}
237+
}

packages/vite/src/node/server/hmr.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import type { EnvironmentModuleNode } from './moduleGraph'
2727
import type { ModuleNode } from './mixedModuleGraph'
2828
import type { DevEnvironment } from './environment'
2929
import { prepareError } from './middlewares/error'
30+
import type { BuildModuleNode } from './buildModuleGraph'
3031
import type { HttpServer } from '.'
3132
import { restartServerWithUrls } from '.'
3233

@@ -64,7 +65,7 @@ export interface HotUpdateOptions {
6465
export interface HmrContext {
6566
file: string
6667
timestamp: number
67-
modules: Array<ModuleNode>
68+
modules: Array<ModuleNode | BuildModuleNode>
6869
read: () => string | Promise<string>
6970
server: ViteDevServer
7071
}
@@ -453,7 +454,9 @@ export async function handleHMRUpdate(
453454
hotMap.set(environment, { options })
454455
}
455456

456-
const mixedMods = new Set(mixedModuleGraph.getModulesByFile(file))
457+
const mixedMods = new Set<BuildModuleNode | ModuleNode>(
458+
mixedModuleGraph.getModulesByFile(file),
459+
)
457460

458461
const mixedHmrContext: HmrContext = {
459462
...contextMeta,

packages/vite/src/node/server/index.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ import type { DevEnvironment } from './environment'
101101
import { hostCheckMiddleware } from './middlewares/hostCheck'
102102
import { memoryFilesMiddleware } from './middlewares/memoryFiles'
103103
import { rejectInvalidRequestMiddleware } from './middlewares/rejectInvalidRequest'
104+
import { BuildModuleGraph } from './buildModuleGraph'
104105

105106
export interface ServerOptions extends CommonServerOptions {
106107
/**
@@ -295,7 +296,7 @@ export interface ViteDevServer {
295296
* Module graph that tracks the import relationships, url to file mapping
296297
* and hmr state.
297298
*/
298-
moduleGraph: ModuleGraph
299+
moduleGraph: ModuleGraph | BuildModuleGraph
299300
/**
300301
* The resolved urls Vite prints on the CLI (URL-encoded). Returns `null`
301302
* in middleware mode or if the server is not listening on any port.
@@ -531,10 +532,12 @@ export async function _createServer(
531532

532533
// Backward compatibility
533534

534-
let moduleGraph = new ModuleGraph({
535-
client: () => environments.client.moduleGraph,
536-
ssr: () => environments.ssr.moduleGraph,
537-
})
535+
let moduleGraph = config.experimental.fullBundleMode
536+
? new BuildModuleGraph()
537+
: new ModuleGraph({
538+
client: () => environments.client.moduleGraph,
539+
ssr: () => environments.ssr.moduleGraph,
540+
})
538541
const pluginContainer = createPluginContainer(environments)
539542

540543
const closeHttpServer = createServerCloseFn(httpServer)
@@ -797,6 +800,7 @@ export async function _createServer(
797800
}
798801
}
799802

803+
// TODO(underfin): handle this
800804
const onFileAddUnlink = async (file: string, isUnlink: boolean) => {
801805
file = normalizePath(file)
802806
reloadOnTsconfigChange(server, file)

0 commit comments

Comments
 (0)