Skip to content

Commit b09ce57

Browse files
committed
fix(@angular-devkit/build-angular): handle HMR updates of global CSS when using Vite
This commit updates the Vite based dev-server to send updates for global styles using the HMR update instead of a full page reload when the the dev-server builder `hmr` option to be enabled.
1 parent c3c4853 commit b09ce57

File tree

1 file changed

+57
-18
lines changed
  • packages/angular_devkit/build_angular/src/builders/dev-server

1 file changed

+57
-18
lines changed

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

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import type { BuilderContext } from '@angular-devkit/architect';
10-
import type { json } from '@angular-devkit/core';
10+
import type { json, logging } from '@angular-devkit/core';
1111
import type { OutputFile } from 'esbuild';
1212
import { lookup as lookupMimeType } from 'mrmime';
1313
import assert from 'node:assert';
@@ -89,23 +89,7 @@ export async function* serveWithVite(
8989
}
9090

9191
if (server) {
92-
// Invalidate any updated files
93-
for (const [file, record] of generatedFiles) {
94-
if (record.updated) {
95-
const updatedModules = server.moduleGraph.getModulesByFile(file);
96-
updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
97-
}
98-
}
99-
100-
// Send reload command to clients
101-
if (serverOptions.liveReload) {
102-
context.logger.info('Reloading client(s)...');
103-
104-
server.ws.send({
105-
type: 'full-reload',
106-
path: '*',
107-
});
108-
}
92+
handleUpdate(generatedFiles, server, serverOptions, context.logger);
10993
} else {
11094
// Setup server and start listening
11195
const serverConfiguration = await setupServer(
@@ -140,6 +124,61 @@ export async function* serveWithVite(
140124
}
141125
}
142126

127+
function handleUpdate(
128+
generatedFiles: Map<string, OutputFileRecord>,
129+
server: ViteDevServer,
130+
serverOptions: NormalizedDevServerOptions,
131+
logger: logging.LoggerApi,
132+
): void {
133+
const updatedFiles: string[] = [];
134+
135+
// Invalidate any updated files
136+
for (const [file, record] of generatedFiles) {
137+
if (record.updated) {
138+
updatedFiles.push(file);
139+
const updatedModules = server.moduleGraph.getModulesByFile(file);
140+
updatedModules?.forEach((m) => server?.moduleGraph.invalidateModule(m));
141+
}
142+
}
143+
144+
if (!updatedFiles.length) {
145+
return;
146+
}
147+
148+
if (serverOptions.hmr) {
149+
if (updatedFiles.every((f) => f.endsWith('.css'))) {
150+
const timestamp = Date.now();
151+
server.ws.send({
152+
type: 'update',
153+
updates: updatedFiles.map((f) => {
154+
const filePath = f.slice(1); // Remove leading slash.
155+
156+
return {
157+
type: 'css-update',
158+
timestamp,
159+
path: filePath,
160+
acceptedPath: filePath,
161+
};
162+
}),
163+
});
164+
165+
logger.info('HMR update sent to client(s)...');
166+
167+
return;
168+
}
169+
}
170+
171+
// Send reload command to clients
172+
if (serverOptions.liveReload) {
173+
logger.info('Reloading client(s)...');
174+
175+
server.ws.send({
176+
type: 'full-reload',
177+
path: '*',
178+
});
179+
}
180+
}
181+
143182
function analyzeResultFiles(
144183
normalizePath: (id: string) => string,
145184
resultFiles: OutputFile[],

0 commit comments

Comments
 (0)