@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.21

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 (195) hide show
  1. package/package.json +62 -36
  2. package/src/cli.js +15 -12
  3. package/src/constants.js +6 -1
  4. package/src/core/adapt/builder.js +66 -72
  5. package/src/core/adapt/index.js +17 -6
  6. package/src/core/config/index.js +134 -80
  7. package/src/core/config/options.js +295 -273
  8. package/src/core/config/types.d.ts +1 -1
  9. package/src/core/env.js +146 -16
  10. package/src/core/generate_manifest/index.js +18 -15
  11. package/src/core/postbuild/analyse.js +8 -20
  12. package/src/core/postbuild/crawl.js +22 -6
  13. package/src/core/postbuild/entities.js +8 -2
  14. package/src/core/postbuild/fallback.js +4 -2
  15. package/src/core/postbuild/prerender.js +222 -70
  16. package/src/core/postbuild/queue.js +2 -1
  17. package/src/core/sync/create_manifest_data/conflict.js +1 -1
  18. package/src/core/sync/create_manifest_data/index.js +82 -62
  19. package/src/core/sync/sync.js +40 -31
  20. package/src/core/sync/ts.js +1 -1
  21. package/src/core/sync/utils.js +22 -2
  22. package/src/core/sync/{write_non_ambient.js → write_app_types.js} +107 -58
  23. package/src/core/sync/write_client_manifest.js +14 -29
  24. package/src/core/sync/write_env.js +7 -5
  25. package/src/core/sync/write_server.js +37 -45
  26. package/src/core/sync/write_tsconfig/index.js +274 -0
  27. package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
  28. package/src/core/sync/write_tsconfig/utils.js +77 -0
  29. package/src/core/sync/write_tsconfig/validate.js +128 -0
  30. package/src/core/sync/write_types/index.js +127 -123
  31. package/src/core/utils.js +30 -5
  32. package/src/exports/env/index.js +77 -0
  33. package/src/exports/env/public.d.ts +55 -0
  34. package/src/exports/hooks/index.js +3 -9
  35. package/src/exports/hooks/public.d.ts +195 -0
  36. package/src/exports/hooks/sequence.js +9 -6
  37. package/src/exports/index.js +52 -29
  38. package/src/exports/internal/client.js +5 -0
  39. package/src/exports/internal/env.js +8 -5
  40. package/src/exports/internal/index.js +1 -90
  41. package/src/exports/internal/{event.js → server/event.js} +2 -3
  42. package/src/exports/internal/server/index.js +37 -0
  43. package/src/exports/internal/server/telemetry.js +95 -0
  44. package/src/exports/internal/shared.js +90 -0
  45. package/src/exports/node/index.js +64 -22
  46. package/src/exports/params/index.js +70 -0
  47. package/src/exports/params/public.d.ts +63 -0
  48. package/src/exports/public.d.ts +50 -1733
  49. package/src/exports/remote/index.js +11 -0
  50. package/src/exports/remote/public.d.ts +519 -0
  51. package/src/exports/url.js +86 -0
  52. package/src/exports/vite/build/build_server.js +54 -65
  53. package/src/exports/vite/build/remote.js +24 -19
  54. package/src/exports/vite/build/utils.js +0 -8
  55. package/src/exports/vite/dev/index.js +218 -146
  56. package/src/exports/vite/index.js +1590 -858
  57. package/src/exports/vite/module_ids.js +2 -2
  58. package/src/exports/vite/preview/index.js +40 -32
  59. package/src/exports/vite/public.d.ts +588 -0
  60. package/src/exports/vite/utils.js +84 -46
  61. package/src/pathname.js +55 -0
  62. package/src/runner.js +15 -0
  63. package/src/runtime/app/env/internal.js +4 -4
  64. package/src/runtime/app/env/types.d.ts +1 -1
  65. package/src/runtime/app/environment/index.js +3 -3
  66. package/src/runtime/app/{forms.js → forms/index.js} +73 -42
  67. package/src/runtime/app/forms/public.d.ts +2 -0
  68. package/src/runtime/app/forms/types.d.ts +56 -0
  69. package/src/runtime/app/internal/transport.js +53 -0
  70. package/src/runtime/app/manifest/index.js +1 -0
  71. package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
  72. package/src/runtime/app/navigation/public.d.ts +237 -0
  73. package/src/runtime/app/paths/client.js +37 -37
  74. package/src/runtime/app/paths/index.js +1 -1
  75. package/src/runtime/app/paths/internal/client.js +34 -2
  76. package/src/runtime/app/paths/internal/server.js +6 -23
  77. package/src/runtime/app/paths/internal.d.ts +3 -0
  78. package/src/runtime/app/paths/public.d.ts +1 -29
  79. package/src/runtime/app/paths/server.js +36 -17
  80. package/src/runtime/app/paths/types.d.ts +11 -19
  81. package/src/runtime/app/server/index.js +2 -2
  82. package/src/runtime/app/server/public.d.ts +201 -0
  83. package/src/runtime/app/server/remote/command.js +13 -11
  84. package/src/runtime/app/server/remote/form.js +61 -39
  85. package/src/runtime/app/server/remote/prerender.js +45 -45
  86. package/src/runtime/app/server/remote/query.js +106 -108
  87. package/src/runtime/app/server/remote/requested.js +27 -19
  88. package/src/runtime/app/server/remote/shared.js +76 -76
  89. package/src/runtime/app/service-worker/index.js +24 -0
  90. package/src/runtime/app/state/client.js +4 -2
  91. package/src/runtime/app/state/index.js +7 -5
  92. package/src/runtime/app/state/public.d.ts +72 -0
  93. package/src/runtime/app/state/server.js +3 -0
  94. package/src/runtime/app/stores.js +15 -78
  95. package/src/runtime/client/bundle.js +1 -1
  96. package/src/runtime/client/client-entry.js +3 -0
  97. package/src/runtime/client/client.js +1336 -648
  98. package/src/runtime/client/constants.js +3 -6
  99. package/src/runtime/client/entry.js +24 -3
  100. package/src/runtime/client/fetcher.js +25 -25
  101. package/src/runtime/client/ndjson.js +1 -1
  102. package/src/runtime/client/parse.js +1 -1
  103. package/src/runtime/client/payload.js +17 -0
  104. package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
  105. package/src/runtime/client/remote-functions/command.svelte.js +37 -61
  106. package/src/runtime/client/remote-functions/form.svelte.js +267 -178
  107. package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
  108. package/src/runtime/client/remote-functions/query/index.js +10 -17
  109. package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
  110. package/src/runtime/client/remote-functions/query/proxy.js +5 -5
  111. package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
  112. package/src/runtime/client/remote-functions/query-live/index.js +1 -1
  113. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
  114. package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
  115. package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
  116. package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
  117. package/src/runtime/client/snapshots.js +147 -0
  118. package/src/runtime/client/state.svelte.js +94 -55
  119. package/src/runtime/client/stream.js +3 -2
  120. package/src/runtime/client/types.d.ts +13 -9
  121. package/src/runtime/client/utils.js +22 -110
  122. package/src/runtime/components/root.svelte +56 -0
  123. package/src/runtime/env/dynamic/private.js +7 -0
  124. package/src/runtime/env/dynamic/public.js +7 -0
  125. package/src/runtime/env/static/private.js +6 -0
  126. package/src/runtime/env/static/public.js +6 -0
  127. package/src/runtime/form-utils.js +172 -61
  128. package/src/runtime/pathname.js +20 -32
  129. package/src/runtime/props.svelte.js +72 -0
  130. package/src/runtime/server/constants.js +0 -3
  131. package/src/runtime/server/cookie.js +72 -55
  132. package/src/runtime/server/csrf.js +65 -0
  133. package/src/runtime/server/data/index.js +49 -53
  134. package/src/runtime/server/dev.js +22 -0
  135. package/src/runtime/server/endpoint.js +6 -7
  136. package/src/runtime/server/env_module.js +0 -5
  137. package/src/runtime/server/errors.js +160 -0
  138. package/src/runtime/server/fetch.js +32 -39
  139. package/src/runtime/server/index.js +90 -64
  140. package/src/runtime/server/internal.js +71 -0
  141. package/src/runtime/server/page/actions.js +85 -64
  142. package/src/runtime/server/page/crypto.js +2 -2
  143. package/src/runtime/server/page/csp.js +88 -104
  144. package/src/runtime/server/page/data_serializer.js +24 -25
  145. package/src/runtime/server/page/index.js +36 -53
  146. package/src/runtime/server/page/load_data.js +50 -57
  147. package/src/runtime/server/page/render.js +173 -239
  148. package/src/runtime/server/page/respond_with_error.js +17 -31
  149. package/src/runtime/server/page/serialize_data.js +2 -13
  150. package/src/runtime/server/page/server_routing.js +85 -26
  151. package/src/runtime/server/remote-functions.js +640 -0
  152. package/src/runtime/server/respond.js +190 -131
  153. package/src/runtime/server/sourcemaps.js +183 -0
  154. package/src/runtime/server/state.js +53 -0
  155. package/src/runtime/server/utils.js +13 -155
  156. package/src/runtime/shared.js +20 -40
  157. package/src/runtime/utils.js +3 -0
  158. package/src/types/ambient-private.d.ts +11 -1
  159. package/src/types/ambient.d.ts +87 -36
  160. package/src/types/global-private.d.ts +25 -25
  161. package/src/types/internal.d.ts +163 -157
  162. package/src/types/private.d.ts +41 -1
  163. package/src/utils/error.js +28 -4
  164. package/src/utils/escape.js +9 -25
  165. package/src/utils/features.js +1 -1
  166. package/src/utils/filesystem.js +1 -23
  167. package/src/utils/fork.js +7 -2
  168. package/src/utils/hash.js +21 -0
  169. package/src/utils/http.js +8 -7
  170. package/src/utils/import.js +9 -2
  171. package/src/utils/imports.js +83 -0
  172. package/src/utils/mime.js +9 -0
  173. package/src/utils/page_nodes.js +6 -7
  174. package/src/utils/params.js +67 -0
  175. package/src/utils/regex.js +9 -0
  176. package/src/utils/routing.js +145 -73
  177. package/src/utils/shared-iterator.js +5 -0
  178. package/src/utils/streaming.js +14 -4
  179. package/src/utils/url.js +33 -2
  180. package/src/version.js +1 -1
  181. package/types/index.d.ts +2616 -2433
  182. package/types/index.d.ts.map +120 -106
  183. package/src/core/sync/write_ambient.js +0 -18
  184. package/src/core/sync/write_root.js +0 -148
  185. package/src/core/sync/write_tsconfig.js +0 -250
  186. package/src/exports/internal/server.js +0 -22
  187. package/src/exports/node/polyfills.js +0 -30
  188. package/src/runtime/server/app.js +0 -9
  189. package/src/runtime/server/remote.js +0 -457
  190. package/src/runtime/shared-server.js +0 -7
  191. package/src/runtime/telemetry/otel.js +0 -21
  192. package/src/runtime/telemetry/record_span.js +0 -65
  193. package/src/types/synthetic/$lib.md +0 -5
  194. /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
  195. /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
@@ -1,8 +1,9 @@
1
+ /** @import { Component } from 'svelte'; */
1
2
  import * as devalue from 'devalue';
2
- import { readable, writable } from 'svelte/store';
3
3
  import { DEV } from 'esm-env';
4
4
  import { isRedirect, text } from '@sveltejs/kit';
5
- import * as paths from '$app/paths/internal/server';
5
+ import * as paths from '#app/paths';
6
+ import { relative } from '$app/paths/internal/server';
6
7
  import { hash } from '../../../utils/hash.js';
7
8
  import { serialize_data } from './serialize_data.js';
8
9
  import { s } from '../../../utils/misc.js';
@@ -11,26 +12,24 @@ import { uneval_action_response } from './actions.js';
11
12
  import { SVELTE_KIT_ASSETS } from '../../../constants.js';
12
13
  import { SCHEME } from '../../../utils/url.js';
13
14
  import { create_server_routing_response, generate_route_object } from './server_routing.js';
14
- import { add_resolution_suffix } from '../../pathname.js';
15
+ import {
16
+ add_data_suffix,
17
+ add_resolution_suffix,
18
+ route_id_resolution_pathname
19
+ } from '../../pathname.js';
15
20
  import { try_get_request_store, with_request_store } from '@sveltejs/kit/internal/server';
16
21
  import { text_encoder } from '../../utils.js';
17
- import {
18
- count_non_ssi_comments,
19
- create_replacer,
20
- get_global_name,
21
- handle_error_and_jsonify
22
- } from '../utils.js';
23
- import { create_remote_key } from '../../shared.js';
24
- import { get_status } from '../../../utils/error.js';
22
+ import { count_non_ssi_comments, get_global_name } from '../utils.js';
23
+ import { handle_error_and_jsonify } from '../errors.js';
25
24
  import * as env from '__sveltekit/env';
25
+ import { collect_remote_data } from '../remote-functions.js';
26
+ import Root from '../../components/root.svelte';
27
+ import { render } from 'svelte/server';
28
+ import { Props, RenderNode } from '../../props.svelte.js';
29
+ import { has_custom_transporters, uneval } from '#app/internal/transport';
26
30
 
27
31
  // TODO rename this function/module
28
32
 
29
- const updated = {
30
- ...readable(false),
31
- check: () => false
32
- };
33
-
34
33
  /**
35
34
  * Creates the HTML response.
36
35
  * @param {{
@@ -38,16 +37,15 @@ const updated = {
38
37
  * fetched: Array<import('./types.js').Fetched>;
39
38
  * options: import('types').SSROptions;
40
39
  * manifest: import('@sveltejs/kit').SSRManifest;
41
- * state: import('types').SSRState;
42
40
  * page_config: { ssr: boolean; csr: boolean };
43
41
  * status: number;
44
42
  * error: App.Error | null;
45
- * event: import('@sveltejs/kit').RequestEvent;
46
- * event_state: import('types').RequestState;
43
+ * event: import('$app/server').RequestEvent;
44
+ * state: import('types').RequestState;
47
45
  * resolve_opts: import('types').RequiredResolveOptions;
48
- * action_result?: import('@sveltejs/kit').ActionResult;
46
+ * action_result?: import('$app/forms').ActionResult;
49
47
  * data_serializer: import('./types.js').ServerDataSerializer;
50
- * error_components?: Array<import('types').SSRComponent | undefined>
48
+ * error_components?: Array<import('svelte').Component | undefined>
51
49
  * }} opts
52
50
  */
53
51
  export async function render_response({
@@ -55,20 +53,19 @@ export async function render_response({
55
53
  fetched,
56
54
  options,
57
55
  manifest,
58
- state,
59
56
  page_config,
60
57
  status,
61
58
  error = null,
62
59
  event,
63
- event_state,
60
+ state,
64
61
  resolve_opts,
65
62
  action_result,
66
63
  data_serializer,
67
64
  error_components
68
65
  }) {
69
- if (state.prerendering) {
66
+ if (state.prerendering || state.prerender_default === true) {
70
67
  if (options.csp.mode === 'nonce') {
71
- throw new Error('Cannot use prerendering if config.kit.csp.mode === "nonce"');
68
+ throw new Error('Cannot use prerendering if config.csp.mode === "nonce"');
72
69
  }
73
70
 
74
71
  if (options.app_template_contains_nonce) {
@@ -78,9 +75,9 @@ export async function render_response({
78
75
 
79
76
  const { client } = manifest._;
80
77
 
81
- const modulepreloads = new Set(client.imports);
82
- const stylesheets = new Set(client.stylesheets);
83
- const fonts = new Set(client.fonts);
78
+ const modulepreloads = new Set(client?.imports);
79
+ const stylesheets = new Set(client?.stylesheets);
80
+ const fonts = new Set(client?.fonts);
84
81
 
85
82
  /**
86
83
  * The value of the Link header that is added to the response when not prerendering
@@ -92,7 +89,8 @@ export async function render_response({
92
89
  // TODO if we add a client entry point one day, we will need to include inline_styles with the entry, otherwise stylesheets will be linked even if they are below inlineStyleThreshold
93
90
  const inline_styles = new Map();
94
91
 
95
- /** @type {ReturnType<typeof options.root.render>} */
92
+ // TODO `svelte/server` should expose `RenderOutput`
93
+ /** @type {{ head: string, body: string, hashes: { script: string[] } }} */
96
94
  let rendered;
97
95
 
98
96
  const form_value =
@@ -113,13 +111,18 @@ export async function render_response({
113
111
  let base_expression = s(paths.base);
114
112
 
115
113
  const csp = new Csp(options.csp, {
116
- prerender: !!state.prerendering
114
+ prerender: !!(state.prerendering || state.prerender_default === true)
117
115
  });
118
116
 
119
117
  // if appropriate, use relative paths for greater portability
120
- if (paths.relative) {
118
+ if (relative) {
121
119
  if (!state.prerendering?.fallback) {
122
- const segments = event.url.pathname.slice(paths.base.length).split('/').slice(2);
120
+ // the relative path depth must reflect the URL the browser is actually at, which
121
+ // for a data request includes the `__data.json` suffix that was stripped during routing
122
+ const pathname = event.isDataRequest
123
+ ? add_data_suffix(event.url.pathname)
124
+ : event.url.pathname;
125
+ const segments = pathname.slice(paths.base.length).split('/').slice(2);
123
126
 
124
127
  base = segments.map(() => '..').join('/') || '.';
125
128
 
@@ -136,52 +139,52 @@ export async function render_response({
136
139
  }
137
140
 
138
141
  if (page_config.ssr) {
139
- /** @type {Record<string, any>} */
140
- const props = {
141
- stores: {
142
- page: writable(null),
143
- navigating: writable(null),
144
- updated
145
- },
146
- constructors: await Promise.all(
147
- branch.map(({ node }) => {
148
- if (!node.component) {
149
- // Can only be the leaf, layouts have a fallback component generated
150
- throw new Error(`Missing +page.svelte component for route ${event.route.id}`);
151
- }
152
- return node.component();
153
- })
154
- ),
155
- form: form_value
156
- };
157
-
158
- if (error_components) {
159
- if (error) {
160
- props.error = error;
161
- }
162
- props.errors = error_components;
163
- }
164
-
165
- let data = {};
166
-
167
- // props_n (instead of props[n]) makes it easy to avoid
168
- // unnecessary updates for layout components
169
- for (let i = 0; i < branch.length; i += 1) {
170
- data = { ...data, ...branch[i].data };
171
- props[`data_${i}`] = data;
172
- }
173
-
174
- props.page = {
142
+ const page = {
175
143
  error,
176
144
  params: /** @type {Record<string, any>} */ (event.params),
177
145
  route: event.route,
178
146
  status,
179
147
  url: event.url,
180
- data,
148
+ data: {},
181
149
  form: form_value,
150
+ shallow: null,
182
151
  state: {}
183
152
  };
184
153
 
154
+ const props = new Props({
155
+ page,
156
+ tree: new RenderNode(
157
+ // TODO tidy up
158
+ /** @type {Component} */ (await branch[0].node.component?.()),
159
+ /** @type {Component} */ (error_components?.[1])
160
+ ),
161
+ form: form_value,
162
+ error: error ?? undefined
163
+ });
164
+
165
+ let current_node = props.tree;
166
+ let data = props.page.data;
167
+
168
+ for (let i = 0; i < branch.length; i += 1) {
169
+ const node = branch[i];
170
+
171
+ data = { ...data, ...node.data };
172
+
173
+ current_node.data = data;
174
+
175
+ if (i < branch.length - 1) {
176
+ current_node = current_node.child = new RenderNode(
177
+ // TODO tidy up
178
+ /** @type {Component} */ (await branch[i + 1].node.component?.()),
179
+ /** @type {Component} */ (error_components?.slice(0, i + 2).findLast((x) => x))
180
+ );
181
+ }
182
+ }
183
+
184
+ props.page.data = data;
185
+
186
+ const render_state = { ...state, is_in_render: true };
187
+
185
188
  const render_opts = {
186
189
  context: new Map([
187
190
  [
@@ -193,15 +196,28 @@ export async function render_response({
193
196
  ]),
194
197
  csp: csp.script_needs_nonce ? { nonce: csp.nonce } : { hash: csp.script_needs_hash },
195
198
  transformError: error_components
196
- ? /** @param {unknown} e */ async (e) => {
199
+ ? /** @param {unknown} e */ (e) => {
197
200
  if (isRedirect(e)) {
198
201
  throw e;
199
202
  }
200
203
 
201
- const transformed = await handle_error_and_jsonify(event, event_state, options, e);
202
- props.page.error = props.error = error = transformed;
203
- props.page.status = status = get_status(e);
204
- return transformed;
204
+ const handled = handle_error_and_jsonify(event, render_state, options, e);
205
+
206
+ // TODO 4.0 make this an async function and await `handled`
207
+ if (handled instanceof Promise) {
208
+ return handled.then((e) => {
209
+ error = e;
210
+ props.page.error = error;
211
+ props.page.status = status = error.status;
212
+ return error;
213
+ });
214
+ }
215
+
216
+ error = handled;
217
+ props.page.error = error;
218
+ props.page.status = status = error.status;
219
+
220
+ return error;
205
221
  }
206
222
  : undefined
207
223
  };
@@ -227,53 +243,27 @@ export async function render_response({
227
243
  };
228
244
  }
229
245
 
230
- const state = { ...event_state, is_in_render: true };
231
-
232
- rendered = await with_request_store({ event, state }, async () => {
233
- // use relative paths during rendering, so that the resulting HTML is as
234
- // portable as possible, but reset afterwards
235
- if (paths.relative) paths.override({ base, assets });
236
-
237
- const maybe_promise = options.root.render(props, render_opts);
246
+ rendered = await with_request_store({ event, state: render_state }, async () => {
238
247
  // We have to invoke .then eagerly here in order to kick off rendering: it's only starting on access,
239
248
  // and `await maybe_promise` would eagerly access the .then property but call its function only after a tick, which is too late
240
249
  // for the paths.reset() below and for any eager getRequestEvent() calls during rendering without AsyncLocalStorage available.
241
- const rendered =
242
- options.async && 'then' in maybe_promise
243
- ? /** @type {ReturnType<typeof options.root.render> & Promise<any>} */ (
244
- maybe_promise
245
- ).then((r) => r)
246
- : maybe_promise;
247
-
248
- // TODO 3.0 remove options.async
249
- if (options.async) {
250
- // we reset this synchronously, rather than after async rendering is complete,
251
- // to avoid cross-talk between requests. This is a breaking change for
252
- // anyone who opts into async SSR, since `base` and `assets` will no
253
- // longer be relative to the current pathname.
254
- // TODO 3.0 remove `base` and `assets` in favour of `resolve(...)` and `asset(...)`
255
- paths.reset();
256
- }
250
+ const rendered = render(Root, { ...render_opts, props });
257
251
 
258
- const { head, html, css, hashes } = /** @type {ReturnType<typeof options.root.render>} */ (
259
- options.async ? await rendered : rendered
260
- );
252
+ const { head, body, hashes } = await rendered;
261
253
 
262
254
  if (hashes) {
263
255
  csp.add_script_hashes(hashes.script);
264
256
  }
265
257
 
266
- return { head, html, css, hashes };
258
+ return { head, body, hashes };
267
259
  });
268
260
  } finally {
269
261
  if (DEV) {
270
262
  globalThis.fetch = fetch;
271
263
  }
272
-
273
- paths.reset(); // just in case `options.root.render(...)` failed
274
264
  }
275
265
  } else {
276
- rendered = { head: '', html: '', css: { code: '', map: null }, hashes: { script: [] } };
266
+ rendered = { head: '', body: '', hashes: { script: [] } };
277
267
  }
278
268
 
279
269
  for (const { node } of branch) {
@@ -281,7 +271,7 @@ export async function render_response({
281
271
  for (const url of node.stylesheets) stylesheets.add(url);
282
272
  for (const url of node.fonts) fonts.add(url);
283
273
 
284
- if (node.inline_styles && !client.inline) {
274
+ if (node.inline_styles && !client?.inline) {
285
275
  Object.entries(await node.inline_styles()).forEach(([filename, css]) => {
286
276
  if (typeof css === 'string') {
287
277
  inline_styles.set(filename, css);
@@ -294,7 +284,7 @@ export async function render_response({
294
284
  }
295
285
 
296
286
  const head = new Head(rendered.head);
297
- let body = rendered.html;
287
+ let body = rendered.body;
298
288
 
299
289
  /** @param {string} path */
300
290
  const prefixed = (path) => {
@@ -307,7 +297,7 @@ export async function render_response({
307
297
  return `${assets}/${path}`;
308
298
  };
309
299
 
310
- const style = client.inline
300
+ const style = client?.inline
311
301
  ? client.inline?.style
312
302
  : Array.from(inline_styles.values()).join('\n');
313
303
 
@@ -321,6 +311,19 @@ export async function render_response({
321
311
  head.add_style(style, attributes);
322
312
  }
323
313
 
314
+ /**
315
+ * see the `output.linkHeaderPreload` option for details on why we have multiple options here
316
+ * @param {string} path
317
+ * @param {string[]} attributes
318
+ */
319
+ const add_preload = (path, attributes) => {
320
+ if (options.link_header_preload && !(state.prerendering || state.prerender_default === true)) {
321
+ link_headers.add(`<${encodeURI(path)}>; ${attributes.join('; ')}; nopush`);
322
+ } else {
323
+ head.add_link_tag(path, attributes);
324
+ }
325
+ };
326
+
324
327
  for (const dep of stylesheets) {
325
328
  const path = prefixed(dep);
326
329
 
@@ -345,18 +348,7 @@ export async function render_response({
345
348
  if (resolve_opts.preload({ type: 'font', path })) {
346
349
  const ext = dep.slice(dep.lastIndexOf('.') + 1);
347
350
 
348
- if (options.link_header_preload && !state.prerendering) {
349
- link_headers.add(
350
- `<${encodeURI(path)}>; rel="preload"; as="font"; type="font/${ext}"; crossorigin; nopush`
351
- );
352
- } else {
353
- head.add_link_tag(path, [
354
- 'rel="preload"',
355
- 'as="font"',
356
- `type="font/${ext}"`,
357
- 'crossorigin'
358
- ]);
359
- }
351
+ add_preload(path, ['rel="preload"', 'as="font"', `type="font/${ext}"`, 'crossorigin']);
360
352
  }
361
353
  }
362
354
 
@@ -366,58 +358,66 @@ export async function render_response({
366
358
  if (page_config.ssr && page_config.csr) {
367
359
  body += `\n\t\t\t${fetched
368
360
  .map((item) =>
369
- serialize_data(item, resolve_opts.filterSerializedResponseHeaders, !!state.prerendering)
361
+ serialize_data(
362
+ item,
363
+ resolve_opts.filterSerializedResponseHeaders,
364
+ !!(state.prerendering || state.prerender_default === true)
365
+ )
370
366
  )
371
367
  .join('\n\t\t\t')}`;
372
368
  }
373
369
 
374
- if (page_config.csr) {
375
- const route = manifest._.client.routes?.find((r) => r.id === event.route.id) ?? null;
370
+ if (page_config.csr && client) {
371
+ const route = client.routes?.find((r) => r.id === event.route.id) ?? null;
372
+
373
+ // when serving a prerendered page in an app that uses runtime public env vars, we must
374
+ // import the env.js module so that it evaluates before any user code can evaluate.
375
+ // TODO revert to using top-level await once https://bugs.webkit.org/show_bug.cgi?id=242740 is fixed
376
+ // https://github.com/sveltejs/kit/pull/11601
377
+ const load_env_eagerly =
378
+ client.uses_env_dynamic_public && (state.prerendering || state.prerender_default === true);
376
379
 
377
- if (client.uses_env_dynamic_public && state.prerendering) {
380
+ if (load_env_eagerly) {
378
381
  modulepreloads.add(`${paths.app_dir}/env.js`);
379
382
  }
380
383
 
381
384
  if (!client.inline) {
382
- const included_modulepreloads = Array.from(modulepreloads, (dep) => prefixed(dep)).filter(
383
- (path) => resolve_opts.preload({ type: 'js', path })
384
- );
385
+ for (const dep of modulepreloads) {
386
+ const path = prefixed(dep);
385
387
 
386
- /** @type {(path: string) => void} */
387
- let add_preload;
388
-
389
- // see the kit.output.preloadStrategy option for details on why we have multiple options here
390
- if (options.link_header_preload && !state.prerendering) {
391
- add_preload = (path) =>
392
- link_headers.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
393
- } else {
394
- add_preload = (path) => head.add_link_tag(path, ['rel="modulepreload"']);
395
- }
396
-
397
- for (const path of included_modulepreloads) {
398
- add_preload(path);
388
+ if (resolve_opts.preload({ type: 'js', path })) {
389
+ add_preload(path, ['rel="modulepreload"']);
390
+ }
399
391
  }
400
392
  }
401
393
 
402
394
  // prerender a `/path/to/page/__route.js` module
403
- if (manifest._.client.routes && state.prerendering && !state.prerendering.fallback) {
395
+ if (client.routes && state.prerendering && !state.prerendering.fallback) {
404
396
  const pathname = add_resolution_suffix(event.url.pathname);
405
397
 
406
398
  state.prerendering.dependencies.set(
407
399
  pathname,
408
- create_server_routing_response(route, event.params, new URL(pathname, event.url), manifest)
400
+ create_server_routing_response(route, event.params, new URL(pathname, event.url), client)
409
401
  );
402
+
403
+ // Prerender a route-ID-keyed `/_app/routes/<id>/__route.js` module alongside the
404
+ // pathname-keyed one above, so that `preloadCode(id)` can resolve a route ID without
405
+ // hitting the server.
406
+ if (route && !state.prerendering.resolved_route_ids.has(route.id)) {
407
+ state.prerendering.resolved_route_ids.add(route.id);
408
+
409
+ const id_pathname = paths.base + route_id_resolution_pathname(route.id);
410
+
411
+ state.prerendering.dependencies.set(
412
+ id_pathname,
413
+ create_server_routing_response(route, null, new URL(id_pathname, event.url), client)
414
+ );
415
+ }
410
416
  }
411
417
 
412
418
  const blocks = [];
413
419
 
414
- // when serving a prerendered page in an app that uses $app/env/public, we must
415
- // import the env.js module so that it evaluates before any user code can evaluate.
416
- // TODO revert to using top-level await once https://bugs.webkit.org/show_bug.cgi?id=242740 is fixed
417
- // https://github.com/sveltejs/kit/pull/11601
418
- const load_env_eagerly = client.uses_env_dynamic_public && state.prerendering; // TODO implement uses_env_dynamic_public
419
-
420
- const properties = [`base: ${base_expression}`];
420
+ const properties = [`base: ${base_expression}`, `version: ${s(__SVELTEKIT_APP_VERSION__)}`];
421
421
 
422
422
  if (paths.assets) {
423
423
  properties.push(`assets: ${s(paths.assets)}`);
@@ -436,11 +436,13 @@ export async function render_response({
436
436
 
437
437
  let app_declaration = '';
438
438
 
439
- if (Object.keys(options.hooks.transport).length > 0) {
439
+ if (has_custom_transporters) {
440
440
  if (client.inline) {
441
- app_declaration = `const app = __sveltekit_${options.version_hash}.app.app;`;
441
+ app_declaration = `const app = ${global}.app.app;`;
442
442
  } else if (client.app) {
443
- app_declaration = `const app = await import(${s(prefixed(client.app))});`;
443
+ app_declaration = `const kit = await import(${s(prefixed(client.start))});
444
+ kit.init(${global});
445
+ const app = await import(${s(prefixed(client.app))});`;
444
446
  } else {
445
447
  app_declaration = `const { app } = await import(${s(prefixed(client.start))});`;
446
448
  }
@@ -485,8 +487,7 @@ export async function render_response({
485
487
  if (form_value) {
486
488
  serialized.form = uneval_action_response(
487
489
  form_value,
488
- /** @type {string} */ (event.route.id),
489
- options.hooks.transport
490
+ /** @type {string} */ (event.route.id)
490
491
  );
491
492
  }
492
493
 
@@ -501,13 +502,13 @@ export async function render_response({
501
502
  `error: ${serialized.error}`
502
503
  ];
503
504
 
504
- if (status !== 200) {
505
+ if (status !== 200 && !error) {
505
506
  hydrate.push(`status: ${status}`);
506
507
  }
507
508
 
508
- if (manifest._.client.routes) {
509
+ if (client.routes) {
509
510
  if (route) {
510
- const stringified = generate_route_object(route, event.url, manifest).replaceAll(
511
+ const stringified = generate_route_object(route, event.url, client).replaceAll(
511
512
  '\n',
512
513
  '\n\t\t\t\t\t\t\t'
513
514
  ); // make output after it's put together with the rest more readable
@@ -521,87 +522,26 @@ export async function render_response({
521
522
  args.push(`{\n${indent}\t${hydrate.join(`,\n${indent}\t`)}\n${indent}}`);
522
523
  }
523
524
 
524
- const { remote } = event_state;
525
-
526
- let serialized_query_data = '';
527
- let serialized_prerender_data = '';
528
-
529
- if (remote.data) {
530
- /** @type {Record<string, any>} */
531
- const query = {};
532
-
533
- /** @type {Record<string, any>} */
534
- const prerender = {};
535
-
536
- for (const [internals, cache] of remote.data) {
537
- // remote functions without an `id` aren't exported, and thus
538
- // cannot be called from the client
539
- if (!internals.id) continue;
540
-
541
- for (const key in cache) {
542
- const entry = cache[key];
543
-
544
- if (!entry.serialize) continue;
545
-
546
- const remote_key = create_remote_key(internals.id, key);
547
-
548
- const store = internals.type === 'prerender' ? prerender : query;
549
-
550
- if (
551
- event_state.remote.refreshes?.has(remote_key) ||
552
- event_state.remote.reconnects?.has(remote_key)
553
- ) {
554
- // This entry was refreshed/set by a command or form action.
555
- // Always await it so the mutation result is serialized.
556
- store[remote_key] = await entry.data;
557
- } else {
558
- // Don't block the response on pending remote data - if a query
559
- // hasn't settled yet, it wasn't awaited in the template (or is behind a pending boundary).
560
- const result = await Promise.race([
561
- Promise.resolve(entry.data).then(
562
- (v) => /** @type {const} */ ({ settled: true, value: v }),
563
- (e) => /** @type {const} */ ({ settled: true, error: e })
564
- ),
565
- new Promise((resolve) => {
566
- queueMicrotask(() => resolve(/** @type {const} */ ({ settled: false })));
567
- })
568
- ]);
569
-
570
- if (result.settled) {
571
- if ('error' in result) throw result.error;
572
- store[remote_key] = result.value;
573
- }
574
- }
575
- }
576
- }
525
+ const remote_data = await collect_remote_data({}, event, state, options);
577
526
 
578
- const replacer = create_replacer(options.hooks.transport);
579
-
580
- if (Object.keys(query).length > 0) {
581
- serialized_query_data = `${global}.query = ${devalue.uneval(query, replacer)};\n\n\t\t\t\t\t\t`;
582
- }
583
-
584
- if (Object.keys(prerender).length > 0) {
585
- serialized_prerender_data = `${global}.prerender = ${devalue.uneval(prerender, replacer)};\n\n\t\t\t\t\t\t`;
586
- }
587
- }
588
-
589
- const serialized_remote_data = `${serialized_query_data}${serialized_prerender_data}`;
527
+ const serialized_data =
528
+ Object.keys(remote_data).length > 0
529
+ ? `${global}.data = ${uneval(remote_data)};\n\n\t\t\t\t\t\t`
530
+ : '';
590
531
 
591
532
  // `client.app` is a proxy for `bundleStrategy === 'split'`
592
533
  const boot = client.inline
593
534
  ? `${client.inline.script}
594
535
 
595
- ${serialized_remote_data}${global}.app.start(${args.join(', ')});`
536
+ ${serialized_data}${global}.app.start(${args.join(', ')});`
596
537
  : client.app
597
- ? `Promise.all([
598
- import(${s(prefixed(client.start))}),
599
- import(${s(prefixed(client.app))})
600
- ]).then(([kit, app]) => {
601
- ${serialized_remote_data}kit.start(app, ${args.join(', ')});
538
+ ? `import(${s(prefixed(client.start))}).then(async (kit) => {
539
+ kit.init(${global});
540
+ const app = await import(${s(prefixed(client.app))});
541
+ ${serialized_data}kit.start(app, ${args.join(', ')});
602
542
  });`
603
543
  : `import(${s(prefixed(client.start))}).then((app) => {
604
- ${serialized_remote_data}app.start(${args.join(', ')})
544
+ ${serialized_data}app.start(${args.join(', ')})
605
545
  });`;
606
546
 
607
547
  if (load_env_eagerly) {
@@ -615,12 +555,9 @@ export async function render_response({
615
555
  }
616
556
 
617
557
  if (options.service_worker) {
618
- let opts = __SVELTEKIT_DEV__ ? ", { type: 'module' }" : '';
558
+ let opts = ", { type: 'module' }";
619
559
  if (options.service_worker_options != null) {
620
- const service_worker_options = { ...options.service_worker_options };
621
- if (__SVELTEKIT_DEV__) {
622
- service_worker_options.type = 'module';
623
- }
560
+ const service_worker_options = { ...options.service_worker_options, type: 'module' };
624
561
  opts = `, ${s(service_worker_options)}`;
625
562
  }
626
563
 
@@ -639,11 +576,8 @@ export async function render_response({
639
576
  }`);
640
577
  }
641
578
 
642
- // we need to eagerly import the Vite client module in development to ensure
643
- // that Vite global constant replacements are initialised before our code runs
644
579
  const init_app = `
645
580
  {
646
- ${DEV ? `import('${paths.base}/@vite/client')` : ''}
647
581
  ${blocks.join('\n\n\t\t\t\t\t')}
648
582
  }
649
583
  `;
@@ -659,14 +593,14 @@ export async function render_response({
659
593
  'content-type': 'text/html'
660
594
  });
661
595
 
662
- if (state.prerendering) {
596
+ if (state.prerendering || state.prerender_default === true) {
663
597
  // TODO read headers set with setHeaders and convert into http-equiv where possible
664
598
  const csp_headers = csp.csp_provider.get_meta();
665
599
  if (csp_headers) {
666
600
  head.add_http_equiv(csp_headers);
667
601
  }
668
602
 
669
- if (state.prerendering.cache) {
603
+ if (state.prerendering?.cache) {
670
604
  head.add_http_equiv(
671
605
  `<meta http-equiv="cache-control" content="${state.prerendering.cache}">`
672
606
  );