Skip to content

Commit bce7eed

Browse files
committed
chore(vite): make devserver work
- support vite base - build qrls on demand
1 parent 416098b commit bce7eed

File tree

3 files changed

+69
-99
lines changed

3 files changed

+69
-99
lines changed

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

Lines changed: 32 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,6 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
296296
} else {
297297
opts.lint = updatedOpts.buildMode === 'development';
298298
}
299-
console.dir(opts);
300299
return { ...opts };
301300
};
302301

@@ -326,14 +325,9 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
326325
};
327326

328327
let didAddQwikEntries = false;
329-
const jsPacketIdSource = new Map<string, string>();
330328
const buildStart = async (ctx: Rollup.PluginContext) => {
331329
debug(`buildStart()`, opts.buildMode, opts.scope, opts.target);
332330
const optimizer = getOptimizer();
333-
// hmm
334-
// transformedOutputs.clear();
335-
// ssrTransformedOutputs.clear();
336-
337331
if (optimizer.sys.env === 'node' && opts.target === 'ssr' && opts.lint) {
338332
try {
339333
linter = await createLinter(optimizer.sys, opts.rootDir, opts.tsconfigFileNames);
@@ -388,38 +382,29 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
388382
moduleSideEffects: false,
389383
};
390384
}
391-
let firstInput: string;
392-
if (Array.isArray(opts.input)) {
393-
firstInput = opts.input[0];
394-
} else {
395-
firstInput = Object.values(opts.input)[0];
396-
}
385+
386+
const firstInput = Object.values(opts.input)[0];
397387
return {
398388
id: normalizePath(getPath().resolve(firstInput, QWIK_CLIENT_MANIFEST_ID)),
399389
moduleSideEffects: false,
400390
};
401391
}
402392

403393
const path = getPath();
404-
const isSSR = resolveOpts?.ssr ?? opts.target === 'ssr';
394+
const isSSR = !!resolveOpts?.ssr;
405395

406396
if (importer) {
407-
if (!isSSR && importer.endsWith('.html')) {
408-
const match = id.match(/.js?qrl=(.*)$/);
409-
console.log('dev server asking for jsPacket', path.isAbsolute(id), match);
410-
if (match) {
411-
const jsPacketId = match[1];
412-
const sourceId = jsPacketIdSource.get(jsPacketId);
413-
if (sourceId) {
414-
await ctx.load({ id: sourceId });
415-
// Now all jsPackets exist in the cache
416-
}
417-
}
418-
}
419-
// Only process relative links
420-
if (!id.startsWith('.') && (!path.isAbsolute(id) || !importer.endsWith('.html'))) {
397+
// Only process real files
398+
if (!(id.startsWith('.') || path.isAbsolute(id))) {
421399
return;
422400
}
401+
const match = /^([^?]*)\?_qrl_parent=/.exec(id);
402+
if (match) {
403+
// ssr mode asking for a client jsPacket, fall through to the devserver
404+
// building via ctx.load doesn't seem to work
405+
const packetId = `${opts.rootDir}${match[1]}`;
406+
return { id: packetId };
407+
}
423408
const parsedId = parseId(id);
424409
let importeePathId = normalizePath(parsedId.pathId);
425410
const ext = path.extname(importeePathId).toLowerCase();
@@ -462,6 +447,7 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
462447
}
463448
}
464449
}
450+
// we don't know what this is
465451
return null;
466452
};
467453
const load = async (
@@ -518,7 +504,7 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
518504
return generateQwikEntries(transformedOutputs);
519505
}
520506

521-
const isSSR = loadOpts?.ssr ?? opts.target === 'ssr';
507+
const isSSR = !!loadOpts?.ssr;
522508
if (opts.resolveQwikBuild && id.endsWith(QWIK_BUILD_ID)) {
523509
debug(`load()`, QWIK_BUILD_ID, opts.buildMode);
524510
return {
@@ -542,31 +528,22 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
542528

543529
if (transformedModule) {
544530
debug(`load()`, 'Found', id);
531+
let { code } = transformedModule[0];
532+
const { map, hook } = transformedModule[0];
545533

546-
let code = transformedModule[0].code;
547-
let firstInput: string;
548-
if (Array.isArray(opts.input)) {
549-
firstInput = opts.input[0];
550-
} else {
551-
firstInput = Object.values(opts.input)[0];
552-
}
553534
if (opts.target === 'ssr') {
535+
const firstInput = Object.values(opts.input)[0];
554536
// doing this because vite will not use resolveId() when "noExternal" is false
555537
// so we need to turn the @qwik-client-manifest import into a relative import
556538
code = code.replace(
557539
/@qwik-client-manifest/g,
558540
normalizePath(path.resolve(firstInput, QWIK_CLIENT_MANIFEST_ID))
559541
);
560542
}
561-
return {
562-
code,
563-
map: transformedModule[0].map,
564-
meta: {
565-
hook: transformedModule[0].hook,
566-
},
567-
};
543+
return { code, map, meta: { hook } };
568544
}
569545

546+
debug('load()', 'Not found', id);
570547
return null;
571548
};
572549

@@ -579,7 +556,7 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
579556
if (id.startsWith('\0') || id.startsWith('/@fs/')) {
580557
return;
581558
}
582-
const isSSR = transformOpts.ssr ?? opts.target === 'ssr';
559+
const isSSR = !!transformOpts.ssr;
583560
const currentOutputs = isSSR ? ssrTransformedOutputs : transformedOutputs;
584561
if (currentOutputs.has(id)) {
585562
return;
@@ -600,7 +577,17 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
600577
/** Strip client|server code from server|client */
601578
const strip = opts.target === 'client' || opts.target === 'ssr';
602579
const normalizedID = normalizePath(pathId);
603-
debug(`transform()`, 'Transforming', pathId);
580+
debug(
581+
`transform()`,
582+
'Transforming',
583+
pathId,
584+
id,
585+
parsedPathId,
586+
strip,
587+
isSSR,
588+
opts.srcDir,
589+
dir
590+
);
604591

605592
let filePath = base;
606593
if (opts.srcDir) {
@@ -663,47 +650,6 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
663650
ctx.addWatchFile(key);
664651
}
665652
}
666-
if (isSSR && strip) {
667-
// We also need a client build with the server code stripped
668-
// so that we know all the possible jsPackets that are used
669-
const clientTransformOpts: TransformModulesOptions = {
670-
input: [{ code, path: filePath }],
671-
entryStrategy: opts.entryStrategy,
672-
minify: 'simplify',
673-
sourceMaps: opts.sourcemap || 'development' === opts.buildMode,
674-
transpileTs: true,
675-
transpileJsx: true,
676-
explicitExtensions: true,
677-
preserveFilenames: true,
678-
srcDir: srcDir,
679-
rootDir: opts.rootDir,
680-
mode: mode,
681-
scope: opts.scope ? opts.scope : void 0,
682-
stripCtxName: SERVER_STRIP_CTX_NAME,
683-
stripExports: SERVER_STRIP_EXPORTS,
684-
isServer: false,
685-
};
686-
const clientNewOutput = optimizer.transformModulesSync(clientTransformOpts);
687-
debug('client build', transformOpts, newOutput);
688-
689-
diagnosticsCallback(clientNewOutput.diagnostics, optimizer, srcDir);
690-
691-
results.set(normalizedID, clientNewOutput);
692-
for (const mod of clientNewOutput.modules) {
693-
if (isAdditionalFile(mod)) {
694-
const key = normalizePath(path.join(srcDir, mod.path));
695-
transformedOutputs.set(key, [mod, id]);
696-
// these are in ssr context and should be in client context
697-
// deps.add(key);
698-
// ctx.addWatchFile(key);
699-
if (mod.hook) {
700-
currentOutputs.set(mod.hook.name, [mod, id]);
701-
jsPacketIdSource.set(mod.hook.name, id);
702-
console.log('hook', mod.hook.name.toLowerCase(), id);
703-
}
704-
}
705-
}
706-
}
707653

708654
// Force loading generated submodules into Rollup cache so later
709655
// unchanged imports are not missing in our internal transform cache
@@ -778,7 +724,7 @@ export function createPlugin(optimizerOptions: OptimizerOptions = {}) {
778724
};
779725

780726
const debug = (...str: any[]) => {
781-
if (true || opts.debug) {
727+
if (opts.debug) {
782728
// eslint-disable-next-line no-console
783729
console.debug(`[QWIK PLUGIN: ${id}]`, ...str);
784730
}

packages/qwik/src/optimizer/src/plugins/vite-server.ts

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function getOrigin(req: IncomingMessage) {
2828
}
2929

3030
export async function configureDevServer(
31+
base: string,
3132
server: ViteDevServer,
3233
opts: NormalizedQwikPluginOptions,
3334
sys: OptimizerSystem,
@@ -54,7 +55,7 @@ export async function configureDevServer(
5455
}
5556

5657
// qwik middleware injected BEFORE vite internal middlewares
57-
server.middlewares.use(async (req: any, res: any, next: any) => {
58+
server.middlewares.use(async (req, res, next) => {
5859
try {
5960
const { ORIGIN } = process.env;
6061
const domain = ORIGIN ?? getOrigin(req);
@@ -136,9 +137,12 @@ export async function configureDevServer(
136137
});
137138
});
138139

139-
const srcBase = opts.srcDir
140+
let srcBase = opts.srcDir
140141
? path.relative(opts.rootDir, opts.srcDir).replace(/\\/g, '/')
141-
: 'src';
142+
: '';
143+
if (srcBase !== '') {
144+
srcBase += '/';
145+
}
142146

143147
const renderOpts: RenderToStreamOptions = {
144148
debug: true,
@@ -152,16 +156,16 @@ export async function configureDevServer(
152156
if (symbolName === SYNC_QRL) {
153157
return [symbolName, ''];
154158
}
155-
const defaultChunk = [
156-
symbolName,
157-
`${import.meta.env.BASE_URL}${parent ? `${srcBase}/${parent}?qrl=` : '@qrl/'}${symbolName.toLowerCase()}`,
158-
] as const;
159-
if (mapper) {
160-
const hash = getSymbolHash(symbolName);
161-
return mapper[hash] ?? defaultChunk;
162-
} else {
163-
return defaultChunk;
159+
const chunk = mapper && mapper[getSymbolHash(symbolName)];
160+
if (chunk) {
161+
return chunk;
162+
}
163+
if (!parent) {
164+
console.error('unknown qrl requested without parent:', symbolName);
165+
return [symbolName, `${base}${symbolName.toLowerCase()}.js`];
164166
}
167+
const packetFile = `${path.dirname(parent)}/${symbolName.toLowerCase()}.js?_qrl_parent=/${srcBase}${parent}`;
168+
return [symbolName, `${base}${srcBase}${packetFile}`];
165169
},
166170
prefetchStrategy: null,
167171
serverData,
@@ -206,6 +210,18 @@ export async function configureDevServer(
206210
next();
207211
}
208212
} else {
213+
// We didn't ssr, but maybe a qrl was requested
214+
const parent = url.searchParams.get('_qrl_parent');
215+
if (parent && url.pathname.endsWith('.js')) {
216+
// load the parent so it populates the qrl cache
217+
await server.transformRequest(parent);
218+
const result = await server.transformRequest(url.pathname);
219+
if (result) {
220+
res.setHeader('content-type', 'application/javascript');
221+
res.write(result.code);
222+
res.end();
223+
}
224+
}
209225
next();
210226
}
211227
} catch (e: any) {

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,15 @@ export function qwikVite(qwikViteOpts: QwikVitePluginOptions = {}): any {
649649
const opts = qwikPlugin.getOptions();
650650
const sys = qwikPlugin.getSys();
651651
const path = qwikPlugin.getPath();
652-
await configureDevServer(server, opts, sys, path, isClientDevOnly, clientDevInput);
652+
await configureDevServer(
653+
basePathname,
654+
server,
655+
opts,
656+
sys,
657+
path,
658+
isClientDevOnly,
659+
clientDevInput
660+
);
653661
};
654662
const isNEW = (globalThis as any).__qwikCityNew === true;
655663
if (isNEW) {

0 commit comments

Comments
 (0)