Skip to content

Commit 201856a

Browse files
manfredsteyermgechev
authored andcommitted
fix(@angular-devkit/build-angular): run build steps for differential loading in sequence to avoid confusing progress information
Before, the build tasks ran in parallel and so the different webpack instances competed over the same lines on the console. To fail fast and to prevent to show the same errors twice, the second build step is not executed if the first one fails. As running these tasks in sequence causes issues with watch mode, this PR also disables differential loading when watch mode is requested.
1 parent 4807ff0 commit 201856a

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

packages/angular_devkit/build_angular/src/browser/index.ts

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
BuilderOutput,
1111
createBuilder,
1212
} from '@angular-devkit/architect';
13-
import { WebpackLoggingCallback, runWebpack } from '@angular-devkit/build-webpack';
13+
import { BuildResult, WebpackLoggingCallback, runWebpack } from '@angular-devkit/build-webpack';
1414
import {
1515
experimental,
1616
join,
@@ -23,8 +23,8 @@ import {
2323
import { NodeJsSyncHost } from '@angular-devkit/core/node';
2424
import * as fs from 'fs';
2525
import * as path from 'path';
26-
import { from, of, zip } from 'rxjs';
27-
import { catchError, concatMap, map, switchMap } from 'rxjs/operators';
26+
import { concat, from, of, zip } from 'rxjs';
27+
import { bufferCount, catchError, concatMap, map, mergeScan, switchMap } from 'rxjs/operators';
2828
import * as webpack from 'webpack';
2929
import { NgBuildAnalyticsPlugin } from '../../plugins/webpack/analytics';
3030
import { WebpackConfigOptions } from '../angular-cli-files/models/build-options';
@@ -182,12 +182,18 @@ export function buildWebpackBrowser(
182182
normalize(workspace.getProject(projectName).root),
183183
);
184184

185-
// We use zip because when having multiple builds we want to wait
186-
// for all builds to finish before processeding
187-
return zip(
188-
...configs.map(config => runWebpack(config, context, { logging: loggingFn })),
189-
)
190-
.pipe(
185+
return from(configs).pipe(
186+
// the concurrency parameter (3rd parameter of mergeScan) is deliberately
187+
// set to 1 to make sure the build steps are executed in sequence.
188+
mergeScan((lastResult, config) => {
189+
// Make sure to only run the 2nd build step, if 1st one succeeded
190+
if (lastResult.success) {
191+
return runWebpack(config, context, { logging: loggingFn });
192+
} else {
193+
return of();
194+
}
195+
}, { success: true } as BuildResult, 1),
196+
bufferCount(configs.length),
191197
switchMap(buildEvents => {
192198
const success = buildEvents.every(r => r.success);
193199
if (success && buildEvents.length === 2 && options.index) {

packages/angular_devkit/build_angular/src/utils/webpack-browser-config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ export async function generateWebpackConfig(
5555
// However this config generation is used by multiple builders such as dev-server
5656
const scriptTarget = tsConfig.options.target;
5757
const differentialLoading = context.builder.builderName === 'browser'
58-
&& isDifferentialLoadingNeeded(projectRoot, scriptTarget);
58+
&& isDifferentialLoadingNeeded(projectRoot, scriptTarget) && !options.watch;
59+
5960
const scriptTargets = [scriptTarget];
6061

6162
if (differentialLoading) {

packages/angular_devkit/build_angular/test/browser/differential_loading_spec_large.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,36 @@ describe('Browser Builder with differential loading', () => {
6363
.toEqual(jasmine.arrayWithExactContents(expectedOutputs));
6464
});
6565

66+
it('deactivates differential loading for watch mode', async () => {
67+
const { files } = await browserBuild(architect, host, target, { watch: true });
68+
69+
const expectedOutputs = [
70+
'favicon.ico',
71+
'index.html',
72+
73+
'main.js',
74+
'main.js.map',
75+
76+
'polyfills-es5.js',
77+
'polyfills-es5.js.map',
78+
'polyfills.js',
79+
'polyfills.js.map',
80+
81+
'runtime.js',
82+
'runtime.js.map',
83+
84+
'styles.js',
85+
'styles.js.map',
86+
87+
'vendor.js',
88+
'vendor.js.map',
89+
] as PathFragment[];
90+
91+
expect(Object.keys(files))
92+
.toEqual(jasmine.arrayWithExactContents(expectedOutputs));
93+
});
94+
95+
6696
it('emits the right ES formats', async () => {
6797
const { files } = await browserBuild(architect, host, target, { optimization: true });
6898
expect(await files['main-es5.js']).not.toContain('class');

0 commit comments

Comments
 (0)