From 72f53c2df78198cfe602819a48e8f35c2415b78a Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Sat, 7 Jul 2018 20:26:06 +0800 Subject: [PATCH] fix(@angular-devkit/build-angular): don't add hash to lazy styles Fix #11235 --- .../models/webpack-configs/styles.ts | 15 ++++++- .../plugins/remove-hash-plugin.ts | 43 +++++++++++++++++++ .../test/browser/output-hashing_spec_large.ts | 17 ++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 packages/angular_devkit/build_angular/src/angular-cli-files/plugins/remove-hash-plugin.ts diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts index 3f0f17efa333..32b0f388f5e7 100644 --- a/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/models/webpack-configs/styles.ts @@ -17,6 +17,7 @@ import { findUp } from '../../utilities/find-up'; import { RawCssLoader } from '../../plugins/webpack'; import { ExtraEntryPoint } from '../../../browser/schema'; import { normalizeExtraEntryPoints } from './utils'; +import { RemoveHashPlugin } from '../../plugins/remove-hash-plugin'; const postcssUrl = require('postcss-url'); const autoprefixer = require('autoprefixer'); @@ -158,7 +159,7 @@ export function getStylesConfig(wco: WebpackConfigOptions) { // use includePaths from appConfig const includePaths: string[] = []; - let lessPathOptions: { paths?: string[] } = { }; + let lessPathOptions: { paths?: string[] } = {}; if (buildOptions.stylePreprocessorOptions && buildOptions.stylePreprocessorOptions.includePaths @@ -173,6 +174,8 @@ export function getStylesConfig(wco: WebpackConfigOptions) { // Process global styles. if (buildOptions.styles.length > 0) { + const chunkIds: string[] = []; + normalizeExtraEntryPoints(buildOptions.styles, 'styles').forEach(style => { const resolvedPath = path.resolve(root, style.input); @@ -183,9 +186,19 @@ export function getStylesConfig(wco: WebpackConfigOptions) { entryPoints[style.bundleName] = [resolvedPath] } + // Add lazy styles to the list. + if (style.lazy) { + chunkIds.push(style.bundleName); + } + // Add global css paths. globalStylePaths.push(resolvedPath); }); + + if (chunkIds.length > 0) { + // Add plugin to remove hashes from lazy styles. + extraPlugins.push(new RemoveHashPlugin({ chunkIds, hashFormat})); + } } // set base rules to derive final rules from diff --git a/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/remove-hash-plugin.ts b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/remove-hash-plugin.ts new file mode 100644 index 000000000000..2dc1e814e3b8 --- /dev/null +++ b/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/remove-hash-plugin.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright Google Inc. 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 { Compiler, compilation } from 'webpack'; +import { HashFormat } from '../models/webpack-configs/utils'; + + +export interface RemoveHashPluginOptions { + chunkIds: string[]; + hashFormat: HashFormat; +} + +export class RemoveHashPlugin { + + constructor(private options: RemoveHashPluginOptions) { } + + apply(compiler: Compiler): void { + compiler.hooks.compilation.tap('remove-hash-plugin', compilation => { + const mainTemplate = compilation.mainTemplate as compilation.MainTemplate & { + hooks: compilation.CompilationHooks; + }; + + mainTemplate.hooks.assetPath.tap('remove-hash-plugin', + (path: string, data: { chunk?: { id: string } }) => { + const chunkId = data.chunk && data.chunk.id; + + if (chunkId && this.options.chunkIds.includes(chunkId)) { + // Replace hash formats with empty strings. + return path + .replace(this.options.hashFormat.chunk, '') + .replace(this.options.hashFormat.extract, ''); + } + + return path; + }, + ); + }); + } +} diff --git a/packages/angular_devkit/build_angular/test/browser/output-hashing_spec_large.ts b/packages/angular_devkit/build_angular/test/browser/output-hashing_spec_large.ts index 999e843c5d3e..56390f91d42a 100644 --- a/packages/angular_devkit/build_angular/test/browser/output-hashing_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/browser/output-hashing_spec_large.ts @@ -163,4 +163,21 @@ describe('Browser Builder output hashing', () => { }), ).toPromise().then(done, done.fail); }); + + it('does not hash lazy styles', (done) => { + const overrides = { + outputHashing: 'all', + extractCss: true, + styles: [{ input: 'src/styles.css', lazy: true }], + }; + + runTargetSpec(host, browserTargetSpec, overrides, DefaultTimeout).pipe( + tap(() => { + expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js/)).toBeFalsy(); + expect(host.fileMatchExists('dist', /styles\.[0-9a-f]{20}\.js.map/)).toBeFalsy(); + expect(host.scopedSync().exists(normalize('dist/styles.css'))).toBe(true); + expect(host.scopedSync().exists(normalize('dist/styles.css.map'))).toBe(true); + }), + ).toPromise().then(done, done.fail); + }); });