8
8
9
9
import { readFile } from 'node:fs/promises' ;
10
10
import { join } from 'node:path' ;
11
- import type { Connect , InlineConfig } from 'vite' ;
11
+ import type { Connect , InlineConfig , SSROptions , ServerOptions } from 'vite' ;
12
12
import type { ComponentStyleRecord } from '../../../tools/vite/middlewares' ;
13
13
import {
14
14
ServerSsrMode ,
@@ -25,7 +25,116 @@ import { type ApplicationBuilderInternalOptions, JavaScriptTransformer } from '.
25
25
import type { NormalizedDevServerOptions } from '../options' ;
26
26
import { DevServerExternalResultMetadata , OutputAssetRecord , OutputFileRecord } from './utils' ;
27
27
28
- // eslint-disable-next-line max-lines-per-function
28
+ async function createServerConfig (
29
+ serverOptions : NormalizedDevServerOptions ,
30
+ assets : Map < string , OutputAssetRecord > ,
31
+ ssrMode : ServerSsrMode ,
32
+ preTransformRequests : boolean ,
33
+ cacheDir : string ,
34
+ ) : Promise < ServerOptions > {
35
+ const proxy = await loadProxyConfiguration (
36
+ serverOptions . workspaceRoot ,
37
+ serverOptions . proxyConfig ,
38
+ ) ;
39
+
40
+ // Files used for SSR warmup.
41
+ let ssrFiles : string [ ] | undefined ;
42
+ switch ( ssrMode ) {
43
+ case ServerSsrMode . InternalSsrMiddleware :
44
+ ssrFiles = [ './main.server.mjs' ] ;
45
+ break ;
46
+ case ServerSsrMode . ExternalSsrMiddleware :
47
+ ssrFiles = [ './main.server.mjs' , './server.mjs' ] ;
48
+ break ;
49
+ }
50
+
51
+ const server : ServerOptions = {
52
+ preTransformRequests,
53
+ warmup : {
54
+ ssrFiles,
55
+ } ,
56
+ port : serverOptions . port ,
57
+ strictPort : true ,
58
+ host : serverOptions . host ,
59
+ open : serverOptions . open ,
60
+ allowedHosts : serverOptions . allowedHosts ,
61
+ headers : serverOptions . headers ,
62
+ // Disable the websocket if live reload is disabled (false/undefined are the only valid values)
63
+ ws : serverOptions . liveReload === false && serverOptions . hmr === false ? false : undefined ,
64
+ // When server-side rendering (SSR) is enabled togather with SSL and Express is being used,
65
+ // we must configure Vite to use HTTP/1.1.
66
+ // This is necessary because Express does not support HTTP/2.
67
+ // We achieve this by defining an empty proxy.
68
+ // See: https://github.com/vitejs/vite/blob/c4b532cc900bf988073583511f57bd581755d5e3/packages/vite/src/node/http.ts#L106
69
+ proxy :
70
+ serverOptions . ssl && ssrMode === ServerSsrMode . ExternalSsrMiddleware ? ( proxy ?? { } ) : proxy ,
71
+ cors : {
72
+ // This will add the header `Access-Control-Allow-Origin: http://example.com`,
73
+ // where `http://example.com` is the requesting origin.
74
+ origin : true ,
75
+ // Allow preflight requests to be proxied.
76
+ preflightContinue : true ,
77
+ } ,
78
+ // File watching is handled by the build directly. `null` disables file watching for Vite.
79
+ watch : null ,
80
+ fs : {
81
+ // Ensure cache directory, node modules, and all assets are accessible by the client.
82
+ // The first two are required for Vite to function in prebundling mode (the default) and to load
83
+ // the Vite client-side code for browser reloading. These would be available by default but when
84
+ // the `allow` option is explicitly configured, they must be included manually.
85
+ allow : [
86
+ cacheDir ,
87
+ join ( serverOptions . workspaceRoot , 'node_modules' ) ,
88
+ ...[ ...assets . values ( ) ] . map ( ( { source } ) => source ) ,
89
+ ] ,
90
+ } ,
91
+ } ;
92
+
93
+ if ( serverOptions . ssl ) {
94
+ if ( serverOptions . sslCert && serverOptions . sslKey ) {
95
+ server . https = {
96
+ cert : await readFile ( serverOptions . sslCert ) ,
97
+ key : await readFile ( serverOptions . sslKey ) ,
98
+ } ;
99
+ }
100
+ }
101
+
102
+ return server ;
103
+ }
104
+
105
+ function createSsrConfig (
106
+ externalMetadata : DevServerExternalResultMetadata ,
107
+ serverOptions : NormalizedDevServerOptions ,
108
+ prebundleTransformer : JavaScriptTransformer ,
109
+ zoneless : boolean ,
110
+ target : string [ ] ,
111
+ prebundleLoaderExtensions : EsbuildLoaderOption | undefined ,
112
+ thirdPartySourcemaps : boolean ,
113
+ define : ApplicationBuilderInternalOptions [ 'define' ] ,
114
+ ) : SSROptions {
115
+ return {
116
+ // Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
117
+ noExternal : / .* / ,
118
+ // Exclude any Node.js built in module and provided dependencies (currently build defined externals)
119
+ external : externalMetadata . explicitServer ,
120
+ optimizeDeps : getDepOptimizationConfig ( {
121
+ // Only enable with caching since it causes prebundle dependencies to be cached
122
+ disabled : serverOptions . prebundle === false ,
123
+ // Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
124
+ exclude : externalMetadata . explicitServer ,
125
+ // Include all implict dependencies from the external packages internal option
126
+ include : externalMetadata . implicitServer ,
127
+ ssr : true ,
128
+ prebundleTransformer,
129
+ zoneless,
130
+ target,
131
+ loader : prebundleLoaderExtensions ,
132
+ thirdPartySourcemaps,
133
+ define,
134
+ } ) ,
135
+ } ;
136
+ }
137
+
29
138
export async function setupServer (
30
139
serverOptions : NormalizedDevServerOptions ,
31
140
outputFiles : Map < string , OutputFileRecord > ,
@@ -44,11 +153,6 @@ export async function setupServer(
44
153
indexHtmlTransformer ?: ( content : string ) => Promise < string > ,
45
154
thirdPartySourcemaps = false ,
46
155
) : Promise < InlineConfig > {
47
- const proxy = await loadProxyConfiguration (
48
- serverOptions . workspaceRoot ,
49
- serverOptions . proxyConfig ,
50
- ) ;
51
-
52
156
// dynamically import Vite for ESM compatibility
53
157
const { normalizePath } = await loadEsmModule < typeof import ( 'vite' ) > ( 'vite' ) ;
54
158
@@ -57,17 +161,6 @@ export async function setupServer(
57
161
join ( serverOptions . workspaceRoot , `.angular/vite-root` , serverOptions . buildTarget . project ) ,
58
162
) ;
59
163
60
- // Files used for SSR warmup.
61
- let ssrFiles : string [ ] | undefined ;
62
- switch ( ssrMode ) {
63
- case ServerSsrMode . InternalSsrMiddleware :
64
- ssrFiles = [ './main.server.mjs' ] ;
65
- break ;
66
- case ServerSsrMode . ExternalSsrMiddleware :
67
- ssrFiles = [ './main.server.mjs' , './server.mjs' ] ;
68
- break ;
69
- }
70
-
71
164
/**
72
165
* Required when using `externalDependencies` to prevent Vite load errors.
73
166
*
@@ -78,6 +171,7 @@ export async function setupServer(
78
171
const preTransformRequests =
79
172
externalMetadata . explicitBrowser . length === 0 && ssrMode === ServerSsrMode . NoSsr ;
80
173
const cacheDir = join ( serverOptions . cacheOptions . path , serverOptions . buildTarget . project , 'vite' ) ;
174
+
81
175
const configuration : InlineConfig = {
82
176
configFile : false ,
83
177
envFile : false ,
@@ -109,70 +203,23 @@ export async function setupServer(
109
203
dev : {
110
204
preTransformRequests,
111
205
} ,
112
- server : {
206
+ server : await createServerConfig (
207
+ serverOptions ,
208
+ assets ,
209
+ ssrMode ,
113
210
preTransformRequests ,
114
- warmup : {
115
- ssrFiles,
116
- } ,
117
- port : serverOptions . port ,
118
- strictPort : true ,
119
- host : serverOptions . host ,
120
- open : serverOptions . open ,
121
- allowedHosts : serverOptions . allowedHosts ,
122
- headers : serverOptions . headers ,
123
- // Disable the websocket if live reload is disabled (false/undefined are the only valid values)
124
- ws : serverOptions . liveReload === false && serverOptions . hmr === false ? false : undefined ,
125
- // When server-side rendering (SSR) is enabled togather with SSL and Express is being used,
126
- // we must configure Vite to use HTTP/1.1.
127
- // This is necessary because Express does not support HTTP/2.
128
- // We achieve this by defining an empty proxy.
129
- // See: https://github.com/vitejs/vite/blob/c4b532cc900bf988073583511f57bd581755d5e3/packages/vite/src/node/http.ts#L106
130
- proxy :
131
- serverOptions . ssl && ssrMode === ServerSsrMode . ExternalSsrMiddleware
132
- ? ( proxy ?? { } )
133
- : proxy ,
134
- cors : {
135
- // This will add the header `Access-Control-Allow-Origin: http://example.com`,
136
- // where `http://example.com` is the requesting origin.
137
- origin : true ,
138
- // Allow preflight requests to be proxied.
139
- preflightContinue : true ,
140
- } ,
141
- // File watching is handled by the build directly. `null` disables file watching for Vite.
142
- watch : null ,
143
- fs : {
144
- // Ensure cache directory, node modules, and all assets are accessible by the client.
145
- // The first two are required for Vite to function in prebundling mode (the default) and to load
146
- // the Vite client-side code for browser reloading. These would be available by default but when
147
- // the `allow` option is explicitly configured, they must be included manually.
148
- allow : [
149
- cacheDir ,
150
- join ( serverOptions . workspaceRoot , 'node_modules' ) ,
151
- ...[ ...assets . values ( ) ] . map ( ( { source } ) => source ) ,
152
- ] ,
153
- } ,
154
- } ,
155
- ssr : {
156
- // Note: `true` and `/.*/` have different sematics. When true, the `external` option is ignored.
157
- noExternal : / .* / ,
158
- // Exclude any Node.js built in module and provided dependencies (currently build defined externals)
159
- external : externalMetadata . explicitServer ,
160
- optimizeDeps : getDepOptimizationConfig ( {
161
- // Only enable with caching since it causes prebundle dependencies to be cached
162
- disabled : serverOptions . prebundle === false ,
163
- // Exclude any explicitly defined dependencies (currently build defined externals and node.js built-ins)
164
- exclude : externalMetadata . explicitServer ,
165
- // Include all implict dependencies from the external packages internal option
166
- include : externalMetadata . implicitServer ,
167
- ssr : true ,
168
- prebundleTransformer,
169
- zoneless,
170
- target,
171
- loader : prebundleLoaderExtensions ,
172
- thirdPartySourcemaps,
173
- define,
174
- } ) ,
175
- } ,
211
+ cacheDir ,
212
+ ) ,
213
+ ssr : createSsrConfig (
214
+ externalMetadata ,
215
+ serverOptions ,
216
+ prebundleTransformer ,
217
+ zoneless ,
218
+ target ,
219
+ prebundleLoaderExtensions ,
220
+ thirdPartySourcemaps ,
221
+ define ,
222
+ ) ,
176
223
plugins : [
177
224
createAngularLocaleDataPlugin ( ) ,
178
225
createAngularSetupMiddlewaresPlugin ( {
@@ -215,14 +262,7 @@ export async function setupServer(
215
262
} ;
216
263
217
264
if ( serverOptions . ssl ) {
218
- if ( serverOptions . sslCert && serverOptions . sslKey ) {
219
- configuration . server ??= { } ;
220
- // server configuration is defined above
221
- configuration . server . https = {
222
- cert : await readFile ( serverOptions . sslCert ) ,
223
- key : await readFile ( serverOptions . sslKey ) ,
224
- } ;
225
- } else {
265
+ if ( ! serverOptions . sslCert || ! serverOptions . sslKey ) {
226
266
const { default : basicSslPlugin } = await import ( '@vitejs/plugin-basic-ssl' ) ;
227
267
configuration . plugins ??= [ ] ;
228
268
configuration . plugins . push ( basicSslPlugin ( ) ) ;
0 commit comments