77 */
88
99import { lookup as lookupMimeType } from 'mrmime' ;
10+ import { createHash } from 'node:crypto' ;
11+ import { readFileSync } from 'node:fs' ;
12+ import type { ServerResponse } from 'node:http' ;
1013import { extname } from 'node:path' ;
1114import type { Connect , ViteDevServer } from 'vite' ;
1215import { AngularMemoryOutputFiles , AngularOutputAssets , pathnameWithoutBasePath } from '../utils' ;
@@ -17,6 +20,8 @@ export interface ComponentStyleRecord {
1720 reload ?: boolean ;
1821}
1922
23+ const JS_TS_REGEXP = / \. [ c m ] ? [ t j ] s x ? $ / ;
24+
2025export function createAngularAssetsMiddleware (
2126 server : ViteDevServer ,
2227 assets : AngularOutputAssets ,
@@ -38,15 +43,28 @@ export function createAngularAssetsMiddleware(
3843 // Rewrite all build assets to a vite raw fs URL
3944 const asset = assets . get ( pathname ) ;
4045 if ( asset ) {
41- // Workaround to disable Vite transformer middleware.
42- // See: https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/middlewares/transform.ts#L201 and
43- // https://github.com/vitejs/vite/blob/746a1daab0395f98f0afbdee8f364cb6cf2f3b3f/packages/vite/src/node/server/transformRequest.ts#L204-L206
44- req . headers . accept = 'text/html' ;
45-
46- // The encoding needs to match what happens in the vite static middleware.
47- // ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
48- req . url = `${ server . config . base } @fs/${ encodeURI ( asset . source ) } ` ;
49- next ( ) ;
46+ // This is a workaround to serve JS and TS files without Vite transformations.
47+ if ( JS_TS_REGEXP . test ( extension ) ) {
48+ const contents = readFileSync ( asset . source ) ;
49+ const etag = `W/${ createHash ( 'sha256' ) . update ( contents ) . digest ( 'hex' ) } ` ;
50+ if ( checkAndHandleEtag ( req , res , etag ) ) {
51+ return ;
52+ }
53+
54+ const mimeType = lookupMimeType ( extension ) ;
55+ if ( mimeType ) {
56+ res . setHeader ( 'Content-Type' , mimeType ) ;
57+ }
58+
59+ res . setHeader ( 'ETag' , etag ) ;
60+ res . setHeader ( 'Cache-Control' , 'no-cache' ) ;
61+ res . end ( contents ) ;
62+ } else {
63+ // The encoding needs to match what happens in the vite static middleware.
64+ // ref: https://github.com/vitejs/vite/blob/d4f13bd81468961c8c926438e815ab6b1c82735e/packages/vite/src/node/server/middlewares/static.ts#L163
65+ req . url = `${ server . config . base } @fs/${ encodeURI ( asset . source ) } ` ;
66+ next ( ) ;
67+ }
5068
5169 return ;
5270 }
@@ -100,12 +118,8 @@ export function createAngularAssetsMiddleware(
100118 componentStyle . used . add ( componentId ) ;
101119 }
102120
103- // Report if there are no changes to avoid reprocessing
104121 const etag = `W/"${ outputFile . contents . byteLength } -${ outputFile . hash } -${ componentId } "` ;
105- if ( req . headers [ 'if-none-match' ] === etag ) {
106- res . statusCode = 304 ;
107- res . end ( ) ;
108-
122+ if ( checkAndHandleEtag ( req , res , etag ) ) {
109123 return ;
110124 }
111125
@@ -134,12 +148,8 @@ export function createAngularAssetsMiddleware(
134148 }
135149 }
136150
137- // Avoid resending the content if it has not changed since last request
138151 const etag = `W/"${ outputFile . contents . byteLength } -${ outputFile . hash } "` ;
139- if ( req . headers [ 'if-none-match' ] === etag ) {
140- res . statusCode = 304 ;
141- res . end ( ) ;
142-
152+ if ( checkAndHandleEtag ( req , res , etag ) ) {
143153 return ;
144154 }
145155
@@ -188,3 +198,18 @@ export function createAngularAssetsMiddleware(
188198 next ( ) ;
189199 } ;
190200}
201+
202+ function checkAndHandleEtag (
203+ req : Connect . IncomingMessage ,
204+ res : ServerResponse ,
205+ etag : string ,
206+ ) : boolean {
207+ if ( req . headers [ 'if-none-match' ] === etag ) {
208+ res . statusCode = 304 ;
209+ res . end ( ) ;
210+
211+ return true ;
212+ }
213+
214+ return false ;
215+ }
0 commit comments