@@ -10,14 +10,22 @@ import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/ar
1010import { runWebpack } from '@angular-devkit/build-webpack' ;
1111import * as path from 'path' ;
1212import { Observable , from } from 'rxjs' ;
13- import { concatMap , map } from 'rxjs/operators' ;
13+ import { concatMap } from 'rxjs/operators' ;
1414import webpack , { Configuration } from 'webpack' ;
1515import { ExecutionTransformer } from '../../transforms' ;
16- import { NormalizedBrowserBuilderSchema , deleteOutputDir } from '../../utils' ;
16+ import {
17+ NormalizedBrowserBuilderSchema ,
18+ deleteOutputDir ,
19+ normalizeAssetPatterns ,
20+ } from '../../utils' ;
21+ import { colors } from '../../utils/color' ;
22+ import { copyAssets } from '../../utils/copy-assets' ;
23+ import { assertIsError } from '../../utils/error' ;
1724import { i18nInlineEmittedFiles } from '../../utils/i18n-inlining' ;
1825import { I18nOptions } from '../../utils/i18n-options' ;
1926import { ensureOutputPaths } from '../../utils/output-paths' ;
2027import { purgeStaleBuildCache } from '../../utils/purge-cache' ;
28+ import { Spinner } from '../../utils/spinner' ;
2129import { assertCompatibleAngularVersion } from '../../utils/version' ;
2230import {
2331 BrowserWebpackConfigOptions ,
@@ -69,7 +77,7 @@ export function execute(
6977 let outputPaths : undefined | Map < string , string > ;
7078
7179 return from ( initialize ( options , context , transforms . webpackConfiguration ) ) . pipe (
72- concatMap ( ( { config, i18n } ) => {
80+ concatMap ( ( { config, i18n, projectRoot , projectSourceRoot } ) => {
7381 return runWebpack ( config , context , {
7482 webpackFactory : require ( 'webpack' ) as typeof webpack ,
7583 logging : ( stats , config ) => {
@@ -84,11 +92,43 @@ export function execute(
8492 throw new Error ( 'Webpack stats build result is required.' ) ;
8593 }
8694
87- let success = output . success ;
88- if ( success && i18n . shouldInline ) {
89- outputPaths = ensureOutputPaths ( baseOutputPath , i18n ) ;
95+ if ( ! output . success ) {
96+ return output ;
97+ }
9098
91- success = await i18nInlineEmittedFiles (
99+ const spinner = new Spinner ( ) ;
100+ spinner . enabled = options . progress !== false ;
101+ outputPaths = ensureOutputPaths ( baseOutputPath , i18n ) ;
102+
103+ // Copy assets
104+ if ( ! options . watch && options . assets ?. length ) {
105+ spinner . start ( 'Copying assets...' ) ;
106+ try {
107+ await copyAssets (
108+ normalizeAssetPatterns (
109+ options . assets ,
110+ context . workspaceRoot ,
111+ projectRoot ,
112+ projectSourceRoot ,
113+ ) ,
114+ Array . from ( outputPaths . values ( ) ) ,
115+ context . workspaceRoot ,
116+ ) ;
117+ spinner . succeed ( 'Copying assets complete.' ) ;
118+ } catch ( err ) {
119+ spinner . fail ( colors . redBright ( 'Copying of assets failed.' ) ) ;
120+ assertIsError ( err ) ;
121+
122+ return {
123+ ...output ,
124+ success : false ,
125+ error : 'Unable to copy assets: ' + err . message ,
126+ } ;
127+ }
128+ }
129+
130+ if ( i18n . shouldInline ) {
131+ const success = await i18nInlineEmittedFiles (
92132 context ,
93133 emittedFiles ,
94134 i18n ,
@@ -98,15 +138,21 @@ export function execute(
98138 outputPath ,
99139 options . i18nMissingTranslation ,
100140 ) ;
141+ if ( ! success ) {
142+ return {
143+ ...output ,
144+ success : false ,
145+ } ;
146+ }
101147 }
102148
103149 webpackStatsLogger ( context . logger , webpackStats , config ) ;
104150
105- return { ... output , success } ;
151+ return output ;
106152 } ) ,
107153 ) ;
108154 } ) ,
109- map ( ( output ) => {
155+ concatMap ( async ( output ) => {
110156 if ( ! output . success ) {
111157 return output as ServerBuilderOutput ;
112158 }
@@ -137,36 +183,42 @@ async function initialize(
137183) : Promise < {
138184 config : webpack . Configuration ;
139185 i18n : I18nOptions ;
186+ projectRoot : string ;
187+ projectSourceRoot ?: string ;
140188} > {
141189 // Purge old build disk cache.
142190 await purgeStaleBuildCache ( context ) ;
143191
144192 const browserslist = ( await import ( 'browserslist' ) ) . default ;
145193 const originalOutputPath = options . outputPath ;
146- const { config, i18n } = await generateI18nBrowserWebpackConfigFromContext (
147- {
148- ...options ,
149- buildOptimizer : false ,
150- aot : true ,
151- platform : 'server' ,
152- } as NormalizedBrowserBuilderSchema ,
153- context ,
154- ( wco ) => {
155- // We use the platform to determine the JavaScript syntax output.
156- wco . buildOptions . supportedBrowsers ??= [ ] ;
157- wco . buildOptions . supportedBrowsers . push ( ...browserslist ( 'maintained node versions' ) ) ;
158-
159- return [ getPlatformServerExportsConfig ( wco ) , getCommonConfig ( wco ) , getStylesConfig ( wco ) ] ;
160- } ,
161- ) ;
194+ // Assets are processed directly by the builder except when watching
195+ const adjustedOptions = options . watch ? options : { ...options , assets : [ ] } ;
196+
197+ const { config, projectRoot, projectSourceRoot, i18n } =
198+ await generateI18nBrowserWebpackConfigFromContext (
199+ {
200+ ...adjustedOptions ,
201+ buildOptimizer : false ,
202+ aot : true ,
203+ platform : 'server' ,
204+ } as NormalizedBrowserBuilderSchema ,
205+ context ,
206+ ( wco ) => {
207+ // We use the platform to determine the JavaScript syntax output.
208+ wco . buildOptions . supportedBrowsers ??= [ ] ;
209+ wco . buildOptions . supportedBrowsers . push ( ...browserslist ( 'maintained node versions' ) ) ;
210+
211+ return [ getPlatformServerExportsConfig ( wco ) , getCommonConfig ( wco ) , getStylesConfig ( wco ) ] ;
212+ } ,
213+ ) ;
162214
163215 if ( options . deleteOutputPath ) {
164216 deleteOutputDir ( context . workspaceRoot , originalOutputPath ) ;
165217 }
166218
167219 const transformedConfig = ( await webpackConfigurationTransform ?.( config ) ) ?? config ;
168220
169- return { config : transformedConfig , i18n } ;
221+ return { config : transformedConfig , i18n, projectRoot , projectSourceRoot } ;
170222}
171223
172224/**
0 commit comments