@sveltejs/kit 1.8.3 → 1.8.5
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 +3 -3
- package/postinstall.js +2 -2
- package/src/core/adapt/builder.js +1 -1
- package/src/core/config/options.js +4 -0
- package/src/core/sync/write_server.js +1 -0
- package/src/exports/vite/index.js +5 -6
- package/src/runtime/server/data/index.js +0 -2
- package/src/runtime/server/endpoint.js +2 -5
- package/src/runtime/server/fetch.js +4 -1
- package/src/runtime/server/index.js +5 -1
- package/src/runtime/server/page/index.js +9 -7
- package/src/runtime/server/page/render.js +6 -5
- package/src/runtime/server/page/respond_with_error.js +2 -7
- package/src/runtime/server/respond.js +13 -15
- package/src/runtime/server/utils.js +0 -5
- package/types/index.d.ts +14 -0
- package/types/internal.d.ts +9 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.5",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/sveltejs/kit",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"devalue": "^4.3.0",
|
|
17
17
|
"esm-env": "^1.0.0",
|
|
18
18
|
"kleur": "^4.1.5",
|
|
19
|
-
"magic-string": "^0.
|
|
19
|
+
"magic-string": "^0.30.0",
|
|
20
20
|
"mime": "^3.0.0",
|
|
21
21
|
"sade": "^1.8.1",
|
|
22
22
|
"set-cookie-parser": "^2.5.1",
|
|
@@ -80,7 +80,7 @@
|
|
|
80
80
|
"node": "^16.14 || >=18"
|
|
81
81
|
},
|
|
82
82
|
"scripts": {
|
|
83
|
-
"lint": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore
|
|
83
|
+
"lint": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
|
|
84
84
|
"check": "tsc",
|
|
85
85
|
"check:all": "tsc && pnpm -r --filter=\"./**\" check",
|
|
86
86
|
"format": "prettier --write . --config ../../.prettierrc --ignore-path .gitignore",
|
package/postinstall.js
CHANGED
|
@@ -138,6 +138,10 @@ const options = object(
|
|
|
138
138
|
|
|
139
139
|
outDir: string('.svelte-kit'),
|
|
140
140
|
|
|
141
|
+
output: object({
|
|
142
|
+
preloadStrategy: list(['modulepreload', 'preload-js', 'preload-mjs'], 'modulepreload')
|
|
143
|
+
}),
|
|
144
|
+
|
|
141
145
|
paths: object({
|
|
142
146
|
base: validate('', (input, keypath) => {
|
|
143
147
|
assert_string(input, keypath);
|
|
@@ -36,6 +36,7 @@ export const options = {
|
|
|
36
36
|
embedded: ${config.kit.embedded},
|
|
37
37
|
env_public_prefix: '${config.kit.env.publicPrefix}',
|
|
38
38
|
hooks: null, // added lazily, via \`get_hooks\`
|
|
39
|
+
preload_strategy: ${s(config.kit.output.preloadStrategy)},
|
|
39
40
|
root,
|
|
40
41
|
service_worker: ${has_service_worker},
|
|
41
42
|
templates: {
|
|
@@ -507,6 +507,9 @@ export function set_building() {
|
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
|
|
510
|
+
// see the kit.output.preloadStrategy option for details on why we have multiple options here
|
|
511
|
+
const ext = kit.output.preloadStrategy === 'preload-mjs' ? 'mjs' : 'js';
|
|
512
|
+
|
|
510
513
|
new_config = {
|
|
511
514
|
base: ssr ? assets_base(kit) : './',
|
|
512
515
|
build: {
|
|
@@ -516,12 +519,8 @@ export function set_building() {
|
|
|
516
519
|
input,
|
|
517
520
|
output: {
|
|
518
521
|
format: 'esm',
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
// rather than as a script, preventing a double parse. Ideally we'd just use
|
|
522
|
-
// modulepreload, but Safari prevents that
|
|
523
|
-
entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].mjs`,
|
|
524
|
-
chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name].[hash].mjs`,
|
|
522
|
+
entryFileNames: ssr ? '[name].js' : `${prefix}/[name].[hash].${ext}`,
|
|
523
|
+
chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name].[hash].${ext}`,
|
|
525
524
|
assetFileNames: `${prefix}/assets/[name].[hash][extname]`,
|
|
526
525
|
hoistTransitiveImports: false
|
|
527
526
|
},
|
|
@@ -4,12 +4,11 @@ import { method_not_allowed } from './utils.js';
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @param {import('types').RequestEvent} event
|
|
7
|
-
* @param {import('types').SSRRoute} route
|
|
8
7
|
* @param {import('types').SSREndpoint} mod
|
|
9
8
|
* @param {import('types').SSRState} state
|
|
10
9
|
* @returns {Promise<Response>}
|
|
11
10
|
*/
|
|
12
|
-
export async function render_endpoint(event,
|
|
11
|
+
export async function render_endpoint(event, mod, state) {
|
|
13
12
|
const method = /** @type {import('types').HttpMethod} */ (event.request.method);
|
|
14
13
|
|
|
15
14
|
let handler = mod[method];
|
|
@@ -29,7 +28,7 @@ export async function render_endpoint(event, route, mod, state) {
|
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
if (state.prerendering && !prerender) {
|
|
32
|
-
if (state.
|
|
31
|
+
if (state.depth > 0) {
|
|
33
32
|
// if request came from a prerendered page, bail
|
|
34
33
|
throw new Error(`${event.route.id} is not prerenderable`);
|
|
35
34
|
} else {
|
|
@@ -39,8 +38,6 @@ export async function render_endpoint(event, route, mod, state) {
|
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
state.initiator = route;
|
|
43
|
-
|
|
44
41
|
try {
|
|
45
42
|
const response = await handler(
|
|
46
43
|
/** @type {import('types').RequestEvent<Record<string, any>>} */ (event)
|
|
@@ -131,7 +131,10 @@ export function create_fetch({ event, options, manifest, state, get_cookie_heade
|
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
response = await respond(request, options, manifest,
|
|
134
|
+
response = await respond(request, options, manifest, {
|
|
135
|
+
...state,
|
|
136
|
+
depth: state.depth + 1
|
|
137
|
+
});
|
|
135
138
|
|
|
136
139
|
const set_cookie = response.headers.get('set-cookie');
|
|
137
140
|
if (set_cookie) {
|
|
@@ -16,9 +16,13 @@ import { respond_with_error } from './respond_with_error.js';
|
|
|
16
16
|
import { get_option } from '../../../utils/options.js';
|
|
17
17
|
import { get_data_json } from '../data/index.js';
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The maximum request depth permitted before assuming we're stuck in an infinite loop
|
|
21
|
+
*/
|
|
22
|
+
const MAX_DEPTH = 10;
|
|
23
|
+
|
|
19
24
|
/**
|
|
20
25
|
* @param {import('types').RequestEvent} event
|
|
21
|
-
* @param {import('types').SSRRoute} route
|
|
22
26
|
* @param {import('types').PageNodeIndexes} page
|
|
23
27
|
* @param {import('types').SSROptions} options
|
|
24
28
|
* @param {import('types').SSRManifest} manifest
|
|
@@ -26,16 +30,14 @@ import { get_data_json } from '../data/index.js';
|
|
|
26
30
|
* @param {import('types').RequiredResolveOptions} resolve_opts
|
|
27
31
|
* @returns {Promise<Response>}
|
|
28
32
|
*/
|
|
29
|
-
export async function render_page(event,
|
|
30
|
-
if (state.
|
|
33
|
+
export async function render_page(event, page, options, manifest, state, resolve_opts) {
|
|
34
|
+
if (state.depth > MAX_DEPTH) {
|
|
31
35
|
// infinite request cycle detected
|
|
32
36
|
return text(`Not found: ${event.url.pathname}`, {
|
|
33
|
-
status: 404
|
|
37
|
+
status: 404 // TODO in some cases this should be 500. not sure how to differentiate
|
|
34
38
|
});
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
state.initiator = route;
|
|
38
|
-
|
|
39
41
|
if (is_action_json_request(event)) {
|
|
40
42
|
const node = await manifest._.nodes[page.leaf]();
|
|
41
43
|
return handle_action_json_request(event, options, node?.server);
|
|
@@ -322,7 +324,7 @@ export async function render_page(event, route, page, options, manifest, state,
|
|
|
322
324
|
fetched
|
|
323
325
|
});
|
|
324
326
|
} catch (e) {
|
|
325
|
-
// if we end up here, it means the data loaded
|
|
327
|
+
// if we end up here, it means the data loaded successfully
|
|
326
328
|
// but the page failed to render, or that a prerendering error occurred
|
|
327
329
|
return await respond_with_error({
|
|
328
330
|
event,
|
|
@@ -273,12 +273,13 @@ export async function render_response({
|
|
|
273
273
|
);
|
|
274
274
|
|
|
275
275
|
for (const path of included_modulepreloads) {
|
|
276
|
-
//
|
|
277
|
-
// <link rel="preload"> for Safari. This results in the fastest loading in
|
|
278
|
-
// the most used browsers, with no double-loading. Note that we need to use
|
|
279
|
-
// .mjs extensions for `preload` to behave like `modulepreload` in Chrome
|
|
276
|
+
// see the kit.output.preloadStrategy option for details on why we have multiple options here
|
|
280
277
|
link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
|
|
281
|
-
|
|
278
|
+
if (options.preload_strategy !== 'modulepreload') {
|
|
279
|
+
head += `\n\t\t<link rel="preload" as="script" crossorigin="anonymous" href="${path}">`;
|
|
280
|
+
} else if (state.prerendering) {
|
|
281
|
+
head += `\n\t\t<link rel="modulepreload" href="${path}">`;
|
|
282
|
+
}
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
const blocks = [];
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { render_response } from './render.js';
|
|
2
2
|
import { load_data, load_server_data } from './load_data.js';
|
|
3
|
-
import {
|
|
4
|
-
handle_error_and_jsonify,
|
|
5
|
-
static_error_page,
|
|
6
|
-
redirect_response,
|
|
7
|
-
GENERIC_ERROR
|
|
8
|
-
} from '../utils.js';
|
|
3
|
+
import { handle_error_and_jsonify, static_error_page, redirect_response } from '../utils.js';
|
|
9
4
|
import { get_option } from '../../../utils/options.js';
|
|
10
5
|
import { HttpError, Redirect } from '../../control.js';
|
|
11
6
|
|
|
@@ -43,7 +38,7 @@ export async function respond_with_error({
|
|
|
43
38
|
const csr = get_option([default_layout], 'csr') ?? true;
|
|
44
39
|
|
|
45
40
|
if (ssr) {
|
|
46
|
-
state.
|
|
41
|
+
state.error = true;
|
|
47
42
|
|
|
48
43
|
const server_data_promise = load_server_data({
|
|
49
44
|
event,
|
|
@@ -5,7 +5,7 @@ import { render_page } from './page/index.js';
|
|
|
5
5
|
import { render_response } from './page/render.js';
|
|
6
6
|
import { respond_with_error } from './page/respond_with_error.js';
|
|
7
7
|
import { is_form_content_type } from '../../utils/http.js';
|
|
8
|
-
import {
|
|
8
|
+
import { handle_fatal_error, redirect_response } from './utils.js';
|
|
9
9
|
import {
|
|
10
10
|
decode_pathname,
|
|
11
11
|
decode_params,
|
|
@@ -38,7 +38,13 @@ const default_filter = () => false;
|
|
|
38
38
|
/** @type {import('types').RequiredResolveOptions['preload']} */
|
|
39
39
|
const default_preload = ({ type }) => type === 'js' || type === 'css';
|
|
40
40
|
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* @param {Request} request
|
|
43
|
+
* @param {import('types').SSROptions} options
|
|
44
|
+
* @param {import('types').SSRManifest} manifest
|
|
45
|
+
* @param {import('types').SSRState} state
|
|
46
|
+
* @returns {Promise<Response>}
|
|
47
|
+
*/
|
|
42
48
|
export async function respond(request, options, manifest, state) {
|
|
43
49
|
/** URL but stripped from the potential `/__data.json` suffix and its search param */
|
|
44
50
|
let url = new URL(request.url);
|
|
@@ -358,17 +364,9 @@ export async function respond(request, options, manifest, state) {
|
|
|
358
364
|
trailing_slash ?? 'never'
|
|
359
365
|
);
|
|
360
366
|
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
|
|
361
|
-
response = await render_endpoint(event,
|
|
367
|
+
response = await render_endpoint(event, await route.endpoint(), state);
|
|
362
368
|
} else if (route.page) {
|
|
363
|
-
response = await render_page(
|
|
364
|
-
event,
|
|
365
|
-
route,
|
|
366
|
-
route.page,
|
|
367
|
-
options,
|
|
368
|
-
manifest,
|
|
369
|
-
state,
|
|
370
|
-
resolve_opts
|
|
371
|
-
);
|
|
369
|
+
response = await render_page(event, route.page, options, manifest, state, resolve_opts);
|
|
372
370
|
} else {
|
|
373
371
|
// a route will always have a page or an endpoint, but TypeScript
|
|
374
372
|
// doesn't know that
|
|
@@ -378,15 +376,15 @@ export async function respond(request, options, manifest, state) {
|
|
|
378
376
|
return response;
|
|
379
377
|
}
|
|
380
378
|
|
|
381
|
-
if (state.
|
|
379
|
+
if (state.error) {
|
|
382
380
|
return text('Internal Server Error', {
|
|
383
381
|
status: 500
|
|
384
382
|
});
|
|
385
383
|
}
|
|
386
384
|
|
|
387
385
|
// if this request came direct from the user, rather than
|
|
388
|
-
// via
|
|
389
|
-
if (
|
|
386
|
+
// via our own `fetch`, render a 404 page
|
|
387
|
+
if (state.depth === 0) {
|
|
390
388
|
return await respond_with_error({
|
|
391
389
|
event,
|
|
392
390
|
options,
|
|
@@ -16,11 +16,6 @@ export function is_pojo(body) {
|
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/** @type {import('types').SSRErrorPage} */
|
|
20
|
-
export const GENERIC_ERROR = {
|
|
21
|
-
id: '__error'
|
|
22
|
-
};
|
|
23
|
-
|
|
24
19
|
/**
|
|
25
20
|
* @param {Partial<Record<import('types').HttpMethod, any>>} mod
|
|
26
21
|
* @param {import('types').HttpMethod} method
|
package/types/index.d.ts
CHANGED
|
@@ -422,6 +422,20 @@ export interface KitConfig {
|
|
|
422
422
|
* @default ".svelte-kit"
|
|
423
423
|
*/
|
|
424
424
|
outDir?: string;
|
|
425
|
+
/**
|
|
426
|
+
* Options related to the build output format
|
|
427
|
+
*/
|
|
428
|
+
output?: {
|
|
429
|
+
/**
|
|
430
|
+
* SvelteKit will preload the JavaScript modules needed for the initial page to avoid import 'waterfalls', resulting in faster application startup. There
|
|
431
|
+
* are three strategies with different trade-offs:
|
|
432
|
+
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers, but is currently ignored by Firefox and Safari (though support is coming to Safari soon).
|
|
433
|
+
* - `preload-js` - uses `<link rel="preload">`. Prevents waterfalls in Chromium and Safari, but Chromium will parse each module twice (once as a script, once as a module). Causes modules to be requested twice in Firefox. This is a good setting if you want to maximise performance for users on iOS devices at the cost of a very slight degradation for Chromium users.
|
|
434
|
+
* - `preload-mjs` - uses `<link rel="preload">` but with the `.mjs` extension which prevents double-parsing in Chromium. Some static webservers will fail to serve .mjs files with a `Content-Type: application/javascript` header, which will cause your application to break. If that doesn't apply to you, this is the option that will deliver the best performance for the largest number of users, until `modulepreload` is more widely supported.
|
|
435
|
+
* @default "modulepreload"
|
|
436
|
+
*/
|
|
437
|
+
preloadStrategy?: 'modulepreload' | 'preload-js' | 'preload-mjs';
|
|
438
|
+
};
|
|
425
439
|
paths?: {
|
|
426
440
|
/**
|
|
427
441
|
* An absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kind.
|
package/types/internal.d.ts
CHANGED
|
@@ -157,15 +157,6 @@ export type RecursiveRequired<T> = {
|
|
|
157
157
|
|
|
158
158
|
export type RequiredResolveOptions = Required<ResolveOptions>;
|
|
159
159
|
|
|
160
|
-
export interface Respond {
|
|
161
|
-
(
|
|
162
|
-
request: Request,
|
|
163
|
-
options: SSROptions,
|
|
164
|
-
manifest: SSRManifest,
|
|
165
|
-
state: SSRState
|
|
166
|
-
): Promise<Response>;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
160
|
export interface RouteParam {
|
|
170
161
|
name: string;
|
|
171
162
|
matcher: string;
|
|
@@ -337,6 +328,7 @@ export interface SSROptions {
|
|
|
337
328
|
embedded: boolean;
|
|
338
329
|
env_public_prefix: string;
|
|
339
330
|
hooks: ServerHooks;
|
|
331
|
+
preload_strategy: ValidatedConfig['kit']['output']['preloadStrategy'];
|
|
340
332
|
root: SSRComponent['default'];
|
|
341
333
|
service_worker: boolean;
|
|
342
334
|
templates: {
|
|
@@ -352,10 +344,6 @@ export interface SSROptions {
|
|
|
352
344
|
version_hash: string;
|
|
353
345
|
}
|
|
354
346
|
|
|
355
|
-
export interface SSRErrorPage {
|
|
356
|
-
id: '__error';
|
|
357
|
-
}
|
|
358
|
-
|
|
359
347
|
export interface PageNodeIndexes {
|
|
360
348
|
errors: Array<number | undefined>;
|
|
361
349
|
layouts: Array<number | undefined>;
|
|
@@ -380,7 +368,14 @@ export interface SSRRoute {
|
|
|
380
368
|
export interface SSRState {
|
|
381
369
|
fallback?: string;
|
|
382
370
|
getClientAddress(): string;
|
|
383
|
-
|
|
371
|
+
/**
|
|
372
|
+
* True if we're currently attempting to render an error page
|
|
373
|
+
*/
|
|
374
|
+
error: boolean;
|
|
375
|
+
/**
|
|
376
|
+
* Allows us to prevent `event.fetch` from making infinitely looping internal requests
|
|
377
|
+
*/
|
|
378
|
+
depth: number;
|
|
384
379
|
platform?: any;
|
|
385
380
|
prerendering?: PrerenderOptions;
|
|
386
381
|
/**
|