@@ -107,15 +107,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
107
107
target : 'client' ,
108
108
buildMode : 'development' ,
109
109
debug : false ,
110
- rootDir : null as any ,
110
+ rootDir : undefined as any ,
111
111
tsconfigFileNames : [ './tsconfig.json' ] ,
112
- input : null as any ,
113
- outDir : '' ,
114
- assetsDir : null as any ,
112
+ input : undefined as any ,
113
+ outDir : undefined as any ,
114
+ assetsDir : undefined as any ,
115
115
resolveQwikBuild : true ,
116
- entryStrategy : null as any ,
117
- srcDir : null as any ,
118
- srcInputs : null as any ,
116
+ entryStrategy : undefined as any ,
117
+ srcDir : undefined as any ,
118
+ ssrOutDir : undefined as any ,
119
+ clientOutDir : undefined as any ,
119
120
sourcemap : ! ! optimizerOptions . sourcemap ,
120
121
manifestInput : null ,
121
122
manifestOutput : null ,
@@ -131,10 +132,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
131
132
} ;
132
133
133
134
let lazyNormalizePath : ( id : string ) => string ;
135
+ let maybeFs : typeof import ( 'fs' ) | undefined ;
134
136
const init = async ( ) => {
135
137
if ( ! internalOptimizer ) {
136
138
internalOptimizer = await createOptimizer ( optimizerOptions ) ;
137
139
lazyNormalizePath = makeNormalizePath ( internalOptimizer . sys ) ;
140
+ try {
141
+ maybeFs = await internalOptimizer . sys . dynamicImport ( 'node:fs' ) ;
142
+ } catch {
143
+ // ignore
144
+ }
138
145
}
139
146
} ;
140
147
@@ -161,7 +168,9 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
161
168
} ;
162
169
163
170
/** Note that as a side-effect this updates the internal plugin `opts` */
164
- const normalizeOptions = ( inputOpts ?: QwikPluginOptions ) => {
171
+ const normalizeOptions = async (
172
+ inputOpts ?: QwikPluginOptions
173
+ ) : Promise < NormalizedQwikPluginOptions > => {
165
174
const updatedOpts : QwikPluginOptions = Object . assign ( { } , inputOpts ) ;
166
175
167
176
const optimizer = getOptimizer ( ) ;
@@ -229,45 +238,74 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
229
238
opts . tsconfigFileNames = updatedOpts . tsconfigFileNames ;
230
239
}
231
240
232
- if ( ! updatedOpts . csr ) {
233
- if ( ! updatedOpts . input ) {
234
- if ( opts . target === 'ssr' ) {
235
- // ssr input default - should actually never be used
236
- const ssrInput = path . resolve ( srcDir , 'entry.ssr' ) ;
237
- opts . input = [ ssrInput ] ;
238
- } else if ( opts . target === 'client' ) {
239
- // client input default
240
- const clientInput = path . resolve ( srcDir , 'root' ) ;
241
- opts . input = [ clientInput ] ;
242
- } else if ( opts . target === 'lib' ) {
243
- // lib input default
244
- const libInput = path . resolve ( srcDir , 'index.ts' ) ;
245
- opts . input = [ libInput ] ;
246
- } else {
247
- opts . input = undefined ! ;
248
- }
241
+ if ( ! updatedOpts . input && ! opts . input ) {
242
+ // we only provide inputs if none were provided by the user
243
+ if ( opts . target === 'ssr' ) {
244
+ // this is for dev mode, prod will have own setting
245
+ opts . input = [ path . resolve ( srcDir , 'entry.ssr' ) ] ;
246
+ } else if ( opts . target === 'client' ) {
247
+ // not really an entry, just a starting point
248
+ opts . input = [ path . resolve ( srcDir , 'root' ) ] ;
249
+ } else {
250
+ // others including lib should be ok already
251
+ opts . input = undefined ! ;
249
252
}
253
+ }
250
254
251
- if ( typeof updatedOpts . outDir === 'string' ) {
255
+ if ( ! updatedOpts . csr ) {
256
+ if ( updatedOpts . outDir ) {
257
+ // forced output directory
252
258
opts . outDir = normalizePath ( path . resolve ( opts . rootDir , normalizePath ( updatedOpts . outDir ) ) ) ;
253
- } else if ( ! opts . outDir ) {
254
- if ( opts . target === 'ssr' ) {
255
- opts . outDir = normalizePath ( path . resolve ( opts . rootDir , SSR_OUT_DIR ) ) ;
256
- } else if ( opts . target === 'lib' ) {
257
- opts . outDir = normalizePath ( path . resolve ( opts . rootDir , LIB_OUT_DIR ) ) ;
258
- } else {
259
- opts . outDir = normalizePath ( path . resolve ( opts . rootDir , CLIENT_OUT_DIR ) ) ;
260
- }
259
+ }
260
+
261
+ // default output directory
262
+ opts . clientOutDir = normalizePath (
263
+ path . resolve ( opts . rootDir , updatedOpts . clientOutDir || CLIENT_OUT_DIR )
264
+ ) ;
265
+ opts . ssrOutDir = normalizePath (
266
+ path . resolve ( opts . rootDir , updatedOpts . ssrOutDir || SSR_OUT_DIR )
267
+ ) ;
268
+ if ( opts . target === 'ssr' ) {
269
+ // server
270
+ opts . outDir ||= opts . ssrOutDir ;
271
+ } else if ( opts . target === 'lib' ) {
272
+ // library
273
+ opts . outDir ||= normalizePath ( path . resolve ( opts . rootDir , LIB_OUT_DIR ) ) ;
274
+ } else {
275
+ // client
276
+ opts . outDir ||= opts . clientOutDir ;
261
277
}
262
278
}
263
279
264
280
if ( typeof updatedOpts . manifestOutput === 'function' ) {
265
281
opts . manifestOutput = updatedOpts . manifestOutput ;
266
282
}
267
283
268
- const clientManifest = getValidManifest ( updatedOpts . manifestInput ) ;
269
- if ( clientManifest ) {
270
- opts . manifestInput = clientManifest ;
284
+ if ( updatedOpts . manifestInput ) {
285
+ opts . manifestInput = getValidManifest ( updatedOpts . manifestInput ) || null ;
286
+ }
287
+ if (
288
+ ! opts . manifestInput &&
289
+ opts . target === 'ssr' &&
290
+ opts . buildMode === 'production' &&
291
+ maybeFs
292
+ ) {
293
+ let clientManifestPath = normalizePath ( path . resolve ( opts . clientOutDir , Q_MANIFEST_FILENAME ) ) ;
294
+ if ( ! ( await maybeFs . promises . stat ( clientManifestPath ) . catch ( ( ) => false ) ) ) {
295
+ clientManifestPath = normalizePath (
296
+ path . resolve ( opts . rootDir , CLIENT_OUT_DIR , Q_MANIFEST_FILENAME )
297
+ ) ;
298
+ }
299
+ try {
300
+ const clientManifestStr = await maybeFs . promises . readFile ( clientManifestPath , 'utf-8' ) ;
301
+ opts . manifestInput = getValidManifest ( JSON . parse ( clientManifestStr ) ) || null ;
302
+ // eslint-disable-next-line no-console
303
+ console . info ( 'Read client manifest from' , clientManifestPath ) ;
304
+ } catch ( e ) {
305
+ console . warn (
306
+ `could not read Qwik client manifest ${ clientManifestPath } , ignoring. Make sure you provide it to the SSR renderer. (${ e } )`
307
+ ) ;
308
+ }
271
309
}
272
310
273
311
if ( typeof updatedOpts . transformedModuleOutput === 'function' ) {
@@ -276,6 +314,36 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
276
314
277
315
if ( updatedOpts . scope !== undefined ) {
278
316
opts . scope = updatedOpts . scope ;
317
+ } else if ( ! opts . scope && maybeFs ) {
318
+ // Use the package name for the scope
319
+ let pkgPath = '' ;
320
+ try {
321
+ let pkgDir = opts . rootDir ;
322
+ while ( true ) {
323
+ pkgPath = path . resolve ( pkgDir , 'package.json' ) ;
324
+ if ( await maybeFs . promises . stat ( pkgPath ) . catch ( ( ) => false ) ) {
325
+ break ;
326
+ }
327
+ const parent = path . resolve ( pkgDir , '..' ) ;
328
+ if ( parent === pkgDir ) {
329
+ break ;
330
+ }
331
+ pkgDir = parent ;
332
+ pkgPath = '' ;
333
+ }
334
+
335
+ if ( pkgPath ) {
336
+ const pkgString = await maybeFs . promises . readFile ( pkgPath , 'utf-8' ) ;
337
+ const pkg = JSON . parse ( pkgString ) ;
338
+ if ( typeof pkg . name === 'string' ) {
339
+ opts . scope = pkg . name ;
340
+ }
341
+ }
342
+ } catch ( e ) {
343
+ console . warn (
344
+ `could not read ${ pkgPath || 'package.json' } to determine package name, ignoring. (${ e } )`
345
+ ) ;
346
+ }
279
347
}
280
348
281
349
if ( typeof updatedOpts . resolveQwikBuild === 'boolean' ) {
@@ -867,6 +935,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
867
935
diagnosticsCallback = cb ;
868
936
} ;
869
937
938
+ /** Convert windows backslashes to forward slashes if possible */
870
939
const normalizePath = ( id : string ) => lazyNormalizePath ( id ) ;
871
940
872
941
function getQwikBuildModule ( isServer : boolean , _target : QwikBuildTarget ) {
@@ -1005,9 +1074,6 @@ export const manifest = ${JSON.stringify(serverManifest)};\n`;
1005
1074
if ( typeof opts . transformedModuleOutput === 'function' ) {
1006
1075
await opts . transformedModuleOutput ( getTransformedOutputs ( ) ) ;
1007
1076
}
1008
-
1009
- // TODO get rid of this with the vite environment api
1010
- return manifestStr ;
1011
1077
}
1012
1078
1013
1079
return {
@@ -1123,6 +1189,8 @@ export interface QwikPluginOptions {
1123
1189
manifestInput ?: QwikManifest | null ;
1124
1190
input ?: string [ ] | string | { [ entry : string ] : string } ;
1125
1191
outDir ?: string ;
1192
+ ssrOutDir ?: string ;
1193
+ clientOutDir ?: string ;
1126
1194
assetsDir ?: string ;
1127
1195
srcDir ?: string | null ;
1128
1196
scope ?: string | null ;
@@ -1154,9 +1222,12 @@ export interface QwikPluginOptions {
1154
1222
}
1155
1223
1156
1224
export interface NormalizedQwikPluginOptions
1157
- extends Omit < Required < QwikPluginOptions > , 'vendorRoots' | 'experimental' > {
1158
- input : string [ ] | { [ entry : string ] : string } ;
1159
- experimental ?: Record < keyof typeof ExperimentalFeatures , boolean > ;
1225
+ extends Omit <
1226
+ Required < QwikPluginOptions > ,
1227
+ 'input' | 'vendorRoots' | 'srcInputs' | 'experimental'
1228
+ > {
1229
+ input : string [ ] | { [ entry : string ] : string } | undefined ;
1230
+ experimental : Record < keyof typeof ExperimentalFeatures , boolean > | undefined ;
1160
1231
}
1161
1232
1162
1233
export type QwikPlugin = ReturnType < typeof createQwikPlugin > ;
0 commit comments