diff --git a/packages/angular_devkit/build_angular/src/browser/index.ts b/packages/angular_devkit/build_angular/src/browser/index.ts index d26a149a19..1e8766c796 100644 --- a/packages/angular_devkit/build_angular/src/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/browser/index.ts @@ -10,7 +10,7 @@ import { BuilderOutput, createBuilder, } from '@angular-devkit/architect'; -import { WebpackLoggingCallback, runWebpack } from '@angular-devkit/build-webpack'; +import { BuildResult, WebpackLoggingCallback, runWebpack } from '@angular-devkit/build-webpack'; import { experimental, join, @@ -23,8 +23,8 @@ import { import { NodeJsSyncHost } from '@angular-devkit/core/node'; import * as fs from 'fs'; import * as path from 'path'; -import { from, of, zip } from 'rxjs'; -import { catchError, concatMap, map, switchMap } from 'rxjs/operators'; +import { concat, from, of, zip } from 'rxjs'; +import { bufferCount, catchError, concatMap, map, mergeScan, switchMap } from 'rxjs/operators'; import * as webpack from 'webpack'; import { NgBuildAnalyticsPlugin } from '../../plugins/webpack/analytics'; import { WebpackConfigOptions } from '../angular-cli-files/models/build-options'; @@ -182,12 +182,18 @@ export function buildWebpackBrowser( normalize(workspace.getProject(projectName).root), ); - // We use zip because when having multiple builds we want to wait - // for all builds to finish before processeding - return zip( - ...configs.map(config => runWebpack(config, context, { logging: loggingFn })), - ) - .pipe( + return from(configs).pipe( + // the concurrency parameter (3rd parameter of mergeScan) is deliberately + // set to 1 to make sure the build steps are executed in sequence. + mergeScan((lastResult, config) => { + // Make sure to only run the 2nd build step, if 1st one succeeded + if (lastResult.success) { + return runWebpack(config, context, { logging: loggingFn }); + } else { + return of(); + } + }, { success: true } as BuildResult, 1), + bufferCount(configs.length), switchMap(buildEvents => { const success = buildEvents.every(r => r.success); if (success && buildEvents.length === 2 && options.index) { diff --git a/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts b/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts index bcd8bd6858..652acc4d51 100644 --- a/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts +++ b/packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts @@ -55,7 +55,8 @@ export async function generateWebpackConfig( // However this config generation is used by multiple builders such as dev-server const scriptTarget = tsConfig.options.target; const differentialLoading = context.builder.builderName === 'browser' - && isDifferentialLoadingNeeded(projectRoot, scriptTarget); + && isDifferentialLoadingNeeded(projectRoot, scriptTarget) && !options.watch; + const scriptTargets = [scriptTarget]; if (differentialLoading) { diff --git a/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts b/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts index c0eccfe819..386d825445 100644 --- a/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts +++ b/packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts @@ -63,6 +63,36 @@ describe('Browser Builder with differential loading', () => { .toEqual(jasmine.arrayWithExactContents(expectedOutputs)); }); + it('deactivates differential loading for watch mode', async () => { + const { files } = await browserBuild(architect, host, target, { watch: true }); + + const expectedOutputs = [ + 'favicon.ico', + 'index.html', + + 'main.js', + 'main.js.map', + + 'polyfills-es5.js', + 'polyfills-es5.js.map', + 'polyfills.js', + 'polyfills.js.map', + + 'runtime.js', + 'runtime.js.map', + + 'styles.js', + 'styles.js.map', + + 'vendor.js', + 'vendor.js.map', + ] as PathFragment[]; + + expect(Object.keys(files)) + .toEqual(jasmine.arrayWithExactContents(expectedOutputs)); + }); + + it('emits the right ES formats', async () => { const { files } = await browserBuild(architect, host, target, { optimization: true }); expect(await files['main-es5.js']).not.toContain('class');