diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts index c1ee820d6f1b..f7c7a0acb33a 100644 --- a/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/build-assets_spec.ts @@ -12,6 +12,11 @@ import { describeServeBuilder } from '../jasmine-helpers'; import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup'; describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => { + beforeEach(async () => { + // Application code is not needed for these tests + await harness.writeFile('src/main.ts', 'console.log("TEST");'); + }); + const javascriptFileContent = "import {foo} from 'unresolved'; /* a comment */const foo = `bar`;\n\n\n"; @@ -53,6 +58,42 @@ describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupT expect(await response?.text()).toContain(javascriptFileContent); }); + it('serves a project CSS asset unmodified', async () => { + const cssFileContent = 'p { color: blue };'; + await harness.writeFile('src/extra.css', cssFileContent); + + setupTarget(harness, { + assets: ['src/extra.css'], + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'extra.css'); + + expect(result?.success).toBeTrue(); + expect(await response?.text()).toBe(cssFileContent); + }); + + it('serves a project SCSS asset unmodified', async () => { + const cssFileContent = 'p { color: blue };'; + await harness.writeFile('src/extra.scss', cssFileContent); + + setupTarget(harness, { + assets: ['src/extra.scss'], + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'extra.scss'); + + expect(result?.success).toBeTrue(); + expect(await response?.text()).toBe(cssFileContent); + }); + it('should return 404 for non existing assets', async () => { setupTarget(harness, { assets: [], 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 f3c5098ab74c..a9fe69ffca15 100644 --- a/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts +++ b/packages/angular/build/src/tools/vite/middlewares/assets-middleware.ts @@ -20,6 +20,7 @@ export interface ComponentStyleRecord { reload?: boolean; } +const CSS_PREPROCESSOR_REGEXP = /\.(?:s[ac]ss|less|css)$/; const JS_TS_REGEXP = /\.[cm]?[tj]sx?$/; export function createAngularAssetsMiddleware( @@ -43,8 +44,8 @@ export function createAngularAssetsMiddleware( // Rewrite all build assets to a vite raw fs URL const asset = assets.get(pathname); if (asset) { - // This is a workaround to serve JS and TS files without Vite transformations. - if (JS_TS_REGEXP.test(extension)) { + // This is a workaround to serve CSS, JS and TS files without Vite transformations. + if (JS_TS_REGEXP.test(extension) || CSS_PREPROCESSOR_REGEXP.test(extension)) { const contents = readFileSync(asset.source); const etag = `W/${createHash('sha256').update(contents).digest('hex')}`; if (checkAndHandleEtag(req, res, etag)) {