Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): use a separate worker pool for i1…
Browse files Browse the repository at this point in the history
…8n 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.
  • Loading branch information
clydin committed Oct 18, 2021
1 parent 2109a09 commit 8d52d9b
Showing 1 changed file with 107 additions and 100 deletions.
207 changes: 107 additions & 100 deletions packages/angular_devkit/build_angular/src/browser/index.ts
Expand Up @@ -417,129 +417,136 @@ export function buildWebpackBrowser(
}
}

const executor = new BundleActionExecutor(
const differentialLoadingExecutor = new BundleActionExecutor(
{ cachePath: cacheDownlevelPath, i18n },
options.subresourceIntegrity ? 'sha384' : undefined,
);

// Execute the bundle processing actions
try {
spinner.start('Generating ES5 bundles for differential loading...');
for await (const result of executor.processAll(processActions)) {
for await (const result of differentialLoadingExecutor.processAll(
processActions,
)) {
processResults.push(result);
}
} finally {
differentialLoadingExecutor.stop();
}

// Runtime must be processed after all other files
if (processRuntimeAction) {
const runtimeOptions = {
...processRuntimeAction,
runtimeData: processResults,
supportedBrowsers: buildBrowserFeatures.supportedBrowsers,
};
processResults.push(
await import('../utils/process-bundle').then((m) =>
m.process(runtimeOptions),
),
);
}
// Runtime must be processed after all other files
if (processRuntimeAction) {
const runtimeOptions = {
...processRuntimeAction,
runtimeData: processResults,
supportedBrowsers: buildBrowserFeatures.supportedBrowsers,
};
processResults.push(
await import('../utils/process-bundle').then((m) => m.process(runtimeOptions)),
);
}

spinner.succeed('ES5 bundle generation complete.');

if (i18n.shouldInline) {
spinner.start('Generating localized bundles...');
const inlineActions: InlineOptions[] = [];
const processedFiles = new Set<string>();
for (const result of processResults) {
if (result.original) {
inlineActions.push({
filename: path.basename(result.original.filename),
code: fs.readFileSync(result.original.filename, 'utf8'),
map:
result.original.map &&
fs.readFileSync(result.original.map.filename, 'utf8'),
outputPath: baseOutputPath,
es5: false,
missingTranslation: options.i18nMissingTranslation,
setLocale: result.name === mainChunkId,
});
processedFiles.add(result.original.filename);
if (result.original.map) {
processedFiles.add(result.original.map.filename);
}
spinner.succeed('ES5 bundle generation complete.');

if (i18n.shouldInline) {
spinner.start('Generating localized bundles...');
const inlineActions: InlineOptions[] = [];
const processedFiles = new Set<string>();
for (const result of processResults) {
if (result.original) {
inlineActions.push({
filename: path.basename(result.original.filename),
code: fs.readFileSync(result.original.filename, 'utf8'),
map:
result.original.map &&
fs.readFileSync(result.original.map.filename, 'utf8'),
outputPath: baseOutputPath,
es5: false,
missingTranslation: options.i18nMissingTranslation,
setLocale: result.name === mainChunkId,
});
processedFiles.add(result.original.filename);
if (result.original.map) {
processedFiles.add(result.original.map.filename);
}
if (result.downlevel) {
inlineActions.push({
filename: path.basename(result.downlevel.filename),
code: fs.readFileSync(result.downlevel.filename, 'utf8'),
map:
result.downlevel.map &&
fs.readFileSync(result.downlevel.map.filename, 'utf8'),
outputPath: baseOutputPath,
es5: true,
missingTranslation: options.i18nMissingTranslation,
setLocale: result.name === mainChunkId,
});
processedFiles.add(result.downlevel.filename);
if (result.downlevel.map) {
processedFiles.add(result.downlevel.map.filename);
}
}
if (result.downlevel) {
inlineActions.push({
filename: path.basename(result.downlevel.filename),
code: fs.readFileSync(result.downlevel.filename, 'utf8'),
map:
result.downlevel.map &&
fs.readFileSync(result.downlevel.map.filename, 'utf8'),
outputPath: baseOutputPath,
es5: true,
missingTranslation: options.i18nMissingTranslation,
setLocale: result.name === mainChunkId,
});
processedFiles.add(result.downlevel.filename);
if (result.downlevel.map) {
processedFiles.add(result.downlevel.map.filename);
}
}
}

let hasErrors = false;
try {
for await (const result of executor.inlineAll(inlineActions)) {
if (options.verbose) {
context.logger.info(
`Localized "${result.file}" [${result.count} translation(s)].`,
);
}
for (const diagnostic of result.diagnostics) {
spinner.stop();
if (diagnostic.type === 'error') {
hasErrors = true;
context.logger.error(diagnostic.message);
} else {
context.logger.warn(diagnostic.message);
}
spinner.start();
let hasErrors = false;
const i18nExecutor = new BundleActionExecutor(
{ i18n },
options.subresourceIntegrity ? 'sha384' : undefined,
);
try {
for await (const result of i18nExecutor.inlineAll(inlineActions)) {
if (options.verbose) {
context.logger.info(
`Localized "${result.file}" [${result.count} translation(s)].`,
);
}
for (const diagnostic of result.diagnostics) {
spinner.stop();
if (diagnostic.type === 'error') {
hasErrors = true;
context.logger.error(diagnostic.message);
} else {
context.logger.warn(diagnostic.message);
}
spinner.start();
}
}

// Copy any non-processed files into the output locations
await copyAssets(
[
{
glob: '**/*',
input: webpackOutputPath,
output: '',
ignore: [...processedFiles].map((f) =>
path.relative(webpackOutputPath, f),
),
},
],
Array.from(outputPaths.values()),
'',
);
} catch (err) {
spinner.fail('Localized bundle generation failed.');
// Copy any non-processed files into the output locations
await copyAssets(
[
{
glob: '**/*',
input: webpackOutputPath,
output: '',
ignore: [...processedFiles].map((f) =>
path.relative(webpackOutputPath, f),
),
},
],
Array.from(outputPaths.values()),
'',
);
} catch (err) {
spinner.fail('Localized bundle generation failed.');

return { success: false, error: mapErrorToMessage(err) };
}
return { success: false, error: mapErrorToMessage(err) };
} finally {
i18nExecutor.stop();
}

if (hasErrors) {
spinner.fail('Localized bundle generation failed.');
} else {
spinner.succeed('Localized bundle generation complete.');
}
if (hasErrors) {
spinner.fail('Localized bundle generation failed.');
} else {
spinner.succeed('Localized bundle generation complete.');
}

if (hasErrors) {
return { success: false };
}
if (hasErrors) {
return { success: false };
}
} finally {
executor.stop();
}

for (const result of processResults) {
const chunk = webpackStats.chunks?.find(
(chunk) => chunk.id?.toString() === result.name,
Expand Down

0 comments on commit 8d52d9b

Please sign in to comment.