7
7
*/
8
8
9
9
import { BuilderContext } from '@angular-devkit/architect' ;
10
+ import assert from 'node:assert' ;
10
11
import { SourceFileCache } from '../../tools/esbuild/angular/compiler-plugin' ;
11
12
import {
12
13
createBrowserCodeBundleOptions ,
@@ -26,10 +27,13 @@ import {
26
27
transformSupportedBrowsersToTargets ,
27
28
} from '../../tools/esbuild/utils' ;
28
29
import { copyAssets } from '../../utils/copy-assets' ;
30
+ import { maxWorkers } from '../../utils/environment-options' ;
29
31
import { augmentAppWithServiceWorkerEsbuild } from '../../utils/service-worker' ;
32
+ import { prerenderPages } from '../../utils/ssg/render' ;
30
33
import { getSupportedBrowsers } from '../../utils/supported-browsers' ;
31
34
import { NormalizedApplicationBuildOptions } from './options' ;
32
35
36
+ // eslint-disable-next-line max-lines-per-function
33
37
export async function executeBuild (
34
38
options : NormalizedApplicationBuildOptions ,
35
39
context : BuilderContext ,
@@ -46,6 +50,8 @@ export async function executeBuild(
46
50
assets,
47
51
indexHtmlOptions,
48
52
cacheOptions,
53
+ prerenderOptions,
54
+ appShellOptions,
49
55
} = options ;
50
56
51
57
const browsers = getSupportedBrowsers ( projectRoot , context . logger ) ;
@@ -138,21 +144,58 @@ export async function executeBuild(
138
144
await logMessages ( context , { warnings : messages } ) ;
139
145
}
140
146
147
+ /**
148
+ * Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
149
+ *
150
+ * NOTE: we don't perform critical CSS inlining as this will be done during server rendering.
151
+ */
152
+ let indexContentOutputNoCssInlining : string | undefined ;
153
+
141
154
// Generate index HTML file
142
155
if ( indexHtmlOptions ) {
143
- const { errors , warnings , content } = await generateIndexHtml (
156
+ const { content , contentWithoutCriticalCssInlined , errors , warnings } = await generateIndexHtml (
144
157
initialFiles ,
145
158
executionResult ,
146
- options ,
159
+ {
160
+ ...options ,
161
+ optimizationOptions,
162
+ } ,
147
163
) ;
148
- for ( const error of errors ) {
149
- context . logger . error ( error ) ;
150
- }
151
- for ( const warning of warnings ) {
152
- context . logger . warn ( warning ) ;
153
- }
164
+
165
+ indexContentOutputNoCssInlining = contentWithoutCriticalCssInlined ;
166
+ printWarningsAndErrorsToConsole ( context , warnings , errors ) ;
154
167
155
168
executionResult . addOutputFile ( indexHtmlOptions . output , content ) ;
169
+
170
+ if ( serverEntryPoint ) {
171
+ // TODO only add the below file when SSR is enabled.
172
+ executionResult . addOutputFile ( 'index.server.html' , contentWithoutCriticalCssInlined ) ;
173
+ }
174
+ }
175
+
176
+ // Pre-render (SSG) and App-shell
177
+ if ( prerenderOptions || appShellOptions ) {
178
+ assert (
179
+ indexContentOutputNoCssInlining ,
180
+ 'The "index" option is required when using the "ssg" or "appShell" options.' ,
181
+ ) ;
182
+
183
+ const { output, warnings, errors } = await prerenderPages (
184
+ workspaceRoot ,
185
+ options . tsconfig ,
186
+ appShellOptions ,
187
+ prerenderOptions ,
188
+ executionResult . outputFiles ,
189
+ indexContentOutputNoCssInlining ,
190
+ optimizationOptions . styles . inlineCritical ,
191
+ maxWorkers ,
192
+ ) ;
193
+
194
+ printWarningsAndErrorsToConsole ( context , warnings , errors ) ;
195
+
196
+ for ( const [ path , content ] of Object . entries ( output ) ) {
197
+ executionResult . addOutputFile ( path , content ) ;
198
+ }
156
199
}
157
200
158
201
// Copy assets
@@ -206,3 +249,16 @@ export async function executeBuild(
206
249
207
250
return executionResult ;
208
251
}
252
+
253
+ function printWarningsAndErrorsToConsole (
254
+ context : BuilderContext ,
255
+ warnings : string [ ] ,
256
+ errors : string [ ] ,
257
+ ) : void {
258
+ for ( const error of errors ) {
259
+ context . logger . error ( error ) ;
260
+ }
261
+ for ( const warning of warnings ) {
262
+ context . logger . warn ( warning ) ;
263
+ }
264
+ }
0 commit comments