Skip to content

Commit 2800e2f

Browse files
clydinangular-robot[bot]
authored andcommitted
refactor(@angular-devkit/build-angular): separate change logic in esbuild dev-server
The change detection logic for the output files is now moved to a separate function to reduce the code line count for the main dev-server function. Also changed the setup function for the vite server to return the actual configuration to allow for better reuse and testability.
1 parent 9009175 commit 2800e2f

File tree

1 file changed

+65
-58
lines changed
  • packages/angular_devkit/build_angular/src/builders/dev-server

1 file changed

+65
-58
lines changed

packages/angular_devkit/build_angular/src/builders/dev-server/vite-server.ts

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import type { BuilderContext } from '@angular-devkit/architect';
1010
import type { json } from '@angular-devkit/core';
11+
import type { OutputFile } from 'esbuild';
1112
import { lookup as lookupMimeType } from 'mrmime';
1213
import assert from 'node:assert';
1314
import { BinaryLike, createHash } from 'node:crypto';
@@ -55,71 +56,25 @@ export async function* serveWithVite(
5556

5657
let server: ViteDevServer | undefined;
5758
let listeningAddress: AddressInfo | undefined;
58-
const outputFiles = new Map<string, OutputFileRecord>();
59-
const assets = new Map<string, string>();
59+
const generatedFiles = new Map<string, OutputFileRecord>();
60+
const assetFiles = new Map<string, string>();
6061
// TODO: Switch this to an architect schedule call when infrastructure settings are supported
6162
for await (const result of buildEsbuildBrowser(browserOptions, context, { write: false })) {
6263
assert(result.outputFiles, 'Builder did not provide result files.');
6364

6465
// Analyze result files for changes
65-
const seen = new Set<string>(['/index.html']);
66-
for (const file of result.outputFiles) {
67-
const filePath = '/' + normalizePath(file.path);
68-
seen.add(filePath);
69-
70-
// Skip analysis of sourcemaps
71-
if (filePath.endsWith('.map')) {
72-
outputFiles.set(filePath, {
73-
contents: file.contents,
74-
size: file.contents.byteLength,
75-
updated: false,
76-
});
77-
78-
continue;
79-
}
80-
81-
let fileHash: Buffer | undefined;
82-
const existingRecord = outputFiles.get(filePath);
83-
if (existingRecord && existingRecord.size === file.contents.byteLength) {
84-
// Only hash existing file when needed
85-
if (existingRecord.hash === undefined) {
86-
existingRecord.hash = hashContent(existingRecord.contents);
87-
}
66+
analyzeResultFiles(result.outputFiles, generatedFiles);
8867

89-
// Compare against latest result output
90-
fileHash = hashContent(file.contents);
91-
if (fileHash.equals(existingRecord.hash)) {
92-
// Same file
93-
existingRecord.updated = false;
94-
continue;
95-
}
96-
}
97-
98-
outputFiles.set(filePath, {
99-
contents: file.contents,
100-
size: file.contents.byteLength,
101-
hash: fileHash,
102-
updated: true,
103-
});
104-
}
105-
106-
// Clear stale output files
107-
for (const file of outputFiles.keys()) {
108-
if (!seen.has(file)) {
109-
outputFiles.delete(file);
110-
}
111-
}
112-
113-
assets.clear();
68+
assetFiles.clear();
11469
if (result.assetFiles) {
11570
for (const asset of result.assetFiles) {
116-
assets.set('/' + normalizePath(asset.destination), asset.source);
71+
assetFiles.set('/' + normalizePath(asset.destination), asset.source);
11772
}
11873
}
11974

12075
if (server) {
12176
// Invalidate any updated files
122-
for (const [file, record] of outputFiles) {
77+
for (const [file, record] of generatedFiles) {
12378
if (record.updated) {
12479
const updatedModules = server.moduleGraph.getModulesByFile(file);
12580
updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
@@ -137,7 +92,8 @@ export async function* serveWithVite(
13792
}
13893
} else {
13994
// Setup server and start listening
140-
server = await setupServer(serverOptions, outputFiles, assets);
95+
const serverConfiguration = await setupServer(serverOptions, generatedFiles, assetFiles);
96+
server = await createServer(serverConfiguration);
14197

14298
await server.listen();
14399
listeningAddress = server.httpServer?.address() as AddressInfo;
@@ -160,11 +116,64 @@ export async function* serveWithVite(
160116
}
161117
}
162118

163-
async function setupServer(
119+
function analyzeResultFiles(
120+
resultFiles: OutputFile[],
121+
generatedFiles: Map<string, OutputFileRecord>,
122+
) {
123+
const seen = new Set<string>(['/index.html']);
124+
for (const file of resultFiles) {
125+
const filePath = '/' + normalizePath(file.path);
126+
seen.add(filePath);
127+
128+
// Skip analysis of sourcemaps
129+
if (filePath.endsWith('.map')) {
130+
generatedFiles.set(filePath, {
131+
contents: file.contents,
132+
size: file.contents.byteLength,
133+
updated: false,
134+
});
135+
136+
continue;
137+
}
138+
139+
let fileHash: Buffer | undefined;
140+
const existingRecord = generatedFiles.get(filePath);
141+
if (existingRecord && existingRecord.size === file.contents.byteLength) {
142+
// Only hash existing file when needed
143+
if (existingRecord.hash === undefined) {
144+
existingRecord.hash = hashContent(existingRecord.contents);
145+
}
146+
147+
// Compare against latest result output
148+
fileHash = hashContent(file.contents);
149+
if (fileHash.equals(existingRecord.hash)) {
150+
// Same file
151+
existingRecord.updated = false;
152+
continue;
153+
}
154+
}
155+
156+
generatedFiles.set(filePath, {
157+
contents: file.contents,
158+
size: file.contents.byteLength,
159+
hash: fileHash,
160+
updated: true,
161+
});
162+
}
163+
164+
// Clear stale output files
165+
for (const file of generatedFiles.keys()) {
166+
if (!seen.has(file)) {
167+
generatedFiles.delete(file);
168+
}
169+
}
170+
}
171+
172+
export async function setupServer(
164173
serverOptions: NormalizedDevServerOptions,
165174
outputFiles: Map<string, OutputFileRecord>,
166175
assets: Map<string, string>,
167-
): Promise<ViteDevServer> {
176+
): Promise<InlineConfig> {
168177
const proxy = await loadProxyConfiguration(
169178
serverOptions.workspaceRoot,
170179
serverOptions.proxyConfig,
@@ -330,7 +339,5 @@ async function setupServer(
330339
}
331340
}
332341

333-
const server = await createServer(configuration);
334-
335-
return server;
342+
return configuration;
336343
}

0 commit comments

Comments
 (0)