Skip to content

Commit 283fea3

Browse files
committed
refactor(optimizer): input and q-manifest handling
- saner default input handling - do not write q-manifest to temp dir - try reading manifest on every platform that has the `node:fs` module
1 parent b985de7 commit 283fea3

File tree

9 files changed

+201
-185
lines changed

9 files changed

+201
-185
lines changed

.changeset/short-suits-bet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': minor
3+
---
4+
5+
FIX: `qwikVite` has better vite config handling around input files, and no longer writes the q-manifest file to a temp dir.

packages/qwik/src/optimizer/src/plugins/plugin.ts

Lines changed: 114 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
107107
target: 'client',
108108
buildMode: 'development',
109109
debug: false,
110-
rootDir: null as any,
110+
rootDir: undefined as any,
111111
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,
115115
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,
119120
sourcemap: !!optimizerOptions.sourcemap,
120121
manifestInput: null,
121122
manifestOutput: null,
@@ -131,10 +132,16 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
131132
};
132133

133134
let lazyNormalizePath: (id: string) => string;
135+
let maybeFs: typeof import('fs') | undefined;
134136
const init = async () => {
135137
if (!internalOptimizer) {
136138
internalOptimizer = await createOptimizer(optimizerOptions);
137139
lazyNormalizePath = makeNormalizePath(internalOptimizer.sys);
140+
try {
141+
maybeFs = await internalOptimizer.sys.dynamicImport('node:fs');
142+
} catch {
143+
// ignore
144+
}
138145
}
139146
};
140147

@@ -161,7 +168,9 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
161168
};
162169

163170
/** 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> => {
165174
const updatedOpts: QwikPluginOptions = Object.assign({}, inputOpts);
166175

167176
const optimizer = getOptimizer();
@@ -229,45 +238,74 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
229238
opts.tsconfigFileNames = updatedOpts.tsconfigFileNames;
230239
}
231240

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!;
249252
}
253+
}
250254

251-
if (typeof updatedOpts.outDir === 'string') {
255+
if (!updatedOpts.csr) {
256+
if (updatedOpts.outDir) {
257+
// forced output directory
252258
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;
261277
}
262278
}
263279

264280
if (typeof updatedOpts.manifestOutput === 'function') {
265281
opts.manifestOutput = updatedOpts.manifestOutput;
266282
}
267283

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+
}
271309
}
272310

273311
if (typeof updatedOpts.transformedModuleOutput === 'function') {
@@ -276,6 +314,36 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
276314

277315
if (updatedOpts.scope !== undefined) {
278316
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+
}
279347
}
280348

281349
if (typeof updatedOpts.resolveQwikBuild === 'boolean') {
@@ -867,6 +935,7 @@ export function createQwikPlugin(optimizerOptions: OptimizerOptions = {}) {
867935
diagnosticsCallback = cb;
868936
};
869937

938+
/** Convert windows backslashes to forward slashes if possible */
870939
const normalizePath = (id: string) => lazyNormalizePath(id);
871940

872941
function getQwikBuildModule(isServer: boolean, _target: QwikBuildTarget) {
@@ -1005,9 +1074,6 @@ export const manifest = ${JSON.stringify(serverManifest)};\n`;
10051074
if (typeof opts.transformedModuleOutput === 'function') {
10061075
await opts.transformedModuleOutput(getTransformedOutputs());
10071076
}
1008-
1009-
// TODO get rid of this with the vite environment api
1010-
return manifestStr;
10111077
}
10121078

10131079
return {
@@ -1123,6 +1189,8 @@ export interface QwikPluginOptions {
11231189
manifestInput?: QwikManifest | null;
11241190
input?: string[] | string | { [entry: string]: string };
11251191
outDir?: string;
1192+
ssrOutDir?: string;
1193+
clientOutDir?: string;
11261194
assetsDir?: string;
11271195
srcDir?: string | null;
11281196
scope?: string | null;
@@ -1154,9 +1222,12 @@ export interface QwikPluginOptions {
11541222
}
11551223

11561224
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;
11601231
}
11611232

11621233
export type QwikPlugin = ReturnType<typeof createQwikPlugin>;

0 commit comments

Comments
 (0)