diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index 7a4acb7a00d1..0977257ad782 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -42,7 +42,7 @@ import type { DevServerBuilderOutput } from './output'; interface OutputFileRecord { contents: Uint8Array; size: number; - hash?: string; + hash: string; updated: boolean; servable: boolean; type: BuildOutputFileType; @@ -540,6 +540,7 @@ function analyzeResultFiles( contents: file.contents, servable, size: file.contents.byteLength, + hash: file.hash, type: file.type, updated: false, }); diff --git a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts index a2633c21af27..0fd95baeea30 100644 --- a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts +++ b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts @@ -78,6 +78,13 @@ export function createAngularAssetsMiddleware( // Inject component ID for view encapsulation if requested const componentId = new URL(req.url, 'http://localhost').searchParams.get('ngcomp'); if (componentId !== null) { + const etag = `W/"${outputFile.contents.byteLength}-${outputFile.hash}-${componentId}"`; + if (req.headers['if-none-match'] === etag) { + res.statusCode = 304; + res.end(); + + return; + } // Record the component style usage for HMR updates const usedIds = usedComponentStyles.get(pathname); if (usedIds === undefined) { @@ -98,6 +105,7 @@ export function createAngularAssetsMiddleware( res.setHeader('Content-Type', 'text/css'); res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('ETag', etag); res.end(encapsulatedData); }) .catch((e) => next(e)); diff --git a/packages/angular/build/src/tools/vite/utils.ts b/packages/angular/build/src/tools/vite/utils.ts index 4e922ee1d458..ae2cd59ec693 100644 --- a/packages/angular/build/src/tools/vite/utils.ts +++ b/packages/angular/build/src/tools/vite/utils.ts @@ -9,7 +9,10 @@ import { lookup as lookupMimeType } from 'mrmime'; import { extname } from 'node:path'; -export type AngularMemoryOutputFiles = Map; +export type AngularMemoryOutputFiles = Map< + string, + { contents: Uint8Array; hash: string; servable: boolean } +>; export function pathnameWithoutBasePath(url: string, basePath: string): string { const parsedUrl = new URL(url, 'http://localhost');