diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build-assets_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build-assets_spec.ts new file mode 100644 index 000000000000..48559d704967 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/build-assets_spec.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { serveWebpackBrowser } from '../../index'; +import { executeOnceAndFetch } from '../execute-fetch'; +import { + BASE_OPTIONS, + DEV_SERVER_BUILDER_INFO, + describeBuilder, + setupBrowserTarget, +} from '../setup'; + +describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { + describe('Behavior: "browser builder assets"', () => { + it('serves a project JavaScript asset unmodified', async () => { + const javascriptFileContent = '/* a comment */const foo = `bar`;\n\n\n'; + await harness.writeFile('src/extra.js', javascriptFileContent); + + setupBrowserTarget(harness, { + assets: ['src/extra.js'], + optimization: { + scripts: true, + }, + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, 'extra.js'); + + expect(result?.success).toBeTrue(); + expect(await response?.text()).toBe(javascriptFileContent); + }); + }); +}); diff --git a/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-plugin.ts b/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-plugin.ts index c861dd6636e1..0e7c4ba4ef59 100644 --- a/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-plugin.ts +++ b/packages/angular_devkit/build_angular/src/webpack/plugins/javascript-optimizer-plugin.ts @@ -96,34 +96,36 @@ export class JavaScriptOptimizerPlugin { } const scriptAsset = compilation.getAsset(assetName); + // Skip assets that have already been optimized or are verbatim copies (project assets) + if (!scriptAsset || scriptAsset.info.minimized || scriptAsset.info.copied) { + continue; + } - if (scriptAsset && !scriptAsset.info.minimized) { - const { source: scriptAssetSource, name } = scriptAsset; - let cacheItem; - - if (cache) { - const eTag = cache.getLazyHashedEtag(scriptAssetSource); - cacheItem = cache.getItemCache(name, eTag); - const cachedOutput = await cacheItem.getPromise< - { source: sources.Source } | undefined - >(); - - if (cachedOutput) { - compilation.updateAsset(name, cachedOutput.source, { - minimized: true, - }); - continue; - } + const { source: scriptAssetSource, name } = scriptAsset; + let cacheItem; + + if (cache) { + const eTag = cache.getLazyHashedEtag(scriptAssetSource); + cacheItem = cache.getItemCache(name, eTag); + const cachedOutput = await cacheItem.getPromise< + { source: sources.Source } | undefined + >(); + + if (cachedOutput) { + compilation.updateAsset(name, cachedOutput.source, { + minimized: true, + }); + continue; } - - const { source, map } = scriptAssetSource.sourceAndMap(); - scriptsToOptimize.push({ - name: scriptAsset.name, - code: typeof source === 'string' ? source : source.toString(), - map, - cacheItem, - }); } + + const { source, map } = scriptAssetSource.sourceAndMap(); + scriptsToOptimize.push({ + name: scriptAsset.name, + code: typeof source === 'string' ? source : source.toString(), + map, + cacheItem, + }); } if (scriptsToOptimize.length === 0) {