@sveltejs/kit 2.63.1 → 2.65.0
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/package.json +2 -2
- package/src/core/postbuild/analyse.js +0 -5
- package/src/core/postbuild/prerender.js +2 -0
- package/src/exports/public.d.ts +1 -1
- package/src/exports/vite/build/build_server.js +47 -57
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/index.js +226 -178
- package/src/runtime/app/server/remote/command.js +0 -3
- package/src/runtime/app/server/remote/form.js +18 -13
- package/src/runtime/app/server/remote/prerender.js +28 -34
- package/src/runtime/app/server/remote/query.js +105 -94
- package/src/runtime/app/server/remote/requested.js +14 -10
- package/src/runtime/app/server/remote/shared.js +25 -18
- package/src/runtime/client/client.js +19 -13
- package/src/runtime/client/remote-functions/command.svelte.js +7 -32
- package/src/runtime/client/remote-functions/form.svelte.js +62 -82
- package/src/runtime/client/remote-functions/prerender.svelte.js +14 -6
- package/src/runtime/client/remote-functions/query/index.js +6 -14
- package/src/runtime/client/remote-functions/query/instance.svelte.js +20 -0
- package/src/runtime/client/remote-functions/query/proxy.js +3 -3
- package/src/runtime/client/remote-functions/query-batch.svelte.js +59 -68
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +20 -6
- package/src/runtime/client/remote-functions/shared.svelte.js +76 -59
- package/src/runtime/server/page/render.js +20 -80
- package/src/runtime/server/page/server_routing.js +20 -15
- package/src/runtime/server/remote.js +296 -204
- package/src/runtime/server/respond.js +4 -2
- package/src/runtime/shared.js +83 -28
- package/src/types/global-private.d.ts +3 -3
- package/src/types/internal.d.ts +53 -34
- package/src/version.js +1 -1
- package/types/index.d.ts +4 -4
- package/types/index.d.ts.map +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/** @import { RemoteFunctionResponse,
|
|
1
|
+
/** @import { RemoteFunctionResponse, RemoteFunctionData, RemoteFunctionDataNode } from 'types' */
|
|
2
2
|
/** @import { RemoteQueryUpdate } from '@sveltejs/kit' */
|
|
3
|
+
/** @import { CacheEntry } from './cache.svelte.js' */
|
|
3
4
|
import * as devalue from 'devalue';
|
|
4
|
-
import { app, goto, live_query_map, query_map } from '../client.js';
|
|
5
|
+
import { app, goto, live_query_map, query_map, query_responses } from '../client.js';
|
|
5
6
|
import { HttpError, Redirect } from '@sveltejs/kit/internal';
|
|
6
7
|
import { untrack } from 'svelte';
|
|
7
8
|
import { create_remote_key, split_remote_key } from '../../shared.js';
|
|
@@ -77,6 +78,20 @@ export function pin_while_resolving(cache_map, cache, id, payload, then) {
|
|
|
77
78
|
/**
|
|
78
79
|
* @returns {{ 'x-sveltekit-pathname': string, 'x-sveltekit-search': string }}
|
|
79
80
|
*/
|
|
81
|
+
/**
|
|
82
|
+
* Unwraps a `RemoteFunctionDataNode` that was serialized during SSR,
|
|
83
|
+
* rethrowing serialized errors so the consuming resource ends up
|
|
84
|
+
* in the same failed state it had on the server
|
|
85
|
+
* @param {RemoteFunctionDataNode} node
|
|
86
|
+
*/
|
|
87
|
+
export function unwrap_node(node) {
|
|
88
|
+
if (node.e) {
|
|
89
|
+
throw new HttpError(node.e[0] ?? 500, node.e[1]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return node.v;
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
export function get_remote_request_headers() {
|
|
81
96
|
// This will be the correct value of the current or soon-current url,
|
|
82
97
|
// even in forks because it's state-based - therefore not using window.location.
|
|
@@ -93,15 +108,10 @@ export function get_remote_request_headers() {
|
|
|
93
108
|
|
|
94
109
|
/**
|
|
95
110
|
* @param {string} url
|
|
96
|
-
* @param {
|
|
111
|
+
* @param {RequestInit} [init]
|
|
97
112
|
*/
|
|
98
|
-
export async function remote_request(url,
|
|
99
|
-
const response = await fetch(url,
|
|
100
|
-
headers: {
|
|
101
|
-
'Content-Type': 'application/json',
|
|
102
|
-
...headers
|
|
103
|
-
}
|
|
104
|
-
});
|
|
113
|
+
export async function remote_request(url, init) {
|
|
114
|
+
const response = await fetch(url, init);
|
|
105
115
|
|
|
106
116
|
if (!response.ok) {
|
|
107
117
|
throw new HttpError(500, 'Failed to execute remote function');
|
|
@@ -109,9 +119,63 @@ export async function remote_request(url, headers) {
|
|
|
109
119
|
|
|
110
120
|
const result = /** @type {RemoteFunctionResponse} */ (await response.json());
|
|
111
121
|
|
|
112
|
-
|
|
122
|
+
if (result.type === 'error') {
|
|
123
|
+
throw new HttpError(result.status ?? 500, result.error);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const data = /** @type {RemoteFunctionData} */ (
|
|
127
|
+
result.data ? devalue.parse(result.data, app.decoders) : {}
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
* @param {string} key
|
|
133
|
+
* @param {CacheEntry<any> | undefined} entry
|
|
134
|
+
* @param {any} result
|
|
135
|
+
*/
|
|
136
|
+
function refresh(key, entry, result) {
|
|
137
|
+
if (entry?.resource) {
|
|
138
|
+
if (result.e) {
|
|
139
|
+
entry.resource.fail(new HttpError(result.e[0] ?? 500, result.e[1]));
|
|
140
|
+
} else {
|
|
141
|
+
entry.resource.set(result.v);
|
|
142
|
+
}
|
|
143
|
+
} else if (!result.e) {
|
|
144
|
+
// `query_responses` stores `{ v }`/`{ e }` nodes, not raw values.
|
|
145
|
+
// Errors are deliberately dropped here: they are responses to a specific
|
|
146
|
+
// refresh, not durable state a future resource should initialize with
|
|
147
|
+
query_responses[key] = result;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// update queries with refreshed data
|
|
152
|
+
if (data.q) {
|
|
153
|
+
for (const key in data.q) {
|
|
154
|
+
const parts = split_remote_key(key);
|
|
155
|
+
const entry = query_map.get(parts.id)?.get(parts.payload);
|
|
156
|
+
|
|
157
|
+
refresh(key, entry, data.q[key]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// reconnect live queries
|
|
162
|
+
if (data.l) {
|
|
163
|
+
for (const key in data.l) {
|
|
164
|
+
const parts = split_remote_key(key);
|
|
165
|
+
const entry = live_query_map.get(parts.id)?.get(parts.payload);
|
|
166
|
+
|
|
167
|
+
refresh(key, entry, data.l[key]);
|
|
113
168
|
|
|
114
|
-
|
|
169
|
+
// `fail()` is terminal, so only reconnect on the success path —
|
|
170
|
+
// reconnecting after a hard failure would wipe the error state and
|
|
171
|
+
// restart the stream (see commit 63a3e83 regression).
|
|
172
|
+
if (!data.l[key].e) {
|
|
173
|
+
void entry?.resource.reconnect();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return data;
|
|
115
179
|
}
|
|
116
180
|
|
|
117
181
|
/**
|
|
@@ -206,50 +270,3 @@ export function categorize_updates(updates) {
|
|
|
206
270
|
|
|
207
271
|
return { overrides, refreshes };
|
|
208
272
|
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* @template TResource
|
|
212
|
-
* @param {string} stringified_singleflight
|
|
213
|
-
* @param {Map<string, Map<string, { resource: TResource }>>} map
|
|
214
|
-
* @param {(resource: TResource, value: RemoteSingleflightEntry) => void} callback
|
|
215
|
-
*/
|
|
216
|
-
function apply_singleflight(stringified_singleflight, map, callback) {
|
|
217
|
-
const singleflight = /** @type {RemoteSingleflightMap} */ (
|
|
218
|
-
devalue.parse(stringified_singleflight, app.decoders)
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
for (const [key, value] of Object.entries(singleflight)) {
|
|
222
|
-
const parts = split_remote_key(key);
|
|
223
|
-
const entry = map.get(parts.id)?.get(parts.payload);
|
|
224
|
-
if (entry?.resource) {
|
|
225
|
-
callback(entry.resource, value);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Apply refresh data from the server to the relevant queries
|
|
232
|
-
*
|
|
233
|
-
* @param {string} stringified_refreshes
|
|
234
|
-
*/
|
|
235
|
-
export const apply_refreshes = (stringified_refreshes) => {
|
|
236
|
-
apply_singleflight(stringified_refreshes, query_map, (resource, value) => {
|
|
237
|
-
if (value.type === 'result') {
|
|
238
|
-
resource?.set(value.data);
|
|
239
|
-
} else {
|
|
240
|
-
resource?.fail(new HttpError(value.status ?? 500, value.error));
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
};
|
|
244
|
-
|
|
245
|
-
/** @param {string} stringified_reconnects */
|
|
246
|
-
export const apply_reconnections = (stringified_reconnects) => {
|
|
247
|
-
apply_singleflight(stringified_reconnects, live_query_map, (resource, value) => {
|
|
248
|
-
if (value.type === 'result') {
|
|
249
|
-
resource?.set(value.data);
|
|
250
|
-
void resource?.reconnect();
|
|
251
|
-
} else {
|
|
252
|
-
resource?.fail(new HttpError(value.status ?? 500, value.error));
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
};
|
|
@@ -21,9 +21,9 @@ import {
|
|
|
21
21
|
get_global_name,
|
|
22
22
|
handle_error_and_jsonify
|
|
23
23
|
} from '../utils.js';
|
|
24
|
-
import { create_remote_key } from '../../shared.js';
|
|
25
24
|
import { get_status } from '../../../utils/error.js';
|
|
26
25
|
import * as env from '__sveltekit/env';
|
|
26
|
+
import { collect_remote_data } from '../remote.js';
|
|
27
27
|
|
|
28
28
|
// TODO rename this function/module
|
|
29
29
|
|
|
@@ -79,9 +79,9 @@ export async function render_response({
|
|
|
79
79
|
|
|
80
80
|
const { client } = manifest._;
|
|
81
81
|
|
|
82
|
-
const modulepreloads = new Set(client
|
|
83
|
-
const stylesheets = new Set(client
|
|
84
|
-
const fonts = new Set(client
|
|
82
|
+
const modulepreloads = new Set(client?.imports);
|
|
83
|
+
const stylesheets = new Set(client?.stylesheets);
|
|
84
|
+
const fonts = new Set(client?.fonts);
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* The value of the Link header that is added to the response when not prerendering
|
|
@@ -282,7 +282,7 @@ export async function render_response({
|
|
|
282
282
|
for (const url of node.stylesheets) stylesheets.add(url);
|
|
283
283
|
for (const url of node.fonts) fonts.add(url);
|
|
284
284
|
|
|
285
|
-
if (node.inline_styles && !client
|
|
285
|
+
if (node.inline_styles && !client?.inline) {
|
|
286
286
|
Object.entries(await node.inline_styles()).forEach(([filename, css]) => {
|
|
287
287
|
if (typeof css === 'string') {
|
|
288
288
|
inline_styles.set(filename, css);
|
|
@@ -308,7 +308,7 @@ export async function render_response({
|
|
|
308
308
|
return `${assets}/${path}`;
|
|
309
309
|
};
|
|
310
310
|
|
|
311
|
-
const style = client
|
|
311
|
+
const style = client?.inline
|
|
312
312
|
? client.inline?.style
|
|
313
313
|
: Array.from(inline_styles.values()).join('\n');
|
|
314
314
|
|
|
@@ -365,8 +365,8 @@ export async function render_response({
|
|
|
365
365
|
.join('\n\t\t\t')}`;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
if (page_config.csr) {
|
|
369
|
-
const route =
|
|
368
|
+
if (page_config.csr && client) {
|
|
369
|
+
const route = client.routes?.find((r) => r.id === event.route.id) ?? null;
|
|
370
370
|
|
|
371
371
|
if (client.uses_env_dynamic_public && state.prerendering) {
|
|
372
372
|
modulepreloads.add(`${paths.app_dir}/env.js`);
|
|
@@ -390,12 +390,12 @@ export async function render_response({
|
|
|
390
390
|
}
|
|
391
391
|
|
|
392
392
|
// prerender a `/path/to/page/__route.js` module
|
|
393
|
-
if (
|
|
393
|
+
if (client.routes && state.prerendering && !state.prerendering.fallback) {
|
|
394
394
|
const pathname = add_resolution_suffix(event.url.pathname);
|
|
395
395
|
|
|
396
396
|
state.prerendering.dependencies.set(
|
|
397
397
|
pathname,
|
|
398
|
-
create_server_routing_response(route, event.params, new URL(pathname, event.url),
|
|
398
|
+
create_server_routing_response(route, event.params, new URL(pathname, event.url), client)
|
|
399
399
|
);
|
|
400
400
|
}
|
|
401
401
|
|
|
@@ -500,9 +500,9 @@ export async function render_response({
|
|
|
500
500
|
hydrate.push(`status: ${status}`);
|
|
501
501
|
}
|
|
502
502
|
|
|
503
|
-
if (
|
|
503
|
+
if (client.routes) {
|
|
504
504
|
if (route) {
|
|
505
|
-
const stringified = generate_route_object(route, event.url,
|
|
505
|
+
const stringified = generate_route_object(route, event.url, client).replaceAll(
|
|
506
506
|
'\n',
|
|
507
507
|
'\n\t\t\t\t\t\t\t'
|
|
508
508
|
); // make output after it's put together with the rest more readable
|
|
@@ -516,87 +516,27 @@ export async function render_response({
|
|
|
516
516
|
args.push(`{\n${indent}\t${hydrate.join(`,\n${indent}\t`)}\n${indent}}`);
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
let serialized_query_data = '';
|
|
522
|
-
let serialized_prerender_data = '';
|
|
523
|
-
|
|
524
|
-
if (remote.data) {
|
|
525
|
-
/** @type {Record<string, any>} */
|
|
526
|
-
const query = {};
|
|
527
|
-
|
|
528
|
-
/** @type {Record<string, any>} */
|
|
529
|
-
const prerender = {};
|
|
530
|
-
|
|
531
|
-
for (const [internals, cache] of remote.data) {
|
|
532
|
-
// remote functions without an `id` aren't exported, and thus
|
|
533
|
-
// cannot be called from the client
|
|
534
|
-
if (!internals.id) continue;
|
|
535
|
-
|
|
536
|
-
for (const key in cache) {
|
|
537
|
-
const entry = cache[key];
|
|
538
|
-
|
|
539
|
-
if (!entry.serialize) continue;
|
|
540
|
-
|
|
541
|
-
const remote_key = create_remote_key(internals.id, key);
|
|
542
|
-
|
|
543
|
-
const store = internals.type === 'prerender' ? prerender : query;
|
|
544
|
-
|
|
545
|
-
if (
|
|
546
|
-
event_state.remote.refreshes?.has(remote_key) ||
|
|
547
|
-
event_state.remote.reconnects?.has(remote_key)
|
|
548
|
-
) {
|
|
549
|
-
// This entry was refreshed/set by a command or form action.
|
|
550
|
-
// Always await it so the mutation result is serialized.
|
|
551
|
-
store[remote_key] = await entry.data;
|
|
552
|
-
} else {
|
|
553
|
-
// Don't block the response on pending remote data - if a query
|
|
554
|
-
// hasn't settled yet, it wasn't awaited in the template (or is behind a pending boundary).
|
|
555
|
-
const result = await Promise.race([
|
|
556
|
-
Promise.resolve(entry.data).then(
|
|
557
|
-
(v) => /** @type {const} */ ({ settled: true, value: v }),
|
|
558
|
-
(e) => /** @type {const} */ ({ settled: true, error: e })
|
|
559
|
-
),
|
|
560
|
-
new Promise((resolve) => {
|
|
561
|
-
queueMicrotask(() => resolve(/** @type {const} */ ({ settled: false })));
|
|
562
|
-
})
|
|
563
|
-
]);
|
|
564
|
-
|
|
565
|
-
if (result.settled) {
|
|
566
|
-
if ('error' in result) throw result.error;
|
|
567
|
-
store[remote_key] = result.value;
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
const replacer = create_replacer(options.hooks.transport);
|
|
574
|
-
|
|
575
|
-
if (Object.keys(query).length > 0) {
|
|
576
|
-
serialized_query_data = `${global}.query = ${devalue.uneval(query, replacer)};\n\n\t\t\t\t\t\t`;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (Object.keys(prerender).length > 0) {
|
|
580
|
-
serialized_prerender_data = `${global}.prerender = ${devalue.uneval(prerender, replacer)};\n\n\t\t\t\t\t\t`;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
519
|
+
const remote_data = await collect_remote_data({}, event, event_state, options);
|
|
583
520
|
|
|
584
|
-
const
|
|
521
|
+
const serialized_data =
|
|
522
|
+
Object.keys(remote_data).length > 0
|
|
523
|
+
? `${global}.data = ${devalue.uneval(remote_data, create_replacer(options.hooks.transport))};\n\n\t\t\t\t\t\t`
|
|
524
|
+
: '';
|
|
585
525
|
|
|
586
526
|
// `client.app` is a proxy for `bundleStrategy === 'split'`
|
|
587
527
|
const boot = client.inline
|
|
588
528
|
? `${client.inline.script}
|
|
589
529
|
|
|
590
|
-
${
|
|
530
|
+
${serialized_data}${global}.app.start(${args.join(', ')});`
|
|
591
531
|
: client.app
|
|
592
532
|
? `Promise.all([
|
|
593
533
|
import(${s(prefixed(client.start))}),
|
|
594
534
|
import(${s(prefixed(client.app))})
|
|
595
535
|
]).then(([kit, app]) => {
|
|
596
|
-
${
|
|
536
|
+
${serialized_data}kit.start(app, ${args.join(', ')});
|
|
597
537
|
});`
|
|
598
538
|
: `import(${s(prefixed(client.start))}).then((app) => {
|
|
599
|
-
${
|
|
539
|
+
${serialized_data}app.start(${args.join(', ')})
|
|
600
540
|
});`;
|
|
601
541
|
|
|
602
542
|
if (load_env_eagerly) {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @import { SSRManifest } from '@sveltejs/kit' */
|
|
1
2
|
import { base, assets, relative } from '$app/paths/internal/server';
|
|
2
3
|
import { text } from '@sveltejs/kit';
|
|
3
4
|
import { s } from '../../../utils/misc.js';
|
|
@@ -7,15 +8,15 @@ import { get_relative_path } from '../../utils.js';
|
|
|
7
8
|
/**
|
|
8
9
|
* @param {import('types').SSRClientRoute} route
|
|
9
10
|
* @param {URL} url
|
|
10
|
-
* @param {
|
|
11
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
11
12
|
* @returns {string}
|
|
12
13
|
*/
|
|
13
|
-
export function generate_route_object(route, url,
|
|
14
|
+
export function generate_route_object(route, url, client) {
|
|
14
15
|
const { errors, layouts, leaf } = route;
|
|
15
16
|
|
|
16
17
|
const nodes = [...errors, ...layouts.map((l) => l?.[1]), leaf[1]]
|
|
17
18
|
.filter((n) => typeof n === 'number')
|
|
18
|
-
.map((n) => `'${n}': () => ${create_client_import(
|
|
19
|
+
.map((n) => `'${n}': () => ${create_client_import(client.nodes?.[n], url)}`)
|
|
19
20
|
.join(',\n\t\t');
|
|
20
21
|
|
|
21
22
|
// stringified version of
|
|
@@ -60,36 +61,40 @@ function create_client_import(import_path, url) {
|
|
|
60
61
|
/**
|
|
61
62
|
* @param {string} resolved_path
|
|
62
63
|
* @param {URL} url
|
|
63
|
-
* @param {
|
|
64
|
+
* @param {SSRManifest} manifest
|
|
64
65
|
* @returns {Promise<Response>}
|
|
65
66
|
*/
|
|
66
67
|
export async function resolve_route(resolved_path, url, manifest) {
|
|
67
|
-
if (!manifest._.client
|
|
68
|
+
if (!manifest._.client?.routes) {
|
|
68
69
|
return text('Server-side route resolution disabled', { status: 400 });
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
const matchers = await manifest._.matchers();
|
|
72
73
|
const result = find_route(resolved_path, manifest._.client.routes, matchers);
|
|
73
74
|
|
|
74
|
-
return create_server_routing_response(
|
|
75
|
-
|
|
75
|
+
return create_server_routing_response(
|
|
76
|
+
result?.route ?? null,
|
|
77
|
+
result?.params ?? {},
|
|
78
|
+
url,
|
|
79
|
+
manifest._.client
|
|
80
|
+
).response;
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
/**
|
|
79
84
|
* @param {import('types').SSRClientRoute | null} route
|
|
80
85
|
* @param {Partial<Record<string, string>>} params
|
|
81
86
|
* @param {URL} url
|
|
82
|
-
* @param {
|
|
87
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
83
88
|
* @returns {{response: Response, body: string}}
|
|
84
89
|
*/
|
|
85
|
-
export function create_server_routing_response(route, params, url,
|
|
90
|
+
export function create_server_routing_response(route, params, url, client) {
|
|
86
91
|
const headers = new Headers({
|
|
87
92
|
'content-type': 'application/javascript; charset=utf-8'
|
|
88
93
|
});
|
|
89
94
|
|
|
90
95
|
if (route) {
|
|
91
|
-
const csr_route = generate_route_object(route, url,
|
|
92
|
-
const body = `${create_css_import(route, url,
|
|
96
|
+
const csr_route = generate_route_object(route, url, client);
|
|
97
|
+
const body = `${create_css_import(route, url, client)}\nexport const route = ${csr_route}; export const params = ${JSON.stringify(params)};`;
|
|
93
98
|
|
|
94
99
|
return { response: text(body, { headers }), body };
|
|
95
100
|
} else {
|
|
@@ -105,17 +110,17 @@ export function create_server_routing_response(route, params, url, manifest) {
|
|
|
105
110
|
*
|
|
106
111
|
* @param {import('types').SSRClientRoute} route
|
|
107
112
|
* @param {URL} url
|
|
108
|
-
* @param {
|
|
113
|
+
* @param {NonNullable<SSRManifest['_']['client']>} client
|
|
109
114
|
* @returns {string}
|
|
110
115
|
*/
|
|
111
|
-
function create_css_import(route, url,
|
|
116
|
+
function create_css_import(route, url, client) {
|
|
112
117
|
const { errors, layouts, leaf } = route;
|
|
113
118
|
|
|
114
119
|
let css = '';
|
|
115
120
|
|
|
116
121
|
for (const node of [...errors, ...layouts.map((l) => l?.[1]), leaf[1]]) {
|
|
117
122
|
if (typeof node !== 'number') continue;
|
|
118
|
-
const node_css =
|
|
123
|
+
const node_css = client.css?.[node];
|
|
119
124
|
for (const css_path of node_css ?? []) {
|
|
120
125
|
css += `'${assets || base}/${css_path}',`;
|
|
121
126
|
}
|
|
@@ -123,5 +128,5 @@ function create_css_import(route, url, manifest) {
|
|
|
123
128
|
|
|
124
129
|
if (!css) return '';
|
|
125
130
|
|
|
126
|
-
return `${create_client_import(
|
|
131
|
+
return `${create_client_import(client.start, url)}.then(x => x.load_css([${css}]));`;
|
|
127
132
|
}
|