Skip to content

Commit c63b5b1

Browse files
clydinmgechev
authored andcommitted
fix(@angular-devkit/build-angular): support differential loading for web workers
Fixes #16275
1 parent 406d792 commit c63b5b1

File tree

4 files changed

+58
-6
lines changed

4 files changed

+58
-6
lines changed

packages/angular_devkit/build_angular/src/angular-cli-files/utilities/stats.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export function generateBundleStats(
3939
const g = (x: string) => (colors ? bold(green(x)) : x);
4040
const y = (x: string) => (colors ? bold(yellow(x)) : x);
4141

42+
const id = info.id ? y(info.id.toString()) : '';
4243
const size = typeof info.size === 'number' ? ` ${formatSize(info.size)}` : '';
4344
const files = info.files.map(f => path.basename(f)).join(', ');
4445
const names = info.names ? ` (${info.names.join(', ')})` : '';
@@ -47,7 +48,7 @@ export function generateBundleStats(
4748
.map(f => (f && (info as any)[f] ? g(` [${f}]`) : ''))
4849
.join('');
4950

50-
return `chunk {${y(info.id.toString())}} ${g(files)}${names}${size} ${initial}${flags}`;
51+
return `chunk {${id}} ${g(files)}${names}${size} ${initial}${flags}`;
5152
}
5253

5354
export function generateBuildStats(hash: string, time: number, colors: boolean): string {

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,23 @@ export function buildWebpackBrowser(
331331

332332
let mainChunkId;
333333
const actions: ProcessBundleOptions[] = [];
334+
let workerReplacements: [string, string][] | undefined;
334335
const seen = new Set<string>();
335336
for (const file of emittedFiles) {
336337
// Assets are not processed nor injected into the index
337338
if (file.asset) {
338-
continue;
339+
// WorkerPlugin adds worker files to assets
340+
if (file.file.endsWith('.worker.js')) {
341+
if (!workerReplacements) {
342+
workerReplacements = [];
343+
}
344+
workerReplacements.push([
345+
file.file,
346+
file.file.replace(/\-es20\d{2}/, '-es5'),
347+
]);
348+
} else {
349+
continue;
350+
}
339351
}
340352

341353
// Scripts and non-javascript files are not processed
@@ -431,7 +443,7 @@ export function buildWebpackBrowser(
431443
if (action.integrityAlgorithm && action.runtime) {
432444
processRuntimeAction = action;
433445
} else {
434-
processActions.push(action);
446+
processActions.push({ replacements: workerReplacements, ...action });
435447
}
436448
}
437449

packages/angular_devkit/build_angular/src/utils/process-bundle.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,15 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
import { NodePath, ParseResult, parseSync, transformAsync, traverse, types } from '@babel/core';
8+
import {
9+
NodePath,
10+
ParseResult,
11+
PluginObj,
12+
parseSync,
13+
transformAsync,
14+
traverse,
15+
types,
16+
} from '@babel/core';
917
import { createHash } from 'crypto';
1018
import * as fs from 'fs';
1119
import * as path from 'path';
@@ -34,6 +42,7 @@ export interface ProcessBundleOptions {
3442
cacheKeys?: (string | null)[];
3543
integrityAlgorithm?: 'sha256' | 'sha384' | 'sha512';
3644
runtimeData?: ProcessBundleResult[];
45+
replacements?: [string, string][];
3746
}
3847

3948
export interface ProcessBundleResult {
@@ -120,6 +129,7 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
120129
// modules aren't needed since the bundles use webpack's custom module loading
121130
// 'transform-typeof-symbol' generates slower code
122131
presets: [['@babel/preset-env', { modules: false, exclude: ['transform-typeof-symbol'] }]],
132+
plugins: options.replacements ? [createReplacePlugin(options.replacements)] : [],
123133
minified: options.optimize,
124134
// `false` ensures it is disabled and prevents large file warnings
125135
compact: options.optimize || false,
@@ -467,6 +477,20 @@ async function processRuntime(
467477
return result;
468478
}
469479

480+
function createReplacePlugin(replacements: [string, string][]): PluginObj {
481+
return {
482+
visitor: {
483+
StringLiteral(path: NodePath<types.StringLiteral>) {
484+
for (const replacement of replacements) {
485+
if (path.node.value === replacement[0]) {
486+
path.replaceWith(types.stringLiteral(replacement[1]));
487+
}
488+
}
489+
},
490+
},
491+
};
492+
}
493+
470494
export interface InlineOptions {
471495
filename: string;
472496
code: string;

tests/legacy-cli/e2e/tests/build/worker.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@
88
import { join } from 'path';
99
import { expectFileToExist, expectFileToMatch, replaceInFile, writeFile } from '../../utils/fs';
1010
import { ng } from '../../utils/process';
11-
11+
import { expectToFail } from '../../utils/utils';
1212

1313
export default async function () {
14-
1514
const workerPath = join('src', 'app', 'app.worker.ts');
1615
const snippetPath = join('src', 'app', 'app.component.ts');
1716
const projectTsConfig = 'tsconfig.json';
@@ -23,6 +22,22 @@ export default async function () {
2322
await expectFileToExist(workerTsConfig);
2423
await expectFileToMatch(snippetPath, `new Worker('./app.worker', { type: 'module' })`);
2524

25+
await ng('build');
26+
await expectFileToExist('dist/test-project/0-es5.worker.js');
27+
await expectFileToMatch('dist/test-project/main-es5.js', '0-es5.worker.js');
28+
await expectToFail(() => expectFileToMatch('dist/test-project/main-es5.js', '0-es2015.worker.js'));
29+
await expectFileToExist('dist/test-project/0-es2015.worker.js');
30+
await expectFileToMatch('dist/test-project/main-es2015.js', '0-es2015.worker.js');
31+
await expectToFail(() => expectFileToMatch('dist/test-project/main-es2015.js', '0-es5.worker.js'));
32+
33+
await ng('build', '--prod', '--output-hashing=none');
34+
await expectFileToExist('dist/test-project/0-es5.worker.js');
35+
await expectFileToMatch('dist/test-project/main-es5.js', '0-es5.worker.js');
36+
await expectToFail(() => expectFileToMatch('dist/test-project/main-es5.js', '0-es2015.worker.js'));
37+
await expectFileToExist('dist/test-project/0-es2015.worker.js');
38+
await expectFileToMatch('dist/test-project/main-es2015.js', '0-es2015.worker.js');
39+
await expectToFail(() => expectFileToMatch('dist/test-project/main-es2015.js', '0-es5.worker.js'));
40+
2641
// console.warn has to be used because chrome only captures warnings and errors by default
2742
// https://github.com/angular/protractor/issues/2207
2843
await replaceInFile('src/app/app.component.ts', 'console.log', 'console.warn');

0 commit comments

Comments
 (0)