Skip to content

Commit 8d52d9b

Browse files
committed
fix(@angular-devkit/build-angular): use a separate worker pool for i18n inlining
This change isolates the i18n processing when differential loading is enabled into a separate pool of Worker threads. This may provide a reduction in peak memory usage due to the larger amount of processing (and therefore processing code/transforms) necessary to perform the differential loading transformations that can now be shutdown earlier in the build process.
1 parent 2109a09 commit 8d52d9b

File tree

1 file changed

+107
-100
lines changed
  • packages/angular_devkit/build_angular/src/browser

1 file changed

+107
-100
lines changed

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

Lines changed: 107 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -417,129 +417,136 @@ export function buildWebpackBrowser(
417417
}
418418
}
419419

420-
const executor = new BundleActionExecutor(
420+
const differentialLoadingExecutor = new BundleActionExecutor(
421421
{ cachePath: cacheDownlevelPath, i18n },
422422
options.subresourceIntegrity ? 'sha384' : undefined,
423423
);
424424

425425
// Execute the bundle processing actions
426426
try {
427427
spinner.start('Generating ES5 bundles for differential loading...');
428-
for await (const result of executor.processAll(processActions)) {
428+
for await (const result of differentialLoadingExecutor.processAll(
429+
processActions,
430+
)) {
429431
processResults.push(result);
430432
}
433+
} finally {
434+
differentialLoadingExecutor.stop();
435+
}
431436

432-
// Runtime must be processed after all other files
433-
if (processRuntimeAction) {
434-
const runtimeOptions = {
435-
...processRuntimeAction,
436-
runtimeData: processResults,
437-
supportedBrowsers: buildBrowserFeatures.supportedBrowsers,
438-
};
439-
processResults.push(
440-
await import('../utils/process-bundle').then((m) =>
441-
m.process(runtimeOptions),
442-
),
443-
);
444-
}
437+
// Runtime must be processed after all other files
438+
if (processRuntimeAction) {
439+
const runtimeOptions = {
440+
...processRuntimeAction,
441+
runtimeData: processResults,
442+
supportedBrowsers: buildBrowserFeatures.supportedBrowsers,
443+
};
444+
processResults.push(
445+
await import('../utils/process-bundle').then((m) => m.process(runtimeOptions)),
446+
);
447+
}
445448

446-
spinner.succeed('ES5 bundle generation complete.');
447-
448-
if (i18n.shouldInline) {
449-
spinner.start('Generating localized bundles...');
450-
const inlineActions: InlineOptions[] = [];
451-
const processedFiles = new Set<string>();
452-
for (const result of processResults) {
453-
if (result.original) {
454-
inlineActions.push({
455-
filename: path.basename(result.original.filename),
456-
code: fs.readFileSync(result.original.filename, 'utf8'),
457-
map:
458-
result.original.map &&
459-
fs.readFileSync(result.original.map.filename, 'utf8'),
460-
outputPath: baseOutputPath,
461-
es5: false,
462-
missingTranslation: options.i18nMissingTranslation,
463-
setLocale: result.name === mainChunkId,
464-
});
465-
processedFiles.add(result.original.filename);
466-
if (result.original.map) {
467-
processedFiles.add(result.original.map.filename);
468-
}
449+
spinner.succeed('ES5 bundle generation complete.');
450+
451+
if (i18n.shouldInline) {
452+
spinner.start('Generating localized bundles...');
453+
const inlineActions: InlineOptions[] = [];
454+
const processedFiles = new Set<string>();
455+
for (const result of processResults) {
456+
if (result.original) {
457+
inlineActions.push({
458+
filename: path.basename(result.original.filename),
459+
code: fs.readFileSync(result.original.filename, 'utf8'),
460+
map:
461+
result.original.map &&
462+
fs.readFileSync(result.original.map.filename, 'utf8'),
463+
outputPath: baseOutputPath,
464+
es5: false,
465+
missingTranslation: options.i18nMissingTranslation,
466+
setLocale: result.name === mainChunkId,
467+
});
468+
processedFiles.add(result.original.filename);
469+
if (result.original.map) {
470+
processedFiles.add(result.original.map.filename);
469471
}
470-
if (result.downlevel) {
471-
inlineActions.push({
472-
filename: path.basename(result.downlevel.filename),
473-
code: fs.readFileSync(result.downlevel.filename, 'utf8'),
474-
map:
475-
result.downlevel.map &&
476-
fs.readFileSync(result.downlevel.map.filename, 'utf8'),
477-
outputPath: baseOutputPath,
478-
es5: true,
479-
missingTranslation: options.i18nMissingTranslation,
480-
setLocale: result.name === mainChunkId,
481-
});
482-
processedFiles.add(result.downlevel.filename);
483-
if (result.downlevel.map) {
484-
processedFiles.add(result.downlevel.map.filename);
485-
}
472+
}
473+
if (result.downlevel) {
474+
inlineActions.push({
475+
filename: path.basename(result.downlevel.filename),
476+
code: fs.readFileSync(result.downlevel.filename, 'utf8'),
477+
map:
478+
result.downlevel.map &&
479+
fs.readFileSync(result.downlevel.map.filename, 'utf8'),
480+
outputPath: baseOutputPath,
481+
es5: true,
482+
missingTranslation: options.i18nMissingTranslation,
483+
setLocale: result.name === mainChunkId,
484+
});
485+
processedFiles.add(result.downlevel.filename);
486+
if (result.downlevel.map) {
487+
processedFiles.add(result.downlevel.map.filename);
486488
}
487489
}
490+
}
488491

489-
let hasErrors = false;
490-
try {
491-
for await (const result of executor.inlineAll(inlineActions)) {
492-
if (options.verbose) {
493-
context.logger.info(
494-
`Localized "${result.file}" [${result.count} translation(s)].`,
495-
);
496-
}
497-
for (const diagnostic of result.diagnostics) {
498-
spinner.stop();
499-
if (diagnostic.type === 'error') {
500-
hasErrors = true;
501-
context.logger.error(diagnostic.message);
502-
} else {
503-
context.logger.warn(diagnostic.message);
504-
}
505-
spinner.start();
492+
let hasErrors = false;
493+
const i18nExecutor = new BundleActionExecutor(
494+
{ i18n },
495+
options.subresourceIntegrity ? 'sha384' : undefined,
496+
);
497+
try {
498+
for await (const result of i18nExecutor.inlineAll(inlineActions)) {
499+
if (options.verbose) {
500+
context.logger.info(
501+
`Localized "${result.file}" [${result.count} translation(s)].`,
502+
);
503+
}
504+
for (const diagnostic of result.diagnostics) {
505+
spinner.stop();
506+
if (diagnostic.type === 'error') {
507+
hasErrors = true;
508+
context.logger.error(diagnostic.message);
509+
} else {
510+
context.logger.warn(diagnostic.message);
506511
}
512+
spinner.start();
507513
}
514+
}
508515

509-
// Copy any non-processed files into the output locations
510-
await copyAssets(
511-
[
512-
{
513-
glob: '**/*',
514-
input: webpackOutputPath,
515-
output: '',
516-
ignore: [...processedFiles].map((f) =>
517-
path.relative(webpackOutputPath, f),
518-
),
519-
},
520-
],
521-
Array.from(outputPaths.values()),
522-
'',
523-
);
524-
} catch (err) {
525-
spinner.fail('Localized bundle generation failed.');
516+
// Copy any non-processed files into the output locations
517+
await copyAssets(
518+
[
519+
{
520+
glob: '**/*',
521+
input: webpackOutputPath,
522+
output: '',
523+
ignore: [...processedFiles].map((f) =>
524+
path.relative(webpackOutputPath, f),
525+
),
526+
},
527+
],
528+
Array.from(outputPaths.values()),
529+
'',
530+
);
531+
} catch (err) {
532+
spinner.fail('Localized bundle generation failed.');
526533

527-
return { success: false, error: mapErrorToMessage(err) };
528-
}
534+
return { success: false, error: mapErrorToMessage(err) };
535+
} finally {
536+
i18nExecutor.stop();
537+
}
529538

530-
if (hasErrors) {
531-
spinner.fail('Localized bundle generation failed.');
532-
} else {
533-
spinner.succeed('Localized bundle generation complete.');
534-
}
539+
if (hasErrors) {
540+
spinner.fail('Localized bundle generation failed.');
541+
} else {
542+
spinner.succeed('Localized bundle generation complete.');
543+
}
535544

536-
if (hasErrors) {
537-
return { success: false };
538-
}
545+
if (hasErrors) {
546+
return { success: false };
539547
}
540-
} finally {
541-
executor.stop();
542548
}
549+
543550
for (const result of processResults) {
544551
const chunk = webpackStats.chunks?.find(
545552
(chunk) => chunk.id?.toString() === result.name,

0 commit comments

Comments
 (0)