@qwik.dev/router 2.0.0-beta.37 → 2.0.0-beta.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/lib/adapters/cloudflare-pages/vite/index.mjs +2 -2
  2. package/lib/adapters/shared/vite/index.d.ts +3 -4
  3. package/lib/adapters/shared/vite/index.mjs +158 -143
  4. package/lib/chunks/dev-preloaded-route-loader.mjs +3 -0
  5. package/lib/chunks/fs.mjs +6 -2
  6. package/lib/chunks/head.qwik.mjs +814 -93
  7. package/lib/chunks/request-body-limit.mjs +37 -0
  8. package/lib/chunks/request-path.mjs +2 -2
  9. package/lib/chunks/routes.mjs +47 -0
  10. package/lib/chunks/server-error.mjs +19 -0
  11. package/lib/chunks/system.mjs +2 -1
  12. package/lib/chunks/use-functions.qwik.mjs +1 -1
  13. package/lib/chunks/{worker-thread.qwik.mjs → user-response.mjs} +1053 -1749
  14. package/lib/chunks/worker-thread.mjs +317 -0
  15. package/lib/index.d.ts +89 -55
  16. package/lib/index.qwik.mjs +178 -100
  17. package/lib/middleware/azure-swa/index.mjs +13 -9
  18. package/lib/middleware/cloudflare-pages/index.mjs +2 -2
  19. package/lib/middleware/deno/index.d.ts +2 -0
  20. package/lib/middleware/deno/index.mjs +2 -1
  21. package/lib/middleware/netlify-edge/index.mjs +2 -2
  22. package/lib/middleware/node/index.d.ts +9 -1
  23. package/lib/middleware/node/index.mjs +28 -3
  24. package/lib/middleware/request-handler/index.d.ts +9 -10
  25. package/lib/middleware/request-handler/index.mjs +26 -1105
  26. package/lib/middleware/vercel-edge/index.mjs +2 -2
  27. package/lib/ssg/index.d.ts +2 -10
  28. package/lib/ssg/index.mjs +10 -50
  29. package/lib/vite/index.d.ts +8 -0
  30. package/lib/vite/index.mjs +406 -117
  31. package/package.json +5 -4
  32. package/lib/chunks/action-handler.mjs +0 -782
  33. package/lib/chunks/deepFreeze.qwik.mjs +0 -608
  34. package/lib/chunks/error-handler.mjs +0 -57
  35. package/lib/chunks/not-found-wrapper.qwik.mjs +0 -25
@@ -1,9 +1,12 @@
1
1
  import { mergeConfig, normalizePath as normalizePath$1, loadEnv } from 'vite';
2
2
  import fs, { existsSync } from 'node:fs';
3
+ import { readFile } from 'node:fs/promises';
3
4
  import path, { join, dirname, basename, resolve, isAbsolute, extname } from 'node:path';
4
- import { g as getExtension, r as removeExtension, i as isIndexModule, a as isErrorName, b as isLayoutModule, c as isEntryName, d as isMenuFileName, e as isServiceWorkerName, f as isPageModuleExt, h as isModuleExt, j as isMarkdownExt, k as normalizePath, l as getPathnameFromDirPath, m as getMenuPathname, o as createFileId, p as parseRouteIndexName, q as isPluginModule, s as isPageExt } from '../chunks/fs.mjs';
5
+ import { findExports, findStaticImports } from 'mlly';
6
+ import { g as getExtension, r as removeExtension, i as isIndexModule, a as isErrorName, b as isPageModuleExt, c as isModuleExt, d as isMarkdownExt, e as isLayoutModule, f as isEntryName, h as isMenuFileName, j as isServiceWorkerName, k as normalizePath, l as getPathnameFromDirPath, m as getMenuPathname, o as createFileId, p as parseRouteIndexName, q as errorBoundaryName, s as isPluginModule, t as isPageExt } from '../chunks/fs.mjs';
5
7
  import { a as addError, b as addWarning } from '../chunks/format.mjs';
6
8
  import { i as isSameOriginUrl, e as ensureSlash } from '../chunks/pathname.mjs';
9
+ import { c as createRouteTester } from '../chunks/routes.mjs';
7
10
  import { marked } from 'marked';
8
11
  import { createHash } from 'node:crypto';
9
12
  import { SourceMapGenerator } from 'source-map';
@@ -16,6 +19,8 @@ import { toString } from 'hast-util-to-string';
16
19
  import { refractor } from 'refractor';
17
20
  import tsxLang from 'refractor/lang/tsx.js';
18
21
  import { optimize } from 'svgo';
22
+ import { r as recognizeRequest, I as IsQLoader, t as trimRecognizedInternalPathname, a as resolveValidInternalFullPathname } from '../chunks/request-path.mjs';
23
+ import { d as devPreloadedRouteLoaders } from '../chunks/dev-preloaded-route-loader.mjs';
19
24
 
20
25
  function extendConfig(baseConfigExport, serverConfigExport) {
21
26
  return async (env) => {
@@ -263,43 +268,6 @@ function parseRoutePathname(basePathname, pathname) {
263
268
  };
264
269
  }
265
270
 
266
- function routeSortCompare(a, b) {
267
- const maxSegments = Math.max(a.segments.length, b.segments.length);
268
- for (let i = 0; i < maxSegments; i += 1) {
269
- const sa = a.segments[i];
270
- const sb = b.segments[i];
271
- if (!sa) {
272
- return a.pathname.includes("[...") ? 1 : -1;
273
- }
274
- if (!sb) {
275
- return b.pathname.includes("[...") ? -1 : 1;
276
- }
277
- const maxParts = Math.max(sa.length, sb.length);
278
- for (let i2 = 0; i2 < maxParts; i2 += 1) {
279
- const pa = sa[i2];
280
- const pb = sb[i2];
281
- if (pa === void 0) {
282
- return pb.dynamic ? -1 : 1;
283
- }
284
- if (pb === void 0) {
285
- return pa.dynamic ? 1 : -1;
286
- }
287
- if (pa.dynamic !== pb.dynamic) {
288
- return pa.dynamic ? 1 : -1;
289
- }
290
- if (pa.dynamic) {
291
- if (pa.rest !== pb.rest) {
292
- return pa.rest ? 1 : -1;
293
- }
294
- }
295
- }
296
- }
297
- if (a.pathname === b.pathname) {
298
- return a.ext > b.ext ? -1 : 1;
299
- }
300
- return a.pathname < b.pathname ? -1 : 1;
301
- }
302
-
303
271
  const LAYOUT_ID = "layout";
304
272
  const LAYOUT_NAMED_PREFIX = LAYOUT_ID + "-";
305
273
  const LAYOUT_TOP_SUFFIX = "!";
@@ -335,8 +303,9 @@ function resolveRoute(opts, appLayouts, sourceFile) {
335
303
  const routesDir = opts.routesDir;
336
304
  const { layoutName, layoutStop } = parseRouteIndexName(sourceFile.extlessName);
337
305
  let pathname = getPathnameFromDirPath(opts, sourceFile.dirPath);
338
- if (sourceFile.extlessName === "404" || sourceFile.extlessName === "error") {
339
- pathname += sourceFile.extlessName + ".html";
306
+ const boundary = errorBoundaryName(sourceFile.extlessName);
307
+ if (boundary) {
308
+ pathname += boundary + ".html";
340
309
  }
341
310
  if (!layoutStop) {
342
311
  let currentDir = normalizePath(dirname(filePath));
@@ -374,6 +343,43 @@ function resolveRoute(opts, appLayouts, sourceFile) {
374
343
  };
375
344
  }
376
345
 
346
+ function routeSortCompare(a, b) {
347
+ const maxSegments = Math.max(a.segments.length, b.segments.length);
348
+ for (let i = 0; i < maxSegments; i += 1) {
349
+ const sa = a.segments[i];
350
+ const sb = b.segments[i];
351
+ if (!sa) {
352
+ return a.pathname.includes("[...") ? 1 : -1;
353
+ }
354
+ if (!sb) {
355
+ return b.pathname.includes("[...") ? -1 : 1;
356
+ }
357
+ const maxParts = Math.max(sa.length, sb.length);
358
+ for (let i2 = 0; i2 < maxParts; i2 += 1) {
359
+ const pa = sa[i2];
360
+ const pb = sb[i2];
361
+ if (pa === void 0) {
362
+ return pb.dynamic ? -1 : 1;
363
+ }
364
+ if (pb === void 0) {
365
+ return pa.dynamic ? 1 : -1;
366
+ }
367
+ if (pa.dynamic !== pb.dynamic) {
368
+ return pa.dynamic ? 1 : -1;
369
+ }
370
+ if (pa.dynamic) {
371
+ if (pa.rest !== pb.rest) {
372
+ return pa.rest ? 1 : -1;
373
+ }
374
+ }
375
+ }
376
+ }
377
+ if (a.pathname === b.pathname) {
378
+ return a.ext > b.ext ? -1 : 1;
379
+ }
380
+ return a.pathname < b.pathname ? -1 : 1;
381
+ }
382
+
377
383
  function parseDirName(name) {
378
384
  if (name.startsWith("(") && name.endsWith(")")) {
379
385
  return {
@@ -412,7 +418,6 @@ async function walkRouteDir(node, dirPath) {
412
418
  if (!child) {
413
419
  child = {
414
420
  _files: [],
415
- _dirPath: itemPath,
416
421
  children: /* @__PURE__ */ new Map()
417
422
  };
418
423
  node.children.set(itemName, child);
@@ -423,7 +428,6 @@ async function walkRouteDir(node, dirPath) {
423
428
  if (!child) {
424
429
  child = {
425
430
  _files: [],
426
- _dirPath: itemPath,
427
431
  children: /* @__PURE__ */ new Map()
428
432
  };
429
433
  if (parsed.paramName) {
@@ -457,7 +461,6 @@ async function walkRoutes(routesDir) {
457
461
  const dirPath = normalizePath(routesDir);
458
462
  const root = {
459
463
  _files: [],
460
- _dirPath: dirPath,
461
464
  children: /* @__PURE__ */ new Map()
462
465
  };
463
466
  await walkRouteDir(root, dirPath);
@@ -642,7 +645,7 @@ function rewriteRoutes(ctx, routes) {
642
645
  function applyRewriteRoutes(root, rewriteConfigs) {
643
646
  const routables = [];
644
647
  function walk(node, steps) {
645
- const hasRoute = node._files.some((f) => f.type === "route" && f.extlessName !== "error" && f.extlessName !== "404");
648
+ const hasRoute = node._files.some((f) => f.type === "route" && !isErrorName(f.extlessName));
646
649
  if (hasRoute) {
647
650
  routables.push({
648
651
  steps: [
@@ -672,7 +675,12 @@ function applyRewriteRoutes(root, rewriteConfigs) {
672
675
  for (const config of rewriteConfigs) {
673
676
  const translations = config.paths || {};
674
677
  const translatable = new Set(Object.keys(translations).map((k) => k.toLowerCase()));
678
+ const isExcluded = config.exclude?.length ? createRouteTester("/", config.exclude, void 0) : void 0;
675
679
  for (const { steps } of routables) {
680
+ const originalKeyPath = steps.map((s) => s.key).join("/");
681
+ if (isExcluded?.("/" + originalKeyPath)) {
682
+ continue;
683
+ }
676
684
  const hasTranslatable = steps.some((s) => translatable.has(s.key));
677
685
  if (!hasTranslatable && !config.prefix) {
678
686
  continue;
@@ -680,7 +688,6 @@ function applyRewriteRoutes(root, rewriteConfigs) {
680
688
  if (steps.length === 0 && !config.prefix) {
681
689
  continue;
682
690
  }
683
- const originalKeyPath = steps.map((s) => s.key).join("/");
684
691
  const translatedSteps = [];
685
692
  if (config.prefix) {
686
693
  translatedSteps.push({
@@ -704,7 +711,6 @@ function applyRewriteRoutes(root, rewriteConfigs) {
704
711
  if (!child) {
705
712
  child = {
706
713
  _files: [],
707
- _dirPath: "",
708
714
  children: /* @__PURE__ */ new Map()
709
715
  };
710
716
  if (step.paramName) {
@@ -832,7 +838,6 @@ function createBuildContext(rootDir, viteBasePath, userOpts, target, dynamicImpo
832
838
  opts: normalizeOptions(rootDir, viteBasePath, userOpts),
833
839
  routeTrie: {
834
840
  _files: [],
835
- _dirPath: "",
836
841
  children: /* @__PURE__ */ new Map()
837
842
  },
838
843
  routes: [],
@@ -1290,6 +1295,20 @@ function resolveNamedLayoutChain(ancestorLayouts, nodeLayouts, targetName) {
1290
1295
  }
1291
1296
  return result;
1292
1297
  }
1298
+ function buildLoaderChainExpr(extlessName, loaderExpr, ancestorLayouts, nodeLayouts) {
1299
+ const { layoutName, layoutStop } = parseRouteIndexName(extlessName);
1300
+ if (layoutStop) {
1301
+ return `[ ${loaderExpr} ]`;
1302
+ }
1303
+ if (layoutName) {
1304
+ const chain = resolveNamedLayoutChain(ancestorLayouts, nodeLayouts, layoutName);
1305
+ return `[ ${[
1306
+ ...chain.map((l) => l.id),
1307
+ loaderExpr
1308
+ ].join(", ")} ]`;
1309
+ }
1310
+ return loaderExpr;
1311
+ }
1293
1312
  function getClientRouteBundleNames(qwikPlugin, r) {
1294
1313
  const bundlesNames = [];
1295
1314
  const manifest = qwikPlugin.api.getManifest();
@@ -1318,7 +1337,7 @@ function getClientRouteBundleNames(qwikPlugin, r) {
1318
1337
  }
1319
1338
  return bundlesNames;
1320
1339
  }
1321
- function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menuIdMap, errorFiles, notFoundFiles, ancestorLayouts, isSSR, indent, loadersByFile) {
1340
+ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menuIdMap, ancestorLayouts, isSSR, indent, loadersByFile, routeLoaderSourceFiles) {
1322
1341
  const lines = [];
1323
1342
  const nextIndent = indent + " ";
1324
1343
  if (node._P) {
@@ -1335,7 +1354,6 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1335
1354
  }
1336
1355
  let layoutExpr;
1337
1356
  let indexExpr;
1338
- let indexIsOverride = false;
1339
1357
  let errorExpr;
1340
1358
  let notFoundExpr;
1341
1359
  let menuExpr;
@@ -1376,28 +1394,14 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1376
1394
  if (!loaderExpr) {
1377
1395
  continue;
1378
1396
  }
1379
- const isError = file.extlessName === "error";
1380
- const is404 = file.extlessName === "404";
1381
- if (isError) {
1382
- errorExpr = loaderExpr;
1383
- errorFiles.set(node._dirPath, file.filePath);
1384
- } else if (is404) {
1385
- notFoundExpr = loaderExpr;
1386
- notFoundFiles.set(node._dirPath, file.filePath);
1397
+ const expr = buildLoaderChainExpr(file.extlessName, loaderExpr, ancestorLayouts, nodeLayouts);
1398
+ const boundary = errorBoundaryName(file.extlessName);
1399
+ if (boundary === "404") {
1400
+ notFoundExpr = expr;
1401
+ } else if (boundary === "error") {
1402
+ errorExpr = expr;
1387
1403
  } else {
1388
- const { layoutName, layoutStop } = parseRouteIndexName(file.extlessName);
1389
- if (layoutStop) {
1390
- indexExpr = `[ ${loaderExpr} ]`;
1391
- indexIsOverride = true;
1392
- } else if (layoutName) {
1393
- const chain = resolveNamedLayoutChain(ancestorLayouts, nodeLayouts, layoutName);
1394
- const chainExprs = chain.map((l) => l.id);
1395
- chainExprs.push(loaderExpr);
1396
- indexExpr = `[ ${chainExprs.join(", ")} ]`;
1397
- indexIsOverride = true;
1398
- } else {
1399
- indexExpr = loaderExpr;
1400
- }
1404
+ indexExpr = expr;
1401
1405
  bundleRoute = ctx.routes.find((r) => r.filePath === file.filePath);
1402
1406
  }
1403
1407
  }
@@ -1405,11 +1409,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1405
1409
  lines.push(`${nextIndent}_L: ${layoutExpr},`);
1406
1410
  }
1407
1411
  if (indexExpr) {
1408
- if (indexIsOverride) {
1409
- lines.push(`${nextIndent}_I: ${indexExpr},`);
1410
- } else {
1411
- lines.push(`${nextIndent}_I: ${indexExpr},`);
1412
- }
1412
+ lines.push(`${nextIndent}_I: ${indexExpr},`);
1413
1413
  if (isSSR && bundleRoute) {
1414
1414
  const bundleNames = getClientRouteBundleNames(qwikPlugin, bundleRoute);
1415
1415
  if (bundleNames.length > 0) {
@@ -1418,16 +1418,22 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1418
1418
  }
1419
1419
  }
1420
1420
  {
1421
- const routeFiles = node._files.filter((f) => f.type === "route" || f.type === "layout").map((f) => f.filePath);
1421
+ const routeFiles = [];
1422
+ for (const file of node._files.filter((f) => f.type === "layout" || f.type === "route" && routeIdMap.has(f.filePath))) {
1423
+ routeFiles.push(file.filePath, ...routeLoaderSourceFiles?.get(file.filePath) ?? []);
1424
+ }
1422
1425
  if (node === ctx.routeTrie) {
1423
1426
  for (const plugin of ctx.serverPlugins) {
1424
- routeFiles.push(plugin.filePath);
1427
+ routeFiles.push(plugin.filePath, ...routeLoaderSourceFiles?.get(plugin.filePath) ?? []);
1425
1428
  }
1426
1429
  }
1427
- if (routeFiles.length > 0) {
1430
+ const routeLoaderFiles = [
1431
+ ...new Set(routeFiles)
1432
+ ];
1433
+ if (routeLoaderFiles.length > 0) {
1428
1434
  if (loadersByFile) {
1429
1435
  const nodeLoaderHashes = [];
1430
- for (const filePath of routeFiles) {
1436
+ for (const filePath of routeLoaderFiles) {
1431
1437
  const hashes = loadersByFile.get(filePath);
1432
1438
  if (hashes) {
1433
1439
  nodeLoaderHashes.push(...hashes);
@@ -1437,7 +1443,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1437
1443
  lines.push(`${nextIndent}_R: ${JSON.stringify(nodeLoaderHashes)},`);
1438
1444
  }
1439
1445
  } else {
1440
- const placeholder = `__LOADERS:${routeFiles.join("|")}__`;
1446
+ const placeholder = `__LOADERS:${routeLoaderFiles.join("|")}__`;
1441
1447
  lines.push(`${nextIndent}_R: ${JSON.stringify(placeholder)},`);
1442
1448
  }
1443
1449
  }
@@ -1474,7 +1480,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1474
1480
  groupChildren.sort((a, b) => a[0].localeCompare(b[0]));
1475
1481
  const groupStrs = [];
1476
1482
  for (const [_key, child] of groupChildren) {
1477
- const childStr = serializeBuildTrie(ctx, qwikPlugin, child, layoutIdMap, routeIdMap, menuIdMap, errorFiles, notFoundFiles, childAncestors, isSSR, nextIndent, loadersByFile);
1483
+ const childStr = serializeBuildTrie(ctx, qwikPlugin, child, layoutIdMap, routeIdMap, menuIdMap, childAncestors, isSSR, nextIndent, loadersByFile, routeLoaderSourceFiles);
1478
1484
  if (childStr !== "{}") {
1479
1485
  groupStrs.push(childStr);
1480
1486
  }
@@ -1484,7 +1490,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1484
1490
  }
1485
1491
  }
1486
1492
  for (const [key, child] of regularChildren) {
1487
- const childStr = serializeBuildTrie(ctx, qwikPlugin, child, layoutIdMap, routeIdMap, menuIdMap, errorFiles, notFoundFiles, childAncestors, isSSR, nextIndent, loadersByFile);
1493
+ const childStr = serializeBuildTrie(ctx, qwikPlugin, child, layoutIdMap, routeIdMap, menuIdMap, childAncestors, isSSR, nextIndent, loadersByFile, routeLoaderSourceFiles);
1488
1494
  if (childStr !== "{}") {
1489
1495
  const keyStr = JSON.stringify(key);
1490
1496
  lines.push(`${nextIndent}${keyStr}: ${childStr},`);
@@ -1497,14 +1503,12 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
1497
1503
  ${lines.join("\n")}
1498
1504
  ${indent}}`;
1499
1505
  }
1500
- function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile) {
1506
+ function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile, serverExcludePaths, routeLoaderSourceFiles) {
1501
1507
  const includeEndpoints = isSSR;
1502
1508
  const dynamicImports = ctx.dynamicImports;
1503
1509
  const layoutIdMap = /* @__PURE__ */ new Map();
1504
1510
  const routeIdMap = /* @__PURE__ */ new Map();
1505
1511
  const menuIdMap = /* @__PURE__ */ new Map();
1506
- const errorFiles = /* @__PURE__ */ new Map();
1507
- const notFoundFiles = /* @__PURE__ */ new Map();
1508
1512
  let layoutCount = 0;
1509
1513
  let routeCount = 0;
1510
1514
  let menuCount = 0;
@@ -1556,6 +1560,9 @@ function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile) {
1556
1560
  /** Qwik Router Routes (${routeCount}) */`);
1557
1561
  for (const route of ctx.routes) {
1558
1562
  if (isPageExt(route.ext)) {
1563
+ if (serverExcludePaths?.has(route.filePath)) {
1564
+ continue;
1565
+ }
1559
1566
  const importPath = getImportPath(route.filePath);
1560
1567
  let loaderExpr;
1561
1568
  if (dynamicImports) {
@@ -1571,7 +1578,7 @@ function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile) {
1571
1578
  routeIdMap.set(route.filePath, `()=>${route.id}`);
1572
1579
  }
1573
1580
  }
1574
- const trieStr = serializeBuildTrie(ctx, qwikPlugin, ctx.routeTrie, layoutIdMap, routeIdMap, menuIdMap, errorFiles, notFoundFiles, [], isSSR, "", loadersByFile);
1581
+ const trieStr = serializeBuildTrie(ctx, qwikPlugin, ctx.routeTrie, layoutIdMap, routeIdMap, menuIdMap, [], isSSR, "", loadersByFile, routeLoaderSourceFiles);
1575
1582
  const baseSegments = ctx.opts.basePathname.split("/").filter((s) => s.length > 0);
1576
1583
  let routesExpr = trieStr;
1577
1584
  for (let j = baseSegments.length - 1; j >= 0; j--) {
@@ -1596,7 +1603,7 @@ function createServerPlugins(ctx, _qwikPlugin, c, esmImports, isSSR) {
1596
1603
  c.push(`];`);
1597
1604
  }
1598
1605
 
1599
- function generateQwikRouterConfig(ctx, qwikPlugin, isSSR, loadersByFile) {
1606
+ function generateQwikRouterConfig(ctx, qwikPlugin, isSSR, loadersByFile, serverExcludePaths, routeLoaderSourceFiles) {
1600
1607
  const esmImports = [];
1601
1608
  const c = [];
1602
1609
  c.push(`
@@ -1607,7 +1614,7 @@ import { isDev } from '@qwik.dev/core/build';`);
1607
1614
  esmImports.push(`import 'virtual:qwik-router-server-fns';`);
1608
1615
  }
1609
1616
  createServerPlugins(ctx, qwikPlugin, c, esmImports, isSSR);
1610
- createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile);
1617
+ createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile, serverExcludePaths, routeLoaderSourceFiles);
1611
1618
  createEntries(ctx, c);
1612
1619
  c.push(`export const trailingSlash = ${JSON.stringify(!globalThis.__NO_TRAILING_SLASH__)};`);
1613
1620
  c.push(`export const basePathname = ${JSON.stringify(ctx.opts.basePathname)};`);
@@ -1633,6 +1640,76 @@ function generateServiceWorkerRegister(ctx, swRegister) {
1633
1640
  return `export default ${JSON.stringify(swReg)};`;
1634
1641
  }
1635
1642
 
1643
+ const NON_GET_HANDLERS = /* @__PURE__ */ new Set([
1644
+ "onRequest",
1645
+ "onPost",
1646
+ "onPut",
1647
+ "onPatch",
1648
+ "onDelete",
1649
+ "onHead",
1650
+ "onOptions"
1651
+ ]);
1652
+ const ROUTER_MODULE = "@qwik.dev/router";
1653
+ const SERVER_QRL = /\b(?:routeLoader|routeAction|globalAction|server)(?:\$|Qrl)/;
1654
+ function isServerFreeSource(code) {
1655
+ for (const e of findExports(code)) {
1656
+ if (e.specifier) {
1657
+ return false;
1658
+ }
1659
+ const names = [
1660
+ ...e.name ? [
1661
+ e.name
1662
+ ] : [],
1663
+ ...e.names ?? []
1664
+ ];
1665
+ if (names.some((n) => NON_GET_HANDLERS.has(n))) {
1666
+ return false;
1667
+ }
1668
+ }
1669
+ for (const imp of findStaticImports(code)) {
1670
+ if (imp.specifier === ROUTER_MODULE && SERVER_QRL.test(imp.code)) {
1671
+ return false;
1672
+ }
1673
+ }
1674
+ return true;
1675
+ }
1676
+ function isFileServerFree(filePath, cache) {
1677
+ let pending = cache.get(filePath);
1678
+ if (!pending) {
1679
+ pending = readFile(filePath, "utf-8").then(isServerFreeSource).catch(() => false);
1680
+ cache.set(filePath, pending);
1681
+ }
1682
+ return pending;
1683
+ }
1684
+ async function isRouteServerFree(route, cache) {
1685
+ if (!isMarkdownExt(route.ext) && !await isFileServerFree(route.filePath, cache)) {
1686
+ return false;
1687
+ }
1688
+ for (const layout of route.layouts) {
1689
+ if (!await isFileServerFree(layout.filePath, cache)) {
1690
+ return false;
1691
+ }
1692
+ }
1693
+ return true;
1694
+ }
1695
+ async function getServerExcludedRoutes(ctx, ssg) {
1696
+ const excluded = /* @__PURE__ */ new Set();
1697
+ if (!ssg?.include?.length) {
1698
+ return excluded;
1699
+ }
1700
+ const isPrerendered = createRouteTester(ctx.opts.basePathname, ssg.include, ssg.exclude);
1701
+ const serverFreeByFile = /* @__PURE__ */ new Map();
1702
+ await Promise.all(ctx.routes.map(async (route) => {
1703
+ if (!isPageExt(route.ext) || route.paramNames.length > 0 || /\/(?:404|error)\.html$/.test(route.pathname) || !isPrerendered(route.pathname)) {
1704
+ return;
1705
+ }
1706
+ if (await isRouteServerFree(route, serverFreeByFile)) {
1707
+ excluded.add(route.filePath);
1708
+ }
1709
+ }));
1710
+ return excluded;
1711
+ }
1712
+
1636
1713
  function isBundlePartOfRoute(bundle, routeAndLayoutPaths) {
1637
1714
  if (!bundle.origins) {
1638
1715
  return false;
@@ -1806,8 +1883,22 @@ function createVirtualImageJsxId(pathId, params) {
1806
1883
  const queryString = query.toString();
1807
1884
  return `${VIRTUAL_IMAGE_JSX_PREFIX}${normalizePath$1(pathId)}${VIRTUAL_IMAGE_JSX_SUFFIX}${queryString ? `?${queryString}` : ""}`;
1808
1885
  }
1809
- function createImageJsxImportId(pathId, params) {
1810
- const query = new URLSearchParams(params);
1886
+ function createImageJsxDirectives(params, userOpts) {
1887
+ const overrides = Object.fromEntries(params.entries());
1888
+ delete overrides[JSX_QUERY_PARAM];
1889
+ delete overrides[INTERNAL_IMAGE_JSX_QUERY_PARAM];
1890
+ return new URLSearchParams({
1891
+ format: "webp",
1892
+ quality: "75",
1893
+ w: "200;400;600;800;1200",
1894
+ withoutEnlargement: "",
1895
+ ...userOpts?.imageOptimization?.jsxDirectives,
1896
+ ...overrides,
1897
+ as: "jsx"
1898
+ });
1899
+ }
1900
+ function createImageJsxImportId(pathId, params, userOpts) {
1901
+ const query = createImageJsxDirectives(params, userOpts);
1811
1902
  query.set(INTERNAL_IMAGE_JSX_QUERY_PARAM, "");
1812
1903
  return `${normalizePath$1(pathId)}?${query.toString()}`;
1813
1904
  }
@@ -1835,9 +1926,10 @@ function getToImg() {
1835
1926
  : _jsxSplit("img", null, {decoding, height: h, loading, srcSet: s, width: w});
1836
1927
  `;
1837
1928
  }
1838
- function createImageJsxModule(pathId, params) {
1929
+ function createImageJsxModule(pathId, params, userOpts) {
1930
+ const importId = createImageJsxImportId(pathId, params, userOpts);
1839
1931
  return `
1840
- import { srcSet, width, height } from ${JSON.stringify(createImageJsxImportId(pathId, params))};
1932
+ import { srcSet, width, height } from ${JSON.stringify(importId)};
1841
1933
  import toImg from ${JSON.stringify(TO_IMG_ID)};
1842
1934
 
1843
1935
  export default toImg(srcSet, width, height);
@@ -1935,18 +2027,7 @@ function imagePlugin(userOpts) {
1935
2027
  },
1936
2028
  defaultDirectives: (url) => {
1937
2029
  if (url.searchParams.has(JSX_QUERY_PARAM)) {
1938
- const params = Object.fromEntries(url.searchParams.entries());
1939
- delete params[JSX_QUERY_PARAM];
1940
- delete params[INTERNAL_IMAGE_JSX_QUERY_PARAM];
1941
- return new URLSearchParams({
1942
- format: "webp",
1943
- quality: "75",
1944
- w: "200;400;600;800;1200",
1945
- withoutEnlargement: "",
1946
- ...userOpts?.imageOptimization?.jsxDirectives,
1947
- ...params,
1948
- as: "jsx"
1949
- });
2030
+ return createImageJsxDirectives(url.searchParams, userOpts);
1950
2031
  }
1951
2032
  return new URLSearchParams();
1952
2033
  }
@@ -1960,9 +2041,9 @@ function imagePlugin(userOpts) {
1960
2041
  order: "pre",
1961
2042
  async handler(id, importer, options) {
1962
2043
  if (parseVirtualImageJsxId(id)) {
1963
- return null;
2044
+ return id;
1964
2045
  }
1965
- if (id.endsWith(TO_IMG_ID)) {
2046
+ if (id.endsWith(TO_IMG_ID) || id === VIRTUAL_TO_IMG_ID) {
1966
2047
  return VIRTUAL_TO_IMG_ID;
1967
2048
  }
1968
2049
  const { pathId, params } = parseId(id);
@@ -2028,7 +2109,7 @@ function imagePlugin(userOpts) {
2028
2109
  }
2029
2110
  if (supportedExtensions.includes(imageId.extension)) {
2030
2111
  return {
2031
- code: createImageJsxModule(imageId.pathId, imageId.params),
2112
+ code: createImageJsxModule(imageId.pathId, imageId.params, userOpts),
2032
2113
  map: null
2033
2114
  };
2034
2115
  }
@@ -2074,15 +2155,21 @@ async function collectServerFnModuleIds(routingContext, resolvedVirtualId, plugi
2074
2155
  continue;
2075
2156
  }
2076
2157
  const moduleInfo = await pluginContext.load({
2077
- id: resolved.id
2158
+ id: resolved.id,
2159
+ resolveDependencies: true
2078
2160
  });
2079
2161
  if (moduleInfo.code == null) {
2080
2162
  continue;
2081
2163
  }
2164
+ const qwikDeps = moduleInfo.meta?.qwikdeps ?? [];
2082
2165
  if (moduleInfo.code.includes("serverQrl(")) {
2083
2166
  serverFnModules.add(moduleInfo.id);
2084
2167
  }
2085
- const resolvedImports = moduleInfo.importedIds.concat(moduleInfo.dynamicallyImportedIds);
2168
+ const resolvedImports = [
2169
+ ...moduleInfo.importedIds,
2170
+ ...moduleInfo.dynamicallyImportedIds,
2171
+ ...qwikDeps
2172
+ ];
2086
2173
  for (let i = 0; i < resolvedImports.length; i++) {
2087
2174
  const resolvedImport = resolvedImports[i];
2088
2175
  if (resolvedImport && !seenModuleIds.has(resolvedImport)) {
@@ -2244,7 +2331,7 @@ class HtmlTransformPatcher {
2244
2331
  try {
2245
2332
  const fakeHtml = `<html><head>[FAKE_HEAD]</head><body>[FAKE_BODY]</body></html>`;
2246
2333
  const transformedHtml = await this.server.transformIndexHtml(this.request.url || "/", fakeHtml);
2247
- const hmrBridge = this.server.hot ? `<script type="module" src="/@id/@qwik-hmr-bridge"><\/script>` : "";
2334
+ const hmrBridge = this.server.hot ? `<script type="module" src="${this.server.config.base}@id/@qwik-hmr-bridge"><\/script>` : "";
2248
2335
  const fakeHeadIndex = transformedHtml.indexOf("[FAKE_HEAD]");
2249
2336
  const fakeHeadCloseIndex = transformedHtml.indexOf("</head>", fakeHeadIndex);
2250
2337
  if (fakeHeadIndex === -1 || fakeHeadCloseIndex === -1) {
@@ -2325,6 +2412,66 @@ function wrapResponseForHtmlTransform(request, response, server) {
2325
2412
  return response;
2326
2413
  }
2327
2414
 
2415
+ const FULLPATH_HEADER = "X-Qwik-fullpath";
2416
+ const ROUTE_PATH_HEADER = "X-Qwik-route-path";
2417
+ function getDevMiddlewareRequestPath(req) {
2418
+ return req.originalUrl || req.url;
2419
+ }
2420
+ async function loadSsrModule(server, filePath) {
2421
+ return server.ssrLoadModule(getImportPath(normalizePath(filePath)));
2422
+ }
2423
+ function matchesLoaderId(loader, loaderId) {
2424
+ return loader.__id === loaderId || loader.__qrl.getHash() === loaderId;
2425
+ }
2426
+ function isLoaderInternal(value) {
2427
+ return typeof value === "function" && value.__brand === "server_loader";
2428
+ }
2429
+ function findMatchingLoader(mod, loaderId) {
2430
+ for (const value of Object.values(mod)) {
2431
+ if (isLoaderInternal(value) && matchesLoaderId(value, loaderId)) {
2432
+ return value;
2433
+ }
2434
+ }
2435
+ }
2436
+ async function preloadQLoaderRouteLoader(server, ctx, req) {
2437
+ const requestPath = getDevMiddlewareRequestPath(req);
2438
+ if (!requestPath) {
2439
+ return void 0;
2440
+ }
2441
+ let requestUrl;
2442
+ try {
2443
+ requestUrl = new URL(requestPath, "http://qwik.dev");
2444
+ } catch {
2445
+ return void 0;
2446
+ }
2447
+ const recognized = recognizeRequest(requestUrl.pathname);
2448
+ if (recognized?.type !== IsQLoader || !recognized.data?.loaderId) {
2449
+ return void 0;
2450
+ }
2451
+ const loaderId = recognized.data.loaderId;
2452
+ const headerValue = req.headers[FULLPATH_HEADER.toLowerCase()] ?? req.headers[ROUTE_PATH_HEADER.toLowerCase()];
2453
+ const fullPathHeader = Array.isArray(headerValue) ? headerValue[0] : headerValue ?? null;
2454
+ const loaderPathname = trimRecognizedInternalPathname(requestUrl.pathname, recognized);
2455
+ const pathname = resolveValidInternalFullPathname(loaderPathname, fullPathHeader) ?? loaderPathname;
2456
+ const route = ctx.routes.filter((route2) => isPageExt(route2.ext)).slice().sort(routeSortCompare).find((route2) => route2.pattern.test(pathname));
2457
+ if (!route) {
2458
+ return void 0;
2459
+ }
2460
+ const routeRootFiles = [
2461
+ ...route.layouts.map((layout) => layout.filePath),
2462
+ route.filePath
2463
+ ];
2464
+ const modules = await Promise.all([
2465
+ ...ctx.serverPlugins.map((plugin) => loadSsrModule(server, plugin.filePath)),
2466
+ ...routeRootFiles.map((filePath) => loadSsrModule(server, filePath))
2467
+ ]);
2468
+ for (const mod of modules) {
2469
+ const loader = findMatchingLoader(mod, loaderId);
2470
+ if (loader) {
2471
+ return loader;
2472
+ }
2473
+ }
2474
+ }
2328
2475
  const makeRouterDevMiddleware = (server, ctx) => async (req, res, next) => {
2329
2476
  let mod;
2330
2477
  try {
@@ -2344,6 +2491,11 @@ const makeRouterDevMiddleware = (server, ctx) => async (req, res, next) => {
2344
2491
  await updateRoutingContext(ctx);
2345
2492
  ctx.isDirty = false;
2346
2493
  }
2494
+ const preloadedRouteLoader = await preloadQLoaderRouteLoader(server, ctx, req);
2495
+ if (preloadedRouteLoader) {
2496
+ await server.ssrLoadModule("@qwik-router-config");
2497
+ devPreloadedRouteLoaders.set(req, preloadedRouteLoader);
2498
+ }
2347
2499
  const entry = ctx.entries.find((e) => req.url === `${server.config.base}${e.chunkFileName}`);
2348
2500
  if (entry) {
2349
2501
  const entryContents = await server.transformRequest(`/@fs${entry.filePath.startsWith("/") ? "" : "/"}${entry.filePath}`);
@@ -2421,6 +2573,9 @@ const getCssUrls = (server) => {
2421
2573
  });
2422
2574
  if ((isEntryCSS || hasJSImporter) && !hasCSSImporter && !cssImportedByCSS.has(mod.url)) {
2423
2575
  cssModules.add(`${mod.url}${mod.lastHMRTimestamp ? `?t=${mod.lastHMRTimestamp}` : ""}`);
2576
+ if (mod.file) {
2577
+ server.watcher.add(mod.file);
2578
+ }
2424
2579
  }
2425
2580
  }
2426
2581
  }
@@ -2435,10 +2590,36 @@ const getRouterIndexTags = (server) => {
2435
2590
  tag: "link",
2436
2591
  attrs: {
2437
2592
  rel: "stylesheet",
2438
- href: url
2593
+ href: server.config.base + url.slice(1)
2439
2594
  }
2440
2595
  }));
2441
2596
  };
2597
+ const sendRouterCssHotUpdate = (server, file, timestamp) => {
2598
+ const { client, ssr } = server.environments;
2599
+ if (!isCssPath(file) || client.moduleGraph.getModulesByFile(file)?.size) {
2600
+ return false;
2601
+ }
2602
+ const paths = /* @__PURE__ */ new Set();
2603
+ for (const mod of ssr.moduleGraph.getModulesByFile(file) ?? []) {
2604
+ mod.lastHMRTimestamp = timestamp;
2605
+ paths.add(mod.url.split("?")[0]);
2606
+ }
2607
+ if (!paths.size) {
2608
+ return false;
2609
+ }
2610
+ client.hot.send({
2611
+ type: "update",
2612
+ updates: [
2613
+ ...paths
2614
+ ].map((path) => ({
2615
+ type: "css-update",
2616
+ path,
2617
+ acceptedPath: path,
2618
+ timestamp
2619
+ }))
2620
+ });
2621
+ return true;
2622
+ };
2442
2623
 
2443
2624
  const QWIK_ROUTER_CONFIG_ID = "@qwik-router-config";
2444
2625
  const QWIK_ROUTER_ENTRIES_ID = "@qwik-router-entries";
@@ -2491,6 +2672,75 @@ function isRouterSourceFileForContext(filePath, ctx) {
2491
2672
  const normalizedPath = normalizePath(filePath);
2492
2673
  return isRouterSourceFilePath(normalizedPath) && (isPathInDir(normalizedPath, ctx.opts.routesDir) || isPathInDir(normalizedPath, ctx.opts.serverPluginsDir));
2493
2674
  }
2675
+ function isDiscoveredRouteLoaderSource(filePath, sourceFiles) {
2676
+ if (!sourceFiles) {
2677
+ return false;
2678
+ }
2679
+ const normalizedPath = normalizePath(filePath);
2680
+ for (const files of sourceFiles.values()) {
2681
+ if (files.includes(normalizedPath)) {
2682
+ return true;
2683
+ }
2684
+ }
2685
+ return false;
2686
+ }
2687
+ function collectRouteLoaderOwners(node, owners) {
2688
+ for (const file of node._files) {
2689
+ if (file.type === "layout" || file.type === "route") {
2690
+ owners.add(file.filePath);
2691
+ }
2692
+ }
2693
+ for (const child of node.children.values()) {
2694
+ collectRouteLoaderOwners(child, owners);
2695
+ }
2696
+ }
2697
+ async function collectReExportSources(owner, filePath, resolveSource, sources, seen = /* @__PURE__ */ new Set([
2698
+ owner
2699
+ ])) {
2700
+ let code, exportEntries;
2701
+ try {
2702
+ code = await readFile(filePath, "utf-8");
2703
+ exportEntries = findExports(code);
2704
+ if (!exportEntries) {
2705
+ return;
2706
+ }
2707
+ } catch {
2708
+ return;
2709
+ }
2710
+ await Promise.all(exportEntries.map(async (exp) => {
2711
+ if (!exp.specifier) {
2712
+ return;
2713
+ }
2714
+ const resolved = await resolveSource(exp.specifier, filePath);
2715
+ if (!resolved || resolved.charCodeAt(0) === 0) {
2716
+ return;
2717
+ }
2718
+ const resolvedPath = normalizePath(resolved.split(/[?#]/, 1)[0]);
2719
+ let ownerSources = sources.get(owner);
2720
+ if (!ownerSources) {
2721
+ sources.set(owner, ownerSources = []);
2722
+ }
2723
+ if (!ownerSources.includes(resolvedPath)) {
2724
+ ownerSources.push(resolvedPath);
2725
+ }
2726
+ if (!seen.has(resolvedPath)) {
2727
+ seen.add(resolvedPath);
2728
+ await collectReExportSources(owner, resolvedPath, resolveSource, sources, seen);
2729
+ }
2730
+ }));
2731
+ }
2732
+ async function findRouteLoaderSourceFiles(ctx, resolveSource) {
2733
+ const sources = /* @__PURE__ */ new Map();
2734
+ const owners = /* @__PURE__ */ new Set();
2735
+ collectRouteLoaderOwners(ctx.routeTrie, owners);
2736
+ for (const plugin of ctx.serverPlugins) {
2737
+ owners.add(plugin.filePath);
2738
+ }
2739
+ await Promise.all([
2740
+ ...owners
2741
+ ].map((owner) => collectReExportSources(owner, owner, resolveSource, sources)));
2742
+ return sources;
2743
+ }
2494
2744
  function invalidateRouterConfigModules(server) {
2495
2745
  const modules = [];
2496
2746
  const moduleGraphs = /* @__PURE__ */ new Set();
@@ -2545,6 +2795,8 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2545
2795
  const routesDir = userOpts?.routesDir ?? "src/routes";
2546
2796
  const serverPluginsDir = userOpts?.serverPluginsDir ?? routesDir;
2547
2797
  const loadersByFile = /* @__PURE__ */ new Map();
2798
+ let reExportedRouteLoaderSources;
2799
+ let ssgRoutePatterns;
2548
2800
  const api = {
2549
2801
  getBasePathname: () => ctx?.opts.basePathname ?? "/",
2550
2802
  getRoutes: () => {
@@ -2552,6 +2804,12 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2552
2804
  },
2553
2805
  getServiceWorkers: () => {
2554
2806
  return ctx?.serviceWorkers.slice() ?? [];
2807
+ },
2808
+ _setSsgRoutes: (include, exclude) => {
2809
+ ssgRoutePatterns = include?.length ? {
2810
+ include,
2811
+ exclude
2812
+ } : void 0;
2555
2813
  }
2556
2814
  };
2557
2815
  const plugin = {
@@ -2635,7 +2893,7 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2635
2893
  return updatedViteConfig;
2636
2894
  },
2637
2895
  configEnvironment(name, _config, _env) {
2638
- if (name === "ssr") {
2896
+ if (name === "ssr" || name === "ssg") {
2639
2897
  return {
2640
2898
  resolve: {
2641
2899
  external: [
@@ -2703,11 +2961,24 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2703
2961
  };
2704
2962
  }
2705
2963
  },
2706
- handleHotUpdate({ file, modules, server }) {
2707
- if (!ctx || !isRouterSourceFileForContext(file, ctx)) {
2964
+ handleHotUpdate({ file, modules, server, timestamp }) {
2965
+ if (sendRouterCssHotUpdate(server, file, timestamp)) {
2966
+ return [];
2967
+ }
2968
+ const clearedLoaderHashes = clearRouteLoaderHashes(loadersByFile, file);
2969
+ if (!ctx) {
2970
+ return;
2971
+ }
2972
+ if (!isRouterSourceFileForContext(file, ctx)) {
2973
+ if (clearedLoaderHashes || isDiscoveredRouteLoaderSource(file, reExportedRouteLoaderSources)) {
2974
+ const configModules2 = invalidateRouterConfigModules(server);
2975
+ return [
2976
+ ...modules,
2977
+ ...configModules2
2978
+ ];
2979
+ }
2708
2980
  return;
2709
2981
  }
2710
- clearRouteLoaderHashes(loadersByFile, file);
2711
2982
  ctx.isDirty = true;
2712
2983
  const configModules = invalidateRouterConfigModules(server);
2713
2984
  return [
@@ -2755,7 +3026,15 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2755
3026
  });
2756
3027
  }
2757
3028
  if (isRouterConfig) {
2758
- return generateQwikRouterConfig(ctx, qwikPlugin, this.environment.config.consumer === "server", devServer ? loadersByFile : void 0);
3029
+ const isServerConsumer = this.environment.config.consumer === "server";
3030
+ const serverExcludePaths = isServerConsumer && !devServer && this.environment.name !== "ssg" ? await getServerExcludedRoutes(ctx, ssgRoutePatterns) : void 0;
3031
+ reExportedRouteLoaderSources = await findRouteLoaderSourceFiles(ctx, async (specifier, importer) => {
3032
+ const resolved = await this.resolve(specifier, importer, {
3033
+ skipSelf: true
3034
+ });
3035
+ return resolved?.id;
3036
+ });
3037
+ return generateQwikRouterConfig(ctx, qwikPlugin, isServerConsumer, devServer ? loadersByFile : void 0, serverExcludePaths, reExportedRouteLoaderSources);
2759
3038
  }
2760
3039
  if (isSwRegister) {
2761
3040
  return generateServiceWorkerRegister(ctx, swRegister);
@@ -2809,6 +3088,15 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
2809
3088
  return null;
2810
3089
  },
2811
3090
  generateBundle(_, bundles) {
3091
+ const manifest = qwikPlugin.api.getManifest();
3092
+ if (manifest) {
3093
+ const srcDir = qwikPlugin.api.getOptions().srcDir;
3094
+ for (const symbol of Object.values(manifest.symbols)) {
3095
+ if (symbol.ctxName === "routeLoader$" && symbol.origin) {
3096
+ addRouteLoaderHash(loadersByFile, resolve(srcDir, symbol.origin), symbol.hash);
3097
+ }
3098
+ }
3099
+ }
2812
3100
  for (const chunk of Object.values(bundles)) {
2813
3101
  if (chunk.type === "chunk" && chunk.code.includes("__LOADERS:")) {
2814
3102
  chunk.code = replaceLoaderPlaceholders(chunk.code, loadersByFile);
@@ -2901,7 +3189,8 @@ function serverFnsPlugin(buildContextRef) {
2901
3189
  }
2902
3190
  return [
2903
3191
  ...serverFnModules
2904
- ].map((mod) => `import ${JSON.stringify(mod)};`).join("\n");
3192
+ ].map((mod, index) => `import * as serverFnModule${index} from ${JSON.stringify(mod)};
3193
+ Object.values(serverFnModule${index});`).join("\n");
2905
3194
  }
2906
3195
  return null;
2907
3196
  }