From 79af1fbd407a46af336d09a9f8b00c9ea83c536a Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 22 Jun 2020 14:58:56 -0400 Subject: [PATCH] fix(@angular-devkit/build-angular): use copy-on-write asset processing for non-watch builds Optimized asset processing was only being performed when differential loading was enabled. This change ensures that the optimized approach is used for non-watch builds. This does not affect `ng serve` usage since it currently requires all application files to be in memory. (cherry picked from commit 3c734a89e1d9fa32a5e2cd0ca617d5afd383e3d8) --- .../build_angular/src/browser/index.ts | 63 ++++++++++++------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/browser/index.ts b/packages/angular_devkit/build_angular/src/browser/index.ts index 7a61b94a5e2b..87d8a4eb46bd 100644 --- a/packages/angular_devkit/build_angular/src/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/browser/index.ts @@ -201,12 +201,31 @@ async function initialize( i18n: I18nOptions; }> { const originalOutputPath = options.outputPath; + + // Assets are processed directly by the builder except when watching + const adjustedOptions = options.watch ? options : { ...options, assets: [] }; + const { config, projectRoot, projectSourceRoot, i18n, - } = await buildBrowserWebpackConfigFromContext(options, context, host, true); + } = await buildBrowserWebpackConfigFromContext(adjustedOptions, context, host, true); + + // Validate asset option values if processed directly + if (options.assets?.length && !adjustedOptions.assets?.length) { + normalizeAssetPatterns( + options.assets, + new virtualFs.SyncDelegateHost(host), + normalize(context.workspaceRoot), + normalize(projectRoot), + projectSourceRoot === undefined ? undefined : normalize(projectSourceRoot), + ).forEach(({ output }) => { + if (output.startsWith('..')) { + throw new Error('An asset cannot be written to a location outside of the output path.'); + } + }); + } let transformedConfig; if (webpackConfigurationTransform) { @@ -573,27 +592,6 @@ export function buildWebpackBrowser( executor.stop(); } - // Copy assets - if (options.assets) { - try { - await copyAssets( - normalizeAssetPatterns( - options.assets, - new virtualFs.SyncDelegateHost(host), - root, - normalize(projectRoot), - projectSourceRoot === undefined ? undefined : normalize(projectSourceRoot), - ), - Array.from(outputPaths.values()), - context.workspaceRoot, - ); - } catch (err) { - context.logger.error('Unable to copy assets: ' + err.message); - - return { success: false }; - } - } - type ArrayElement = A extends ReadonlyArray ? T : never; function generateBundleInfoStats( id: string | number, @@ -698,6 +696,27 @@ export function buildWebpackBrowser( } } + // Copy assets + if (!options.watch && options.assets) { + try { + await copyAssets( + normalizeAssetPatterns( + options.assets, + new virtualFs.SyncDelegateHost(host), + root, + normalize(projectRoot), + projectSourceRoot === undefined ? undefined : normalize(projectSourceRoot), + ), + Array.from(outputPaths.values()), + context.workspaceRoot, + ); + } catch (err) { + context.logger.error('Unable to copy assets: ' + err.message); + + return { success: false }; + } + } + if (options.index) { for (const [locale, outputPath] of outputPaths.entries()) { let localeBaseHref;