@@ -12,17 +12,25 @@ import {
12
12
BuildOutputFileType ,
13
13
InitialFileRecord ,
14
14
} from '../../tools/esbuild/bundler-context' ;
15
- import { BuildOutputAsset } from '../../tools/esbuild/bundler-execution-result' ;
15
+ import {
16
+ BuildOutputAsset ,
17
+ PrerenderedRoutesRecord ,
18
+ } from '../../tools/esbuild/bundler-execution-result' ;
16
19
import { generateIndexHtml } from '../../tools/esbuild/index-html-generator' ;
17
20
import { createOutputFile } from '../../tools/esbuild/utils' ;
18
21
import { maxWorkers } from '../../utils/environment-options' ;
22
+ import { loadEsmModule } from '../../utils/load-esm' ;
19
23
import {
20
24
SERVER_APP_MANIFEST_FILENAME ,
21
25
generateAngularServerAppManifest ,
22
26
} from '../../utils/server-rendering/manifest' ;
23
27
import { prerenderPages } from '../../utils/server-rendering/prerender' ;
28
+ import { RoutersExtractorWorkerResult as SerializableRouteTreeNode } from '../../utils/server-rendering/routes-extractor-worker' ;
24
29
import { augmentAppWithServiceWorkerEsbuild } from '../../utils/service-worker' ;
25
30
import { INDEX_HTML_SERVER , NormalizedApplicationBuildOptions } from './options' ;
31
+ import { OutputMode } from './schema' ;
32
+
33
+ type Writeable < T extends readonly unknown [ ] > = T extends readonly ( infer U ) [ ] ? U [ ] : never ;
26
34
27
35
/**
28
36
* Run additional builds steps including SSG, AppShell, Index HTML file and Service worker generation.
@@ -43,25 +51,26 @@ export async function executePostBundleSteps(
43
51
warnings : string [ ] ;
44
52
additionalOutputFiles : BuildOutputFile [ ] ;
45
53
additionalAssets : BuildOutputAsset [ ] ;
46
- prerenderedRoutes : string [ ] ;
54
+ prerenderedRoutes : PrerenderedRoutesRecord ;
47
55
} > {
48
56
const additionalAssets : BuildOutputAsset [ ] = [ ] ;
49
57
const additionalOutputFiles : BuildOutputFile [ ] = [ ] ;
50
58
const allErrors : string [ ] = [ ] ;
51
59
const allWarnings : string [ ] = [ ] ;
52
- const prerenderedRoutes : string [ ] = [ ] ;
60
+ const prerenderedRoutes : PrerenderedRoutesRecord = { } ;
53
61
54
62
const {
55
63
baseHref = '/' ,
56
64
serviceWorker,
57
65
indexHtmlOptions,
58
66
optimizationOptions,
59
67
sourcemapOptions,
60
- ssrOptions,
68
+ outputMode,
69
+ serverEntryPoint,
61
70
prerenderOptions,
62
71
appShellOptions,
63
72
workspaceRoot,
64
- verbose ,
73
+ disableFullServerManifestGeneration ,
65
74
} = options ;
66
75
67
76
// Index HTML content without CSS inlining to be used for server rendering (AppShell, SSG and SSR).
@@ -97,7 +106,7 @@ export async function executePostBundleSteps(
97
106
}
98
107
99
108
// Create server manifest
100
- if ( prerenderOptions || appShellOptions || ssrOptions ) {
109
+ if ( serverEntryPoint ) {
101
110
additionalOutputFiles . push (
102
111
createOutputFile (
103
112
SERVER_APP_MANIFEST_FILENAME ,
@@ -114,36 +123,32 @@ export async function executePostBundleSteps(
114
123
115
124
// Pre-render (SSG) and App-shell
116
125
// If localization is enabled, prerendering is handled in the inlining process.
117
- if ( ( prerenderOptions || appShellOptions ) && ! allErrors . length ) {
126
+ if (
127
+ ! disableFullServerManifestGeneration &&
128
+ ( prerenderOptions || appShellOptions || ( outputMode && serverEntryPoint ) ) &&
129
+ ! allErrors . length
130
+ ) {
118
131
assert (
119
132
indexHtmlOptions ,
120
133
'The "index" option is required when using the "ssg" or "appShell" options.' ,
121
134
) ;
122
135
123
- const {
124
- output,
125
- warnings,
126
- errors,
127
- prerenderedRoutes : generatedRoutes ,
128
- serializableRouteTreeNode,
129
- } = await prerenderPages (
136
+ const { output, warnings, errors, serializableRouteTreeNode } = await prerenderPages (
130
137
workspaceRoot ,
131
138
baseHref ,
132
139
appShellOptions ,
133
140
prerenderOptions ,
134
141
[ ...outputFiles , ...additionalOutputFiles ] ,
135
142
assetFiles ,
143
+ outputMode ,
136
144
sourcemapOptions . scripts ,
137
145
maxWorkers ,
138
- verbose ,
139
146
) ;
140
147
141
148
allErrors . push ( ...errors ) ;
142
149
allWarnings . push ( ...warnings ) ;
143
- prerenderedRoutes . push ( ...Array . from ( generatedRoutes ) ) ;
144
-
145
- const indexHasBeenPrerendered = generatedRoutes . has ( indexHtmlOptions . output ) ;
146
150
151
+ const indexHasBeenPrerendered = output [ indexHtmlOptions . output ] ;
147
152
for ( const [ path , { content, appShellRoute } ] of Object . entries ( output ) ) {
148
153
// Update the index contents with the app shell under these conditions:
149
154
// - Replace 'index.html' with the app shell only if it hasn't been prerendered yet.
@@ -155,7 +160,24 @@ export async function executePostBundleSteps(
155
160
) ;
156
161
}
157
162
158
- if ( ssrOptions ) {
163
+ const { RenderMode } = await loadEsmModule < typeof import ( '@angular/ssr' ) > ( '@angular/ssr' ) ;
164
+ const serializableRouteTreeNodeForManifest : Writeable < SerializableRouteTreeNode > = [ ] ;
165
+
166
+ for ( const metadata of serializableRouteTreeNode ) {
167
+ switch ( metadata . renderMode ) {
168
+ case RenderMode . Prerender :
169
+ prerenderedRoutes [ metadata . route ] = { headers : metadata . headers } ;
170
+ break ;
171
+
172
+ case RenderMode . Server :
173
+ case RenderMode . Client :
174
+ serializableRouteTreeNodeForManifest . push ( metadata ) ;
175
+
176
+ break ;
177
+ }
178
+ }
179
+
180
+ if ( outputMode === OutputMode . Server ) {
159
181
// Regenerate the manifest to append route tree. This is only needed if SSR is enabled.
160
182
const manifest = additionalOutputFiles . find ( ( f ) => f . path === SERVER_APP_MANIFEST_FILENAME ) ;
161
183
assert ( manifest , `${ SERVER_APP_MANIFEST_FILENAME } was not found in output files.` ) ;
@@ -165,7 +187,7 @@ export async function executePostBundleSteps(
165
187
additionalHtmlOutputFiles ,
166
188
outputFiles ,
167
189
optimizationOptions . styles . inlineCritical ?? false ,
168
- serializableRouteTreeNode ,
190
+ serializableRouteTreeNodeForManifest ,
169
191
) ,
170
192
) ;
171
193
}
0 commit comments