@qwik.dev/router 2.0.0-beta.28 → 2.0.0-beta.29

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 (42) hide show
  1. package/lib/adapters/azure-swa/vite/index.mjs +31 -36
  2. package/lib/adapters/bun-server/vite/index.mjs +0 -3
  3. package/lib/adapters/cloud-run/vite/index.mjs +0 -3
  4. package/lib/adapters/cloudflare-pages/vite/index.mjs +15 -9
  5. package/lib/adapters/deno-server/vite/index.mjs +7 -5
  6. package/lib/adapters/netlify-edge/vite/index.mjs +13 -23
  7. package/lib/adapters/node-server/vite/index.mjs +0 -3
  8. package/lib/adapters/shared/vite/index.d.ts +1 -7
  9. package/lib/adapters/shared/vite/index.mjs +164 -136
  10. package/lib/adapters/ssg/vite/index.mjs +3 -4
  11. package/lib/adapters/vercel-edge/vite/index.mjs +25 -9
  12. package/lib/chunks/error-handler.mjs +26 -26
  13. package/lib/chunks/fs.mjs +28 -138
  14. package/lib/chunks/http-error.qwik.mjs +27 -0
  15. package/lib/chunks/not-found-wrapper.qwik.mjs +25 -0
  16. package/lib/chunks/pathname.mjs +105 -0
  17. package/lib/chunks/routing.qwik.mjs +592 -216
  18. package/lib/chunks/system.mjs +328 -0
  19. package/lib/chunks/use-functions.qwik.mjs +35 -0
  20. package/lib/chunks/worker-thread.mjs +271 -0
  21. package/lib/index.d.ts +136 -102
  22. package/lib/index.qwik.mjs +699 -751
  23. package/lib/middleware/aws-lambda/index.mjs +7 -1
  24. package/lib/middleware/azure-swa/index.mjs +7 -2
  25. package/lib/middleware/bun/index.mjs +20 -5
  26. package/lib/middleware/cloudflare-pages/index.mjs +8 -2
  27. package/lib/middleware/deno/index.mjs +19 -5
  28. package/lib/middleware/netlify-edge/index.mjs +8 -2
  29. package/lib/middleware/node/index.mjs +10 -14
  30. package/lib/middleware/request-handler/index.d.ts +82 -12
  31. package/lib/middleware/request-handler/index.mjs +661 -524
  32. package/lib/middleware/vercel-edge/index.mjs +8 -2
  33. package/lib/modules.d.ts +7 -4
  34. package/lib/ssg/index.d.ts +48 -16
  35. package/lib/ssg/index.mjs +320 -7
  36. package/lib/vite/index.d.ts +6 -0
  37. package/lib/vite/index.mjs +1098 -641
  38. package/modules.d.ts +7 -4
  39. package/package.json +4 -4
  40. package/lib/chunks/format-error.mjs +0 -137
  41. package/lib/chunks/index.mjs +0 -896
  42. package/lib/chunks/types.qwik.mjs +0 -22
@@ -1,7 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { viteAdapter } from '../../shared/vite/index.mjs';
4
- import '../../../chunks/error-handler.mjs';
5
4
 
6
5
  function azureSwaAdapter(opts = {}) {
7
6
  const env = process?.env;
@@ -13,43 +12,39 @@ function azureSwaAdapter(opts = {}) {
13
12
  async generate({ outputEntries, serverOutDir, clientPublicOutDir }) {
14
13
  const serverPackageJsonPath = join(serverOutDir, "package.json");
15
14
  const serverPackageJsonCode = `{"type":"module"}`;
16
- await fs.promises.mkdir(serverOutDir, { recursive: true });
15
+ await fs.promises.mkdir(serverOutDir, {
16
+ recursive: true
17
+ });
17
18
  await fs.promises.writeFile(serverPackageJsonPath, serverPackageJsonCode);
18
- const azureSwaModulePath = outputEntries.find(
19
- (entryName) => entryName.indexOf("entry.azure-swa") === 0
20
- );
19
+ const azureSwaModulePath = outputEntries.find((entryName) => entryName.indexOf("entry.azure-swa") === 0);
21
20
  const funcJsonPath = join(serverOutDir, "function.json");
22
- const funcJson = JSON.stringify(
23
- {
24
- bindings: [
25
- {
26
- authLevel: "anonymous",
27
- type: "httpTrigger",
28
- direction: "in",
29
- name: "req",
30
- methods: [
31
- "get",
32
- "head",
33
- "post",
34
- "put",
35
- "delete",
36
- "connect",
37
- "options",
38
- "trace",
39
- "patch"
40
- ]
41
- },
42
- {
43
- type: "http",
44
- direction: "out",
45
- name: "$return"
46
- }
47
- ],
48
- scriptFile: azureSwaModulePath
49
- },
50
- null,
51
- 2
52
- );
21
+ const funcJson = JSON.stringify({
22
+ bindings: [
23
+ {
24
+ authLevel: "anonymous",
25
+ type: "httpTrigger",
26
+ direction: "in",
27
+ name: "req",
28
+ methods: [
29
+ "get",
30
+ "head",
31
+ "post",
32
+ "put",
33
+ "delete",
34
+ "connect",
35
+ "options",
36
+ "trace",
37
+ "patch"
38
+ ]
39
+ },
40
+ {
41
+ type: "http",
42
+ direction: "out",
43
+ name: "$return"
44
+ }
45
+ ],
46
+ scriptFile: azureSwaModulePath
47
+ }, null, 2);
53
48
  await fs.promises.writeFile(funcJsonPath, funcJson);
54
49
  if (!fs.existsSync(join(clientPublicOutDir, "index.html"))) {
55
50
  await fs.promises.writeFile(join(clientPublicOutDir, "index.html"), "");
@@ -1,7 +1,4 @@
1
1
  import { viteAdapter } from '../../shared/vite/index.mjs';
2
- import 'node:path';
3
- import 'node:fs';
4
- import '../../../chunks/error-handler.mjs';
5
2
 
6
3
  function bunServerAdapter(opts = {}) {
7
4
  const env = process?.env;
@@ -1,7 +1,4 @@
1
1
  import { viteAdapter } from '../../shared/vite/index.mjs';
2
- import 'node:path';
3
- import 'node:fs';
4
- import '../../../chunks/error-handler.mjs';
5
2
 
6
3
  function cloudRunAdapter(opts = {}) {
7
4
  const env = process?.env;
@@ -2,7 +2,6 @@ import fs from 'node:fs';
2
2
  import { join, relative } from 'node:path';
3
3
  import { n as normalizePathSlash } from '../../../chunks/fs.mjs';
4
4
  import { viteAdapter } from '../../shared/vite/index.mjs';
5
- import '../../../chunks/error-handler.mjs';
6
5
 
7
6
  function cloudflarePagesAdapter(opts = {}) {
8
7
  const env = process?.env;
@@ -15,12 +14,17 @@ function cloudflarePagesAdapter(opts = {}) {
15
14
  config() {
16
15
  return {
17
16
  resolve: {
18
- conditions: ["webworker", "worker"]
17
+ conditions: [
18
+ "webworker",
19
+ "worker"
20
+ ]
19
21
  },
20
22
  ssr: {
21
23
  target: "webworker",
22
24
  noExternal: true,
23
- external: ["node:async_hooks"]
25
+ external: [
26
+ "node:async_hooks"
27
+ ]
24
28
  },
25
29
  build: {
26
30
  ssr: true,
@@ -44,8 +48,13 @@ function cloudflarePagesAdapter(opts = {}) {
44
48
  }
45
49
  const routesJson = {
46
50
  version: 1,
47
- include: [basePathname + "*"],
48
- exclude: [pathName + "build/*", pathName + "assets/*"]
51
+ include: [
52
+ basePathname + "*"
53
+ ],
54
+ exclude: [
55
+ pathName + "build/*",
56
+ pathName + "assets/*"
57
+ ]
49
58
  };
50
59
  await fs.promises.writeFile(routesJsonPath, JSON.stringify(routesJson, void 0, 2));
51
60
  }
@@ -53,10 +62,7 @@ function cloudflarePagesAdapter(opts = {}) {
53
62
  const hasWorkerJs = fs.existsSync(workerJsPath);
54
63
  if (!hasWorkerJs) {
55
64
  const importPath = relative(clientOutDir, join(serverOutDir, "entry.cloudflare-pages"));
56
- await fs.promises.writeFile(
57
- workerJsPath,
58
- `import { fetch } from "${normalizePathSlash(importPath)}"; export default { fetch };`
59
- );
65
+ await fs.promises.writeFile(workerJsPath, `import { fetch } from "${normalizePathSlash(importPath)}"; export default { fetch };`);
60
66
  }
61
67
  }
62
68
  });
@@ -1,7 +1,4 @@
1
1
  import { viteAdapter } from '../../shared/vite/index.mjs';
2
- import 'node:path';
3
- import 'node:fs';
4
- import '../../../chunks/error-handler.mjs';
5
2
 
6
3
  function denoServerAdapter(opts = {}) {
7
4
  const env = process?.env;
@@ -13,12 +10,17 @@ function denoServerAdapter(opts = {}) {
13
10
  config() {
14
11
  return {
15
12
  resolve: {
16
- conditions: ["webworker", "worker"]
13
+ conditions: [
14
+ "webworker",
15
+ "worker"
16
+ ]
17
17
  },
18
18
  ssr: {
19
19
  target: "webworker",
20
20
  noExternal: true,
21
- external: ["node:async_hooks"]
21
+ external: [
22
+ "node:async_hooks"
23
+ ]
22
24
  },
23
25
  build: {
24
26
  ssr: true,
@@ -1,7 +1,6 @@
1
1
  import fs, { existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { viteAdapter, getParentDir } from '../../shared/vite/index.mjs';
4
- import '../../../chunks/error-handler.mjs';
5
4
 
6
5
  function netlifyEdgeAdapter(opts = {}) {
7
6
  const env = process?.env;
@@ -15,12 +14,17 @@ function netlifyEdgeAdapter(opts = {}) {
15
14
  const outDir = config.build?.outDir || ".netlify/edge-functions/entry.netlify-edge";
16
15
  return {
17
16
  resolve: {
18
- conditions: ["webworker", "worker"]
17
+ conditions: [
18
+ "webworker",
19
+ "worker"
20
+ ]
19
21
  },
20
22
  ssr: {
21
23
  target: "webworker",
22
24
  noExternal: true,
23
- external: ["node:async_hooks"]
25
+ external: [
26
+ "node:async_hooks"
27
+ ]
24
28
  },
25
29
  build: {
26
30
  ssr: true,
@@ -43,15 +47,7 @@ function netlifyEdgeAdapter(opts = {}) {
43
47
  } else if (Array.isArray(opts.excludedPath)) {
44
48
  excludedPath.push(...opts.excludedPath);
45
49
  } else {
46
- excludedPath.push(
47
- "/build/*",
48
- "/favicon.ico",
49
- "/robots.txt",
50
- "/mainifest.json",
51
- "/~partytown/*",
52
- "/service-worker.js",
53
- "/sitemap.xml"
54
- );
50
+ excludedPath.push("/build/*", "/favicon.ico", "/robots.txt", "/mainifest.json", "/~partytown/*", "/service-worker.js", "/sitemap.xml");
55
51
  }
56
52
  const netlifyEdgeManifest = {
57
53
  functions: [
@@ -67,19 +63,13 @@ function netlifyEdgeAdapter(opts = {}) {
67
63
  const jsPath = join(serverOutDir, "entry.netlify-edge.js");
68
64
  const mjsPath = join(serverOutDir, "entry.netlify-edge.mjs");
69
65
  if (existsSync(mjsPath)) {
70
- await fs.promises.writeFile(
71
- jsPath,
72
- [
73
- `import entry_netlifyEdge from './entry.netlify-edge.mjs';`,
74
- `export default entry_netlifyEdge;`
75
- ].join("\n")
76
- );
66
+ await fs.promises.writeFile(jsPath, [
67
+ `import entry_netlifyEdge from './entry.netlify-edge.mjs';`,
68
+ `export default entry_netlifyEdge;`
69
+ ].join("\n"));
77
70
  }
78
71
  const netlifyEdgeFnsDir = getParentDir(serverOutDir, "edge-functions");
79
- await fs.promises.writeFile(
80
- join(netlifyEdgeFnsDir, "manifest.json"),
81
- JSON.stringify(netlifyEdgeManifest, null, 2)
82
- );
72
+ await fs.promises.writeFile(join(netlifyEdgeFnsDir, "manifest.json"), JSON.stringify(netlifyEdgeManifest, null, 2));
83
73
  }
84
74
  }
85
75
  });
@@ -1,7 +1,4 @@
1
1
  import { viteAdapter } from '../../shared/vite/index.mjs';
2
- import 'node:path';
3
- import 'node:fs';
4
- import '../../../chunks/error-handler.mjs';
5
2
 
6
3
  function nodeServerAdapter(opts = {}) {
7
4
  const env = process?.env;
@@ -74,13 +74,7 @@ export declare interface ServerAdapterOptions {
74
74
  ssg?: AdapterSSGOptions | null;
75
75
  }
76
76
 
77
- /**
78
- * Implements the SSG after the build is complete. Also provides a `generate(...)` callback that is
79
- * called after the SSG is complete, which allows for custom post-processing of the complete build
80
- * results.
81
- *
82
- * @public
83
- */
77
+ /** @public */
84
78
  export declare function viteAdapter(opts: ViteAdapterPluginOptions): Plugin_2<never>;
85
79
 
86
80
  /** @public */
@@ -2,51 +2,6 @@ import { join, resolve, dirname, basename } from 'node:path';
2
2
  import fs from 'node:fs';
3
3
  import { g as getErrorHtml } from '../../../chunks/error-handler.mjs';
4
4
 
5
- async function postBuild(clientOutDir, serverOutDir, pathName, userStaticPaths, cleanStatic) {
6
- if (pathName && !pathName.endsWith("/")) {
7
- pathName += "/";
8
- }
9
- const ignorePathnames = /* @__PURE__ */ new Set([
10
- pathName + "/" + (globalThis.__QWIK_BUILD_DIR__ || "build") + "/",
11
- pathName + "/" + (globalThis.__QWIK_ASSETS_DIR__ || "assets") + "/"
12
- ]);
13
- const staticPaths = new Set(userStaticPaths.map(normalizeTrailingSlash));
14
- const notFounds = [];
15
- const loadItem = async (fsDir, fsName, pathname) => {
16
- pathname = normalizeTrailingSlash(pathname);
17
- if (ignorePathnames.has(pathname)) {
18
- return;
19
- }
20
- const fsPath = join(fsDir, fsName);
21
- if (fsName === "index.html" || fsName === "q-data.json") {
22
- if (!staticPaths.has(pathname) && cleanStatic) {
23
- await fs.promises.unlink(fsPath);
24
- }
25
- return;
26
- }
27
- if (fsName === "404.html") {
28
- const notFoundHtml = await fs.promises.readFile(fsPath, "utf-8");
29
- notFounds.push([pathname, notFoundHtml]);
30
- return;
31
- }
32
- const stat = await fs.promises.stat(fsPath);
33
- if (stat.isDirectory()) {
34
- await loadDir(fsPath, pathname + fsName + "/");
35
- } else if (stat.isFile()) {
36
- staticPaths.add(pathname + fsName);
37
- }
38
- };
39
- const loadDir = async (fsDir, pathname) => {
40
- const itemNames = await fs.promises.readdir(fsDir);
41
- await Promise.all(itemNames.map((i) => loadItem(fsDir, i, pathname)));
42
- };
43
- if (fs.existsSync(clientOutDir)) {
44
- await loadDir(clientOutDir, pathName);
45
- }
46
- const notFoundPathsCode = createNotFoundPathsCode(pathName, notFounds);
47
- const staticPathsCode = createStaticPathsCode(staticPaths);
48
- await injectStatics(staticPathsCode, notFoundPathsCode, serverOutDir);
49
- }
50
5
  function normalizeTrailingSlash(pathname) {
51
6
  if (!pathname.endsWith("/")) {
52
7
  return pathname + "/";
@@ -71,7 +26,10 @@ function createNotFoundPathsCode(basePathname, notFounds) {
71
26
  });
72
27
  if (!notFounds.some((r) => r[0] === basePathname)) {
73
28
  const html = getErrorHtml(404, "Resource Not Found");
74
- notFounds.push([basePathname, html]);
29
+ notFounds.push([
30
+ basePathname,
31
+ html
32
+ ]);
75
33
  }
76
34
  return JSON.stringify(notFounds, null, 2).slice(1, -1);
77
35
  }
@@ -83,19 +41,18 @@ const injectStatics = async (staticPathsCode, notFoundPathsCode, outDir) => {
83
41
  const doReplace = async (path) => {
84
42
  const code = await fs.promises.readFile(path, "utf-8");
85
43
  let replaced = false;
86
- const newCode = code.replace(
87
- /(['"])__QWIK_ROUTER_(STATIC_PATHS|NOT_FOUND)_ARRAY__\1/g,
88
- (_, _quote, type) => {
89
- replaced = true;
90
- return type === "STATIC_PATHS" ? staticPathsCode : notFoundPathsCode;
91
- }
92
- );
44
+ const newCode = code.replace(/(['"])__QWIK_ROUTER_(STATIC_PATHS|NOT_FOUND)_ARRAY__\1/g, (_, _quote, type) => {
45
+ replaced = true;
46
+ return type === "STATIC_PATHS" ? staticPathsCode : notFoundPathsCode;
47
+ });
93
48
  if (replaced) {
94
49
  await fs.promises.writeFile(path, newCode);
95
50
  }
96
51
  };
97
52
  const walk = async (dir) => {
98
- const entries = await fs.promises.readdir(dir, { withFileTypes: true });
53
+ const entries = await fs.promises.readdir(dir, {
54
+ withFileTypes: true
55
+ });
99
56
  for (const entry of entries) {
100
57
  if (entry.isDirectory()) {
101
58
  await walk(join(dir, entry.name));
@@ -110,13 +67,61 @@ const injectStatics = async (staticPathsCode, notFoundPathsCode, outDir) => {
110
67
  await walk(outDir);
111
68
  await Promise.all(promises);
112
69
  };
70
+ async function postBuild(clientOutDir, serverOutDir, pathName, userStaticPaths, cleanStatic) {
71
+ if (pathName && !pathName.endsWith("/")) {
72
+ pathName += "/";
73
+ }
74
+ const ignorePathnames = /* @__PURE__ */ new Set([
75
+ pathName + "/" + (globalThis.__QWIK_BUILD_DIR__ || "build") + "/",
76
+ pathName + "/" + (globalThis.__QWIK_ASSETS_DIR__ || "assets") + "/"
77
+ ]);
78
+ const staticPaths = new Set(userStaticPaths.map(normalizeTrailingSlash));
79
+ const notFounds = [];
80
+ const loadItem = async (fsDir, fsName, pathname) => {
81
+ pathname = normalizeTrailingSlash(pathname);
82
+ if (ignorePathnames.has(pathname)) {
83
+ return;
84
+ }
85
+ const fsPath = join(fsDir, fsName);
86
+ if (fsName === "index.html" || fsName === "q-data.json") {
87
+ if (!staticPaths.has(pathname) && cleanStatic) {
88
+ await fs.promises.unlink(fsPath);
89
+ }
90
+ return;
91
+ }
92
+ if (fsName === "404.html") {
93
+ const notFoundHtml = await fs.promises.readFile(fsPath, "utf-8");
94
+ notFounds.push([
95
+ pathname,
96
+ notFoundHtml
97
+ ]);
98
+ return;
99
+ }
100
+ const stat = await fs.promises.stat(fsPath);
101
+ if (stat.isDirectory()) {
102
+ await loadDir(fsPath, pathname + fsName + "/");
103
+ } else if (stat.isFile()) {
104
+ staticPaths.add(pathname + fsName);
105
+ }
106
+ };
107
+ const loadDir = async (fsDir, pathname) => {
108
+ const itemNames = await fs.promises.readdir(fsDir);
109
+ await Promise.all(itemNames.map((i) => loadItem(fsDir, i, pathname)));
110
+ };
111
+ if (fs.existsSync(clientOutDir)) {
112
+ await loadDir(clientOutDir, pathName);
113
+ }
114
+ const notFoundPathsCode = createNotFoundPathsCode(pathName, notFounds);
115
+ const staticPathsCode = createStaticPathsCode(staticPaths);
116
+ await injectStatics(staticPathsCode, notFoundPathsCode, serverOutDir);
117
+ }
113
118
 
119
+ const QWIK_SSG_ENTRY_ID = "@qwik-ssg-entry";
120
+ const QWIK_SSG_ENTRY_RESOLVED = "\0@qwik-ssg-entry";
114
121
  function viteAdapter(opts) {
115
122
  let qwikRouterPlugin = null;
116
123
  let qwikVitePlugin = null;
117
124
  let serverOutDir = null;
118
- let renderModulePath = null;
119
- let qwikRouterConfigModulePath = null;
120
125
  let viteCommand;
121
126
  const outputEntries = [];
122
127
  const plugin = {
@@ -135,36 +140,87 @@ function viteAdapter(opts) {
135
140
  },
136
141
  configResolved(config) {
137
142
  viteCommand = config.command;
138
- qwikRouterPlugin = config.plugins.find(
139
- (p) => p.name === "vite-plugin-qwik-router"
140
- );
143
+ qwikRouterPlugin = config.plugins.find((p) => p.name === "vite-plugin-qwik-router");
141
144
  if (!qwikRouterPlugin) {
142
145
  throw new Error("Missing vite-plugin-qwik-router");
143
146
  }
144
- qwikVitePlugin = config.plugins.find(
145
- (p) => p.name === "vite-plugin-qwik"
146
- );
147
+ qwikVitePlugin = config.plugins.find((p) => p.name === "vite-plugin-qwik");
147
148
  if (!qwikVitePlugin) {
148
149
  throw new Error("Missing vite-plugin-qwik");
149
150
  }
150
151
  serverOutDir = config.build.outDir;
151
152
  },
152
- buildStart() {
153
- if (this.environment.config.consumer === "server" && opts.ssg !== null) {
154
- const { srcDir } = qwikVitePlugin.api.getOptions();
155
- if (viteCommand === "build" && serverOutDir && srcDir) {
156
- this.emitFile({
157
- id: "@qwik-router-config",
158
- type: "chunk",
159
- fileName: "@qwik-router-config.js"
160
- });
161
- this.emitFile({
162
- id: `${srcDir}/entry.ssr`,
163
- type: "chunk",
164
- fileName: "entry.ssr.js"
165
- });
153
+ resolveId(id) {
154
+ if (id === QWIK_SSG_ENTRY_ID) {
155
+ return QWIK_SSG_ENTRY_RESOLVED;
156
+ }
157
+ },
158
+ load(id) {
159
+ if (id !== QWIK_SSG_ENTRY_RESOLVED) {
160
+ return;
161
+ }
162
+ const { srcDir } = qwikVitePlugin.api.getOptions();
163
+ const clientPublicOutDir = qwikVitePlugin.api.getClientPublicOutDir();
164
+ const basePathname = qwikRouterPlugin.api.getBasePathname();
165
+ const rootDir = qwikVitePlugin.api.getRootDir() ?? void 0;
166
+ let ssgOrigin = opts.ssg?.origin ?? opts.origin;
167
+ if (!ssgOrigin) {
168
+ ssgOrigin = `https://yoursite.qwik.dev`;
169
+ }
170
+ if (ssgOrigin.length > 0 && !/:\/\//.test(ssgOrigin)) {
171
+ ssgOrigin = `https://${ssgOrigin}`;
172
+ }
173
+ if (ssgOrigin.startsWith("//")) {
174
+ ssgOrigin = `https:${ssgOrigin}`;
175
+ }
176
+ try {
177
+ ssgOrigin = new URL(ssgOrigin).origin;
178
+ } catch {
179
+ this.warn(`Invalid "origin" option: "${ssgOrigin}". Using default origin: "https://yoursite.qwik.dev"`);
180
+ ssgOrigin = `https://yoursite.qwik.dev`;
181
+ }
182
+ const ssgOpts = {
183
+ origin: ssgOrigin,
184
+ outDir: clientPublicOutDir,
185
+ basePathname,
186
+ rootDir,
187
+ ...opts.ssg,
188
+ maxWorkers: opts.maxWorkers
189
+ };
190
+ for (const key of Object.keys(ssgOpts)) {
191
+ if (ssgOpts[key] === void 0) {
192
+ delete ssgOpts[key];
166
193
  }
167
194
  }
195
+ return [
196
+ `import { isMainThread } from 'node:worker_threads';`,
197
+ `import render from '${srcDir}/entry.ssr';`,
198
+ `import qwikRouterConfig from '@qwik-router-config';`,
199
+ ``,
200
+ `const ssgOpts = ${JSON.stringify(ssgOpts)};`,
201
+ ``,
202
+ `if (isMainThread) {`,
203
+ ` const { runSsg } = await import('@qwik.dev/router/ssg');`,
204
+ ` await runSsg({`,
205
+ ` render,`,
206
+ ` qwikRouterConfig,`,
207
+ ` workerFilePath: new URL(import.meta.url).href,`,
208
+ ` ...ssgOpts,`,
209
+ ` });`,
210
+ `} else {`,
211
+ ` const { startWorker } = await import('@qwik.dev/router/ssg');`,
212
+ ` await startWorker({ render, qwikRouterConfig });`,
213
+ `}`
214
+ ].join("\n");
215
+ },
216
+ buildStart() {
217
+ if (this.environment.config.consumer === "server" && opts.ssg !== null && viteCommand === "build" && serverOutDir) {
218
+ this.emitFile({
219
+ id: QWIK_SSG_ENTRY_ID,
220
+ type: "chunk",
221
+ fileName: "run-ssg.js"
222
+ });
223
+ }
168
224
  },
169
225
  generateBundle(_, bundles) {
170
226
  if (this.environment.config.consumer === "server") {
@@ -173,11 +229,6 @@ function viteAdapter(opts) {
173
229
  const chunk = bundles[fileName];
174
230
  if (chunk.type === "chunk" && chunk.isEntry) {
175
231
  outputEntries.push(fileName);
176
- if (chunk.name === "entry.ssr") {
177
- renderModulePath = join(serverOutDir, fileName);
178
- } else if (chunk.name === "@qwik-router-config") {
179
- qwikRouterConfigModulePath = join(serverOutDir, fileName);
180
- }
181
232
  }
182
233
  }
183
234
  }
@@ -192,54 +243,41 @@ function viteAdapter(opts) {
192
243
  const clientOutDir = qwikVitePlugin.api.getClientOutDir();
193
244
  const clientPublicOutDir = qwikVitePlugin.api.getClientPublicOutDir();
194
245
  const assetsDir = qwikVitePlugin.api.getAssetsDir();
195
- const rootDir = qwikVitePlugin.api.getRootDir() ?? void 0;
196
- if (opts.ssg !== null && renderModulePath && qwikRouterConfigModulePath && clientOutDir && clientPublicOutDir) {
197
- let ssgOrigin = opts.ssg?.origin ?? opts.origin;
198
- if (!ssgOrigin) {
199
- ssgOrigin = `https://yoursite.qwik.dev`;
200
- }
201
- if (ssgOrigin.length > 0 && !/:\/\//.test(ssgOrigin)) {
202
- ssgOrigin = `https://${ssgOrigin}`;
203
- }
204
- if (ssgOrigin.startsWith("//")) {
205
- ssgOrigin = `https:${ssgOrigin}`;
246
+ if (opts.ssg !== null && clientOutDir && clientPublicOutDir) {
247
+ const runSsgPath = join(serverOutDir, "run-ssg.js");
248
+ const { spawn } = await import('node:child_process');
249
+ const ssgExitCode = await new Promise((resolve2, reject) => {
250
+ const child = spawn(process.execPath, [
251
+ runSsgPath
252
+ ], {
253
+ stdio: [
254
+ "ignore",
255
+ "inherit",
256
+ "inherit"
257
+ ],
258
+ env: {
259
+ ...process.env,
260
+ NODE_ENV: process.env.NODE_ENV || "production"
261
+ }
262
+ });
263
+ child.on("close", resolve2);
264
+ child.on("error", reject);
265
+ });
266
+ if (ssgExitCode !== 0) {
267
+ const err = new Error(`Error while running SSG from "${opts.name}" adapter. At least one path failed to render.`);
268
+ err.stack = void 0;
269
+ this.error(err);
206
270
  }
271
+ const fs = await import('node:fs');
272
+ const staticPathsFile = join(clientPublicOutDir, "_static-paths.json");
207
273
  try {
208
- ssgOrigin = new URL(ssgOrigin).origin;
274
+ const content = await fs.promises.readFile(staticPathsFile, "utf-8");
275
+ staticPaths.push(...JSON.parse(content));
276
+ await fs.promises.unlink(staticPathsFile);
209
277
  } catch {
210
- this.warn(
211
- `Invalid "origin" option: "${ssgOrigin}". Using default origin: "https://yoursite.qwik.dev"`
212
- );
213
- ssgOrigin = `https://yoursite.qwik.dev`;
214
278
  }
215
- const staticGenerate = await import('../../../ssg/index.mjs');
216
- const generateOpts = {
217
- maxWorkers: opts.maxWorkers,
218
- basePathname,
219
- outDir: clientPublicOutDir,
220
- rootDir,
221
- ...opts.ssg,
222
- origin: ssgOrigin,
223
- renderModulePath,
224
- qwikRouterConfigModulePath
225
- };
226
- const staticGenerateResult = await staticGenerate.generate(generateOpts);
227
- if (staticGenerateResult.errors > 0) {
228
- const err = new Error(
229
- `Error while running SSG from "${opts.name}" adapter. At least one path failed to render.`
230
- );
231
- err.stack = void 0;
232
- this.error(err);
233
- }
234
- staticPaths.push(...staticGenerateResult.staticPaths);
235
279
  }
236
- await postBuild(
237
- clientPublicOutDir,
238
- serverOutDir,
239
- assetsDir ? join(basePathname, assetsDir) : basePathname,
240
- staticPaths,
241
- !!opts.cleanStaticGenerated
242
- );
280
+ await postBuild(clientPublicOutDir, serverOutDir, assetsDir ? join(basePathname, assetsDir) : basePathname, staticPaths, !!opts.cleanStaticGenerated);
243
281
  if (typeof opts.generate === "function") {
244
282
  await opts.generate({
245
283
  outputEntries,
@@ -253,21 +291,11 @@ function viteAdapter(opts) {
253
291
  error: (message) => this.error(message)
254
292
  });
255
293
  }
256
- this.warn(
257
- `
294
+ this.warn(`
258
295
  ==============================================
259
296
  Note: Make sure that you are serving the built files with proper cache headers.
260
297
  See https://qwik.dev/docs/deployments/#cache-headers for more information.
261
- ==============================================`
262
- );
263
- if (opts.ssg !== null) {
264
- setTimeout(() => {
265
- console.warn(
266
- "SSG seems to be hanging after completion, forcing process to exit. Everything is likely fine."
267
- );
268
- process.exit(0);
269
- }, 5e3).unref();
270
- }
298
+ ==============================================`);
271
299
  }
272
300
  }
273
301
  }