@qwik.dev/router 2.0.0-beta.45 → 2.0.0-beta.47
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.
- package/lib/adapters/azure-swa/vite/index.d.ts +2 -2
- package/lib/adapters/bun-server/vite/index.d.ts +2 -2
- package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
- package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
- package/lib/adapters/deno-server/vite/index.d.ts +2 -2
- package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
- package/lib/adapters/node-server/vite/index.d.ts +2 -2
- package/lib/adapters/shared/vite/index.d.ts +1 -1
- package/lib/adapters/shared/vite/index.mjs +1 -1
- package/lib/adapters/ssg/vite/index.d.ts +1 -1
- package/lib/adapters/vercel-edge/vite/index.d.ts +2 -2
- package/lib/chunks/fs.mjs +4 -4
- package/lib/chunks/head.qwik.mjs +181 -64
- package/lib/chunks/route-trie-key.mjs +10 -0
- package/lib/chunks/server-error.mjs +17 -1
- package/lib/chunks/system.mjs +13 -8
- package/lib/chunks/user-response.mjs +44 -33
- package/lib/chunks/worker-thread.mjs +5 -4
- package/lib/index.d.ts +50 -7
- package/lib/index.qwik.mjs +83 -45
- package/lib/middleware/request-handler/index.d.ts +102 -2
- package/lib/middleware/request-handler/index.mjs +8 -23
- package/lib/ssg/index.mjs +3 -2
- package/lib/vite/index.mjs +85 -30
- package/package.json +3 -3
package/lib/vite/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { r as isSameOriginUrl, t as ensureSlash } from "../chunks/pathname.mjs";
|
|
2
2
|
import { c as resolveValidInternalFullPathname, s as recognizeRequest, u as trimRecognizedInternalPathname } from "../chunks/request-path.mjs";
|
|
3
|
+
import { t as escapeStaticTrieKey } from "../chunks/route-trie-key.mjs";
|
|
3
4
|
import { n as addWarning, t as addError } from "../chunks/format.mjs";
|
|
4
|
-
import { _ as normalizePath$1, a as getPathnameFromDirPath, b as parseRouteIndexName, c as isIndexModule, d as isMenuFileName, f as isModuleExt, g as isServiceWorkerName, h as isPluginModule, i as getMenuPathname, l as isLayoutModule, m as isPageModuleExt, n as
|
|
5
|
+
import { _ as normalizePath$1, a as getPathnameFromDirPath, b as parseRouteIndexName, c as isIndexModule, d as isMenuFileName, f as isModuleExt, g as isServiceWorkerName, h as isPluginModule, i as getMenuPathname, l as isLayoutModule, m as isPageModuleExt, n as createFileId, o as isEntryName, p as isPageExt, r as getExtension, s as isErrorName, t as caughtErrorName, u as isMarkdownExt, v as normalizePathKey, x as removeExtension } from "../chunks/fs.mjs";
|
|
5
6
|
import { t as devPreloadedRouteLoaders } from "../chunks/dev-preloaded-route-loader.mjs";
|
|
6
7
|
import { t as createRouteTester } from "../chunks/routes.mjs";
|
|
7
8
|
import fs, { existsSync } from "node:fs";
|
|
@@ -31,7 +32,6 @@ function extendConfig(baseConfigExport, serverConfigExport) {
|
|
|
31
32
|
return mergeConfig(resolvedBase, resolvedServer);
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
var sw_register_build_default = "export default\"\"";
|
|
35
35
|
function getSourceFile(fileName) {
|
|
36
36
|
const ext = getExtension(fileName);
|
|
37
37
|
const extlessName = removeExtension(fileName);
|
|
@@ -220,7 +220,7 @@ function resolveRoute(opts, appLayouts, sourceFile) {
|
|
|
220
220
|
const routesDir = opts.routesDir;
|
|
221
221
|
const { layoutName, layoutStop } = parseRouteIndexName(sourceFile.extlessName);
|
|
222
222
|
let pathname = getPathnameFromDirPath(opts, sourceFile.dirPath);
|
|
223
|
-
const boundary =
|
|
223
|
+
const boundary = caughtErrorName(sourceFile.extlessName);
|
|
224
224
|
if (boundary) pathname += boundary + ".html";
|
|
225
225
|
if (!layoutStop) {
|
|
226
226
|
let currentDir = normalizePath$1(dirname(filePath));
|
|
@@ -978,6 +978,14 @@ function getImportPath(importPath) {
|
|
|
978
978
|
function isGroupKey(key) {
|
|
979
979
|
return key.charCodeAt(0) === 40;
|
|
980
980
|
}
|
|
981
|
+
/** The runtime trie key for a build trie key; `_W`/`_A` are the only non-static ones. */
|
|
982
|
+
function toRuntimeTrieKey(key) {
|
|
983
|
+
return key === "_W" || key === "_A" ? key : escapeStaticTrieKey(key);
|
|
984
|
+
}
|
|
985
|
+
/** A rewrite target or base path with each segment converted to its runtime trie key. */
|
|
986
|
+
function toRuntimeTriePath(path) {
|
|
987
|
+
return path.split("/").map(toRuntimeTrieKey).join("/");
|
|
988
|
+
}
|
|
981
989
|
/**
|
|
982
990
|
* Serialize the build trie into JS code.
|
|
983
991
|
*
|
|
@@ -1053,7 +1061,7 @@ function createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile, serv
|
|
|
1053
1061
|
const trieStr = serializeBuildTrie(ctx, qwikPlugin, ctx.routeTrie, layoutIdMap, routeIdMap, menuIdMap, isSSR, "", loadersByFile, routeLoaderSourceFiles);
|
|
1054
1062
|
const baseSegments = ctx.opts.basePathname.split("/").filter((s) => s.length > 0);
|
|
1055
1063
|
let routesExpr = trieStr;
|
|
1056
|
-
for (let j = baseSegments.length - 1; j >= 0; j--) routesExpr = `{ ${JSON.stringify(baseSegments[j])}: ${routesExpr} }`;
|
|
1064
|
+
for (let j = baseSegments.length - 1; j >= 0; j--) routesExpr = `{ ${JSON.stringify(escapeStaticTrieKey(baseSegments[j]))}: ${routesExpr} }`;
|
|
1057
1065
|
c.push(`export const routes = ${routesExpr};`);
|
|
1058
1066
|
}
|
|
1059
1067
|
function collectFiles(node, cb) {
|
|
@@ -1067,7 +1075,10 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
|
|
|
1067
1075
|
if (node._P) lines.push(`${nextIndent}_P: ${JSON.stringify(node._P)},`);
|
|
1068
1076
|
if (node._0) lines.push(`${nextIndent}_0: ${JSON.stringify(node._0)},`);
|
|
1069
1077
|
if (node._9) lines.push(`${nextIndent}_9: ${JSON.stringify(node._9)},`);
|
|
1070
|
-
if (node._G != null)
|
|
1078
|
+
if (node._G != null) {
|
|
1079
|
+
const target = toRuntimeTriePath(ctx.opts.basePathname + node._G);
|
|
1080
|
+
lines.push(`${nextIndent}_G: ${JSON.stringify(target)},`);
|
|
1081
|
+
}
|
|
1071
1082
|
let layoutExpr;
|
|
1072
1083
|
let indexExpr;
|
|
1073
1084
|
let errorExpr;
|
|
@@ -1090,7 +1101,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
|
|
|
1090
1101
|
if (!loaderExpr) continue;
|
|
1091
1102
|
const route = ctx.routes.find((route) => route.filePath === file.filePath);
|
|
1092
1103
|
const expr = buildLoaderChainExpr(file.extlessName, loaderExpr, route?.layouts ?? []);
|
|
1093
|
-
const boundary =
|
|
1104
|
+
const boundary = caughtErrorName(file.extlessName);
|
|
1094
1105
|
if (boundary === "404") notFoundExpr = expr;
|
|
1095
1106
|
else if (boundary === "error") errorExpr = expr;
|
|
1096
1107
|
else {
|
|
@@ -1143,7 +1154,7 @@ function serializeBuildTrie(ctx, qwikPlugin, node, layoutIdMap, routeIdMap, menu
|
|
|
1143
1154
|
for (const [key, child] of regularChildren) {
|
|
1144
1155
|
const childStr = serializeBuildTrie(ctx, qwikPlugin, child, layoutIdMap, routeIdMap, menuIdMap, isSSR, nextIndent, loadersByFile, routeLoaderSourceFiles);
|
|
1145
1156
|
if (childStr !== "{}") {
|
|
1146
|
-
const keyStr = JSON.stringify(key);
|
|
1157
|
+
const keyStr = JSON.stringify(toRuntimeTrieKey(key));
|
|
1147
1158
|
lines.push(`${nextIndent}${keyStr}: ${childStr},`);
|
|
1148
1159
|
}
|
|
1149
1160
|
}
|
|
@@ -1193,38 +1204,44 @@ function createServerPlugins(ctx, _qwikPlugin, c, esmImports, isSSR) {
|
|
|
1193
1204
|
}
|
|
1194
1205
|
c.push(`];`);
|
|
1195
1206
|
}
|
|
1207
|
+
/** The URL of the app's service worker entry, when the routes define one. */
|
|
1208
|
+
function resolveServiceWorkerUrl(ctx) {
|
|
1209
|
+
if (ctx.serviceWorkers.length === 0) return;
|
|
1210
|
+
const sw = ctx.serviceWorkers.sort((a, b) => a.chunkFileName.length < b.chunkFileName.length ? -1 : 1)[0];
|
|
1211
|
+
return ctx.opts.basePathname + sw.chunkFileName;
|
|
1212
|
+
}
|
|
1213
|
+
/** The `@qwik-router-sw-register` module, kept for apps that import it themselves. */
|
|
1214
|
+
function generateServiceWorkerRegister(ctx) {
|
|
1215
|
+
return `import { _getServiceWorkerScript } from '@qwik.dev/router';\nexport default _getServiceWorkerScript(${JSON.stringify(resolveServiceWorkerUrl(ctx))});\n`;
|
|
1216
|
+
}
|
|
1196
1217
|
/** Generates the Qwik Router Config runtime code */
|
|
1197
1218
|
function generateQwikRouterConfig(ctx, qwikPlugin, isSSR, loadersByFile, serverExcludePaths, routeLoaderSourceFiles) {
|
|
1198
1219
|
const esmImports = [];
|
|
1199
1220
|
const c = [];
|
|
1200
1221
|
c.push(`\n/** Qwik Router Config */`);
|
|
1201
1222
|
c.push(`\nimport { isDev } from '@qwik.dev/core/build';`);
|
|
1202
|
-
if (isSSR) esmImports.push(`import { importEagerModules } from 'virtual:qwik-router-server-fns';`, `export { importEagerModules } from 'virtual:qwik-router-server-fns';`);
|
|
1223
|
+
if (isSSR) esmImports.push(`import { importEagerModules } from 'virtual:qwik-router-server-fns';`, `export { importEagerModules } from 'virtual:qwik-router-server-fns';`, `import { _setRouterConfig } from '@qwik.dev/router';`);
|
|
1203
1224
|
createServerPlugins(ctx, qwikPlugin, c, esmImports, isSSR);
|
|
1204
1225
|
createRoutes(ctx, qwikPlugin, c, esmImports, isSSR, loadersByFile, serverExcludePaths, routeLoaderSourceFiles);
|
|
1205
1226
|
createEntries(ctx, c);
|
|
1206
|
-
c.push(`export const trailingSlash =
|
|
1227
|
+
c.push(`export const trailingSlash = !globalThis.__NO_TRAILING_SLASH__;`);
|
|
1207
1228
|
c.push(`export const basePathname = ${JSON.stringify(ctx.opts.basePathname)};`);
|
|
1208
1229
|
c.push(`export const cacheModules = !isDev;`);
|
|
1209
|
-
|
|
1210
|
-
|
|
1230
|
+
c.push(`export const serviceWorkerUrl = ${JSON.stringify(resolveServiceWorkerUrl(ctx))};`);
|
|
1231
|
+
const fields = [
|
|
1232
|
+
"routes",
|
|
1233
|
+
"serverPlugins",
|
|
1234
|
+
"trailingSlash",
|
|
1235
|
+
"basePathname",
|
|
1236
|
+
"cacheModules",
|
|
1237
|
+
"serviceWorkerUrl"
|
|
1238
|
+
];
|
|
1239
|
+
if (isSSR) fields.push("importEagerModules");
|
|
1240
|
+
c.push(`const config = { ${fields.join(", ")} };`);
|
|
1241
|
+
c.push(`export default config;`);
|
|
1242
|
+
if (isSSR) c.push(`_setRouterConfig(config);`);
|
|
1211
1243
|
return esmImports.join("\n") + c.join("\n");
|
|
1212
1244
|
}
|
|
1213
|
-
function generateServiceWorkerRegister(ctx, swRegister) {
|
|
1214
|
-
let swReg;
|
|
1215
|
-
let swUrl = "/service-worker.js";
|
|
1216
|
-
if (ctx.serviceWorkers.length === 0) swReg = SW_UNREGISTER;
|
|
1217
|
-
else {
|
|
1218
|
-
swReg = swRegister;
|
|
1219
|
-
const sw = ctx.serviceWorkers.sort((a, b) => a.chunkFileName.length < b.chunkFileName.length ? -1 : 1)[0];
|
|
1220
|
-
swUrl = ctx.opts.basePathname + sw.chunkFileName;
|
|
1221
|
-
}
|
|
1222
|
-
swReg = swReg.replace("__url", swUrl);
|
|
1223
|
-
return `export default ${JSON.stringify(swReg)};`;
|
|
1224
|
-
}
|
|
1225
|
-
var SW_UNREGISTER = `
|
|
1226
|
-
"serviceWorker"in navigator&&navigator.serviceWorker.getRegistrations().then(r=>{for(const e of r){const c='__url'.split("/").pop();e.active?.scriptURL.endsWith(c||"service-worker.js")&&e.unregister().catch(console.error)}}),"caches"in window&&caches.keys().then(r=>{const e=r.find(c=>c.startsWith("QwikBuild"));e&&caches.delete(e).catch(console.error)}).catch(console.error)
|
|
1227
|
-
`;
|
|
1228
1245
|
/**
|
|
1229
1246
|
* Non-GET RouteModule handlers keep a route server-side (onGet is served statically). Typed against
|
|
1230
1247
|
* keyof RouteModule so a renamed/added handler fails to compile until classified.
|
|
@@ -1933,7 +1950,6 @@ var makeRouterDevMiddleware = (server, ctx) => async (req, res, next) => {
|
|
|
1933
1950
|
res.end("/* Qwik Router Dev Service Worker */self.addEventListener('install', () => self.skipWaiting());self.addEventListener('activate', (ev) => ev.waitUntil(self.clients.claim()));");
|
|
1934
1951
|
return;
|
|
1935
1952
|
}
|
|
1936
|
-
globalThis.__qwik = void 0;
|
|
1937
1953
|
const { createQwikRouter } = await server.ssrLoadModule("@qwik.dev/router/middleware/node");
|
|
1938
1954
|
try {
|
|
1939
1955
|
const render = (async (opts) => {
|
|
@@ -2004,6 +2020,14 @@ var CSS_EXTENSIONS = [
|
|
|
2004
2020
|
var JS_EXTENSIONS = /\.[mc]?[tj]sx?$/;
|
|
2005
2021
|
var isCssPath = (url) => CSS_EXTENSIONS.some((ext) => url.endsWith(ext));
|
|
2006
2022
|
/**
|
|
2023
|
+
* The URL the Vite dev server serves a module under. For a file, the module graph URL is already
|
|
2024
|
+
* one (`/src/a.css`, `/@fs/...`). A virtual module from a plugin has its id as URL, and Vite serves
|
|
2025
|
+
* it under `/@id/` with the `\0` written as `__x00__`, the same as Vite's own `wrapId`.
|
|
2026
|
+
*
|
|
2027
|
+
* `\0virtual:theme.css` -> `/@id/__x00__virtual:theme.css`
|
|
2028
|
+
*/
|
|
2029
|
+
var toDevServerUrl = (url) => url.startsWith("/") ? url : `/@id/${url.replace("\0", "__x00__")}`;
|
|
2030
|
+
/**
|
|
2007
2031
|
* Qwik handles CSS imports itself, meaning vite doesn't get to see them, so we need to manually
|
|
2008
2032
|
* inject the CSS URLs.
|
|
2009
2033
|
*
|
|
@@ -2031,8 +2055,8 @@ var getCssUrls = (server) => {
|
|
|
2031
2055
|
return importerPath && JS_EXTENSIONS.test(importerPath);
|
|
2032
2056
|
});
|
|
2033
2057
|
if ((isEntryCSS || hasJSImporter) && !hasCSSImporter && !cssImportedByCSS.has(mod.url)) {
|
|
2034
|
-
cssModules.add(`${mod.url}${mod.lastHMRTimestamp ? `?t=${mod.lastHMRTimestamp}` : ""}`);
|
|
2035
|
-
if (mod.file) server.watcher.add(mod.file);
|
|
2058
|
+
cssModules.add(`${toDevServerUrl(mod.url)}${mod.lastHMRTimestamp ? `?t=${mod.lastHMRTimestamp}` : ""}`);
|
|
2059
|
+
if (mod.file && mod.url.startsWith("/")) server.watcher.add(mod.file);
|
|
2036
2060
|
}
|
|
2037
2061
|
}
|
|
2038
2062
|
}
|
|
@@ -2224,6 +2248,8 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
|
|
|
2224
2248
|
let reExportedRouteLoaderSources;
|
|
2225
2249
|
/** SSG include/exclude from the adapter (see `_setSsgRoutes`); drives the server-route prune. */
|
|
2226
2250
|
let ssgRoutePatterns;
|
|
2251
|
+
/** Extensionless ids of the server entries that must import the generated config. */
|
|
2252
|
+
let serverEntryIds = [];
|
|
2227
2253
|
return {
|
|
2228
2254
|
name: "vite-plugin-qwik-router",
|
|
2229
2255
|
enforce: "pre",
|
|
@@ -2336,6 +2362,7 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
|
|
|
2336
2362
|
return getRouteImports(ctx.routes, manifest);
|
|
2337
2363
|
});
|
|
2338
2364
|
outDir = config.build?.outDir;
|
|
2365
|
+
serverEntryIds = getServerEntryIds(rootDir, qwikPlugin.api.getOptions().srcDir ?? void 0, config.build?.ssr, config.build?.rolldownOptions?.input);
|
|
2339
2366
|
},
|
|
2340
2367
|
async configureServer(server) {
|
|
2341
2368
|
devServer = server;
|
|
@@ -2410,12 +2437,16 @@ function qwikRouterPlugin(userOpts, buildContextRef) {
|
|
|
2410
2437
|
});
|
|
2411
2438
|
return generateQwikRouterConfig(ctx, qwikPlugin, isServerConsumer, devServer ? loadersByFile : void 0, serverExcludePaths, reExportedRouteLoaderSources);
|
|
2412
2439
|
}
|
|
2413
|
-
if (isSwRegister) return generateServiceWorkerRegister(ctx
|
|
2440
|
+
if (isSwRegister) return generateServiceWorkerRegister(ctx);
|
|
2414
2441
|
}
|
|
2415
2442
|
}
|
|
2416
2443
|
return null;
|
|
2417
2444
|
},
|
|
2418
2445
|
async transform(code, id) {
|
|
2446
|
+
if (this.environment.config.consumer === "server" && isServerEntryId(id, serverEntryIds)) return {
|
|
2447
|
+
code: `${code}\nimport '${QWIK_ROUTER_CONFIG_ID}';`,
|
|
2448
|
+
map: null
|
|
2449
|
+
};
|
|
2419
2450
|
if (id.startsWith("\0")) return;
|
|
2420
2451
|
const ext = extname(id).toLowerCase();
|
|
2421
2452
|
if (ctx && (ext === ".md" || ext === ".mdx")) {
|
|
@@ -2547,4 +2578,28 @@ function serverFnsPlugin(buildContextRef) {
|
|
|
2547
2578
|
}
|
|
2548
2579
|
};
|
|
2549
2580
|
}
|
|
2581
|
+
/**
|
|
2582
|
+
* The server entries: `src/entry.ssr` (what the dev server renders through) plus the configured SSR
|
|
2583
|
+
* build inputs, which may be virtual ids.
|
|
2584
|
+
*/
|
|
2585
|
+
function getServerEntryIds(rootDir, srcDir, buildSsr, input) {
|
|
2586
|
+
const candidates = [];
|
|
2587
|
+
if (srcDir) candidates.push(resolve(srcDir, "entry.ssr"));
|
|
2588
|
+
if (typeof buildSsr === "string") candidates.push(buildSsr);
|
|
2589
|
+
if (typeof input === "string") candidates.push(input);
|
|
2590
|
+
else if (Array.isArray(input)) candidates.push(...input);
|
|
2591
|
+
else if (input) candidates.push(...Object.values(input));
|
|
2592
|
+
return candidates.map((candidate) => normalizeEntryId(candidate, rootDir));
|
|
2593
|
+
}
|
|
2594
|
+
function isServerEntryId(id, serverEntryIds) {
|
|
2595
|
+
const entryId = normalizeEntryId(id.split("?", 1)[0], "");
|
|
2596
|
+
return serverEntryIds.includes(entryId);
|
|
2597
|
+
}
|
|
2598
|
+
var isVirtualEntryId = (id) => id.startsWith("@") || id.startsWith("\0");
|
|
2599
|
+
/** Absolute path without its script extension, or the id itself for a virtual entry. */
|
|
2600
|
+
function normalizeEntryId(id, rootDir) {
|
|
2601
|
+
if (isVirtualEntryId(id)) return id;
|
|
2602
|
+
const absolute = rootDir ? resolve(rootDir, id) : id;
|
|
2603
|
+
return normalizePath$1(absolute).replace(/\.[cm]?[jt]sx?$/, "");
|
|
2604
|
+
}
|
|
2550
2605
|
export { extendConfig, qwikCity, qwikRouter };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwik.dev/router",
|
|
3
3
|
"description": "The router for Qwik.",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.47",
|
|
5
5
|
"bugs": "https://github.com/QwikDev/qwik/issues",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@azure/functions": "3.5.1",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"typescript": "5.9.3",
|
|
42
42
|
"uvu": "0.5.6",
|
|
43
43
|
"vite": "8.2.1",
|
|
44
|
-
"@qwik.dev/core": "2.0.0-beta.
|
|
44
|
+
"@qwik.dev/core": "2.0.0-beta.47"
|
|
45
45
|
},
|
|
46
46
|
"engines": {
|
|
47
47
|
"node": "^18.17.0 || ^20.3.0 || >=21.0.0"
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
"main": "./lib/index.qwik.mjs",
|
|
167
167
|
"peerDependencies": {
|
|
168
168
|
"vite": ">=8 <9",
|
|
169
|
-
"@qwik.dev/core": "2.0.0-beta.
|
|
169
|
+
"@qwik.dev/core": "2.0.0-beta.47"
|
|
170
170
|
},
|
|
171
171
|
"publishConfig": {
|
|
172
172
|
"access": "public"
|