@sveltejs/kit 1.21.0 → 1.22.1
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/constants.js +12 -0
- package/src/core/postbuild/analyse.js +6 -6
- package/src/exports/public.d.ts +1 -1
- package/src/exports/vite/build/utils.js +0 -11
- package/src/exports/vite/index.js +7 -1
- package/src/runtime/client/client.js +36 -21
- package/src/runtime/server/endpoint.js +3 -2
- package/src/runtime/server/page/serialize_data.js +6 -7
- package/src/runtime/server/respond.js +45 -3
- package/src/runtime/server/utils.js +2 -3
- package/src/utils/exports.js +1 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.22.1",
|
|
4
4
|
"description": "The fastest way to build Svelte apps",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dts-buddy": "^0.0.10",
|
|
36
36
|
"marked": "^4.2.3",
|
|
37
37
|
"rollup": "^3.7.0",
|
|
38
|
-
"svelte": "^4.0.
|
|
38
|
+
"svelte": "^4.0.3",
|
|
39
39
|
"svelte-preprocess": "^5.0.4",
|
|
40
40
|
"typescript": "^4.9.4",
|
|
41
41
|
"vite": "^4.3.6",
|
package/src/constants.js
CHANGED
|
@@ -5,3 +5,15 @@
|
|
|
5
5
|
export const SVELTE_KIT_ASSETS = '/_svelte_kit_assets';
|
|
6
6
|
|
|
7
7
|
export const GENERATED_COMMENT = '// this file is generated — do not edit it\n';
|
|
8
|
+
|
|
9
|
+
export const ENDPOINT_METHODS = new Set([
|
|
10
|
+
'GET',
|
|
11
|
+
'POST',
|
|
12
|
+
'PUT',
|
|
13
|
+
'PATCH',
|
|
14
|
+
'DELETE',
|
|
15
|
+
'OPTIONS',
|
|
16
|
+
'HEAD'
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export const PAGE_METHODS = new Set(['GET', 'POST', 'HEAD']);
|
|
@@ -13,6 +13,7 @@ import { forked } from '../../utils/fork.js';
|
|
|
13
13
|
import { should_polyfill } from '../../utils/platform.js';
|
|
14
14
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
15
15
|
import { resolvePath } from '../../exports/index.js';
|
|
16
|
+
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
16
17
|
import { filter_private_env, filter_public_env } from '../../utils/env.js';
|
|
17
18
|
|
|
18
19
|
export default forked(import.meta.url, analyse);
|
|
@@ -92,12 +93,11 @@ async function analyse({ manifest_path, env }) {
|
|
|
92
93
|
prerender = mod.prerender;
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (mod.OPTIONS) api_methods.push('OPTIONS');
|
|
96
|
+
Object.values(mod).forEach((/** @type {import('types').HttpMethod} */ method) => {
|
|
97
|
+
if (mod[method] && ENDPOINT_METHODS.has(method)) {
|
|
98
|
+
api_methods.push(method);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
101
|
|
|
102
102
|
config = mod.config;
|
|
103
103
|
entries = mod.entries;
|
package/src/exports/public.d.ts
CHANGED
|
@@ -454,7 +454,7 @@ export interface KitConfig {
|
|
|
454
454
|
/**
|
|
455
455
|
* SvelteKit will preload the JavaScript modules needed for the initial page to avoid import 'waterfalls', resulting in faster application startup. There
|
|
456
456
|
* are three strategies with different trade-offs:
|
|
457
|
-
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers,
|
|
457
|
+
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers, in Firefox 115+, and Safari 17+. It is ignored in older browsers.
|
|
458
458
|
* - `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.
|
|
459
459
|
* - `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.
|
|
460
460
|
* @default "modulepreload"
|
|
@@ -90,14 +90,3 @@ export function resolve_symlinks(manifest, file) {
|
|
|
90
90
|
export function assets_base(config) {
|
|
91
91
|
return (config.paths.assets || config.paths.base || '.') + '/';
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
const method_names = new Set(['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH', 'OPTIONS']);
|
|
95
|
-
|
|
96
|
-
// If we'd written this in TypeScript, it could be easy...
|
|
97
|
-
/**
|
|
98
|
-
* @param {string} str
|
|
99
|
-
* @returns {str is import('types').HttpMethod}
|
|
100
|
-
*/
|
|
101
|
-
export function is_http_method(str) {
|
|
102
|
-
return method_names.has(str);
|
|
103
|
-
}
|
|
@@ -541,8 +541,14 @@ function kit({ svelte_config }) {
|
|
|
541
541
|
// see the kit.output.preloadStrategy option for details on why we have multiple options here
|
|
542
542
|
const ext = kit.output.preloadStrategy === 'preload-mjs' ? 'mjs' : 'js';
|
|
543
543
|
|
|
544
|
+
// We could always use a relative asset base path here, but it's better for performance not to.
|
|
545
|
+
// E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'.
|
|
546
|
+
// That's larger and takes longer to run and also causes an HTML diff between SSR and client
|
|
547
|
+
// causing us to do a more expensive hydration check.
|
|
548
|
+
const client_base = kit.paths.relative || kit.paths.assets ? './' : kit.paths.base || '/';
|
|
549
|
+
|
|
544
550
|
new_config = {
|
|
545
|
-
base: ssr ? assets_base(kit) :
|
|
551
|
+
base: ssr ? assets_base(kit) : client_base,
|
|
546
552
|
build: {
|
|
547
553
|
copyPublicDir: !ssr,
|
|
548
554
|
cssCodeSplit: true,
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { DEV } from 'esm-env';
|
|
2
2
|
import { onMount, tick } from 'svelte';
|
|
3
3
|
import {
|
|
4
|
-
|
|
5
|
-
decode_pathname,
|
|
4
|
+
add_data_suffix,
|
|
6
5
|
decode_params,
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
decode_pathname,
|
|
7
|
+
make_trackable,
|
|
8
|
+
normalize_path
|
|
9
9
|
} from '../../utils/url.js';
|
|
10
|
+
import {
|
|
11
|
+
initial_fetch,
|
|
12
|
+
lock_fetch,
|
|
13
|
+
native_fetch,
|
|
14
|
+
subsequent_fetch,
|
|
15
|
+
unlock_fetch
|
|
16
|
+
} from './fetcher.js';
|
|
17
|
+
import { parse } from './parse.js';
|
|
18
|
+
import * as storage from './session-storage.js';
|
|
10
19
|
import {
|
|
11
20
|
find_anchor,
|
|
12
21
|
get_base_uri,
|
|
@@ -15,25 +24,16 @@ import {
|
|
|
15
24
|
is_external_url,
|
|
16
25
|
scroll_state
|
|
17
26
|
} from './utils.js';
|
|
18
|
-
import * as storage from './session-storage.js';
|
|
19
|
-
import {
|
|
20
|
-
lock_fetch,
|
|
21
|
-
unlock_fetch,
|
|
22
|
-
initial_fetch,
|
|
23
|
-
subsequent_fetch,
|
|
24
|
-
native_fetch
|
|
25
|
-
} from './fetcher.js';
|
|
26
|
-
import { parse } from './parse.js';
|
|
27
27
|
|
|
28
28
|
import { base } from '__sveltekit/paths';
|
|
29
|
-
import { HttpError, Redirect } from '../control.js';
|
|
30
|
-
import { stores } from './singletons.js';
|
|
31
|
-
import { unwrap_promises } from '../../utils/promises.js';
|
|
32
29
|
import * as devalue from 'devalue';
|
|
33
|
-
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js';
|
|
34
|
-
import { validate_page_exports } from '../../utils/exports.js';
|
|
35
30
|
import { compact } from '../../utils/array.js';
|
|
31
|
+
import { validate_page_exports } from '../../utils/exports.js';
|
|
32
|
+
import { unwrap_promises } from '../../utils/promises.js';
|
|
33
|
+
import { HttpError, Redirect } from '../control.js';
|
|
36
34
|
import { INVALIDATED_PARAM, validate_depends } from '../shared.js';
|
|
35
|
+
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY, SNAPSHOT_KEY } from './constants.js';
|
|
36
|
+
import { stores } from './singletons.js';
|
|
37
37
|
|
|
38
38
|
let errored = false;
|
|
39
39
|
|
|
@@ -1555,9 +1555,7 @@ export function create_client(app, target) {
|
|
|
1555
1555
|
|
|
1556
1556
|
update_scroll_positions(current_history_index);
|
|
1557
1557
|
|
|
1558
|
-
|
|
1559
|
-
stores.page.set({ ...page, url });
|
|
1560
|
-
stores.page.notify();
|
|
1558
|
+
update_url(url);
|
|
1561
1559
|
|
|
1562
1560
|
if (!options.replace_state) return;
|
|
1563
1561
|
|
|
@@ -1670,6 +1668,14 @@ export function create_client(app, target) {
|
|
|
1670
1668
|
type: 'popstate',
|
|
1671
1669
|
delta
|
|
1672
1670
|
});
|
|
1671
|
+
} else {
|
|
1672
|
+
// since popstate event is also emitted when an anchor referencing the same
|
|
1673
|
+
// document is clicked, we have to check that the router isn't already handling
|
|
1674
|
+
// the navigation. otherwise we would be updating the page store twice.
|
|
1675
|
+
if (!hash_navigating) {
|
|
1676
|
+
const url = new URL(location.href);
|
|
1677
|
+
update_url(url);
|
|
1678
|
+
}
|
|
1673
1679
|
}
|
|
1674
1680
|
});
|
|
1675
1681
|
|
|
@@ -1702,6 +1708,15 @@ export function create_client(app, target) {
|
|
|
1702
1708
|
stores.navigating.set(null);
|
|
1703
1709
|
}
|
|
1704
1710
|
});
|
|
1711
|
+
|
|
1712
|
+
/**
|
|
1713
|
+
* @param {URL} url
|
|
1714
|
+
*/
|
|
1715
|
+
function update_url(url) {
|
|
1716
|
+
current.url = url;
|
|
1717
|
+
stores.page.set({ ...page, url });
|
|
1718
|
+
stores.page.notify();
|
|
1719
|
+
}
|
|
1705
1720
|
},
|
|
1706
1721
|
|
|
1707
1722
|
_hydrate: async ({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ENDPOINT_METHODS, PAGE_METHODS } from '../../constants.js';
|
|
1
2
|
import { negotiate } from '../../utils/http.js';
|
|
2
3
|
import { Redirect } from '../control.js';
|
|
3
4
|
import { method_not_allowed } from './utils.js';
|
|
@@ -79,8 +80,8 @@ export async function render_endpoint(event, mod, state) {
|
|
|
79
80
|
export function is_endpoint_request(event) {
|
|
80
81
|
const { method, headers } = event.request;
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
// These methods exist exclusively for endpoints
|
|
84
|
+
if (ENDPOINT_METHODS.has(method) && !PAGE_METHODS.has(method)) {
|
|
84
85
|
return true;
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -46,7 +46,7 @@ export function serialize_data(fetched, filter, prerendering = false) {
|
|
|
46
46
|
|
|
47
47
|
let cache_control = null;
|
|
48
48
|
let age = null;
|
|
49
|
-
let
|
|
49
|
+
let varyAny = false;
|
|
50
50
|
|
|
51
51
|
for (const [key, value] of fetched.response.headers) {
|
|
52
52
|
if (filter(key, value)) {
|
|
@@ -54,8 +54,8 @@ export function serialize_data(fetched, filter, prerendering = false) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
if (key === 'cache-control') cache_control = value;
|
|
57
|
-
if (key === 'age') age = value;
|
|
58
|
-
if (key === 'vary')
|
|
57
|
+
else if (key === 'age') age = value;
|
|
58
|
+
else if (key === 'vary' && value.trim() === '*') varyAny = true;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
const payload = {
|
|
@@ -89,10 +89,9 @@ export function serialize_data(fetched, filter, prerendering = false) {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
// Compute the time the response should be cached, taking into account max-age and age.
|
|
92
|
-
// Do not cache at all if a
|
|
93
|
-
// likely to get busted.
|
|
94
|
-
|
|
95
|
-
if (!prerendering && fetched.method === 'GET' && cache_control && !vary) {
|
|
92
|
+
// Do not cache at all if a `Vary: *` header is present, as this indicates that the
|
|
93
|
+
// cache is likely to get busted.
|
|
94
|
+
if (!prerendering && fetched.method === 'GET' && cache_control && !varyAny) {
|
|
96
95
|
const match = /s-maxage=(\d+)/g.exec(cache_control) ?? /max-age=(\d+)/g.exec(cache_control);
|
|
97
96
|
if (match) {
|
|
98
97
|
const ttl = +match[1] - +(age ?? '0');
|
|
@@ -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 { handle_fatal_error, redirect_response } from './utils.js';
|
|
8
|
+
import { handle_fatal_error, method_not_allowed, redirect_response } from './utils.js';
|
|
9
9
|
import {
|
|
10
10
|
decode_pathname,
|
|
11
11
|
decode_params,
|
|
@@ -42,6 +42,10 @@ const default_filter = () => false;
|
|
|
42
42
|
/** @type {import('types').RequiredResolveOptions['preload']} */
|
|
43
43
|
const default_preload = ({ type }) => type === 'js' || type === 'css';
|
|
44
44
|
|
|
45
|
+
const page_methods = new Set(['GET', 'HEAD', 'POST']);
|
|
46
|
+
|
|
47
|
+
const allowed_page_methods = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
48
|
+
|
|
45
49
|
/**
|
|
46
50
|
* @param {Request} request
|
|
47
51
|
* @param {import('types').SSROptions} options
|
|
@@ -343,7 +347,6 @@ export async function respond(request, options, manifest, state) {
|
|
|
343
347
|
}
|
|
344
348
|
|
|
345
349
|
/**
|
|
346
|
-
*
|
|
347
350
|
* @param {import('@sveltejs/kit').RequestEvent} event
|
|
348
351
|
* @param {import('@sveltejs/kit').ResolveOptions} [opts]
|
|
349
352
|
*/
|
|
@@ -379,6 +382,8 @@ export async function respond(request, options, manifest, state) {
|
|
|
379
382
|
}
|
|
380
383
|
|
|
381
384
|
if (route) {
|
|
385
|
+
const method = /** @type {import('types').HttpMethod} */ (event.request.method);
|
|
386
|
+
|
|
382
387
|
/** @type {Response} */
|
|
383
388
|
let response;
|
|
384
389
|
|
|
@@ -395,13 +400,50 @@ export async function respond(request, options, manifest, state) {
|
|
|
395
400
|
} else if (route.endpoint && (!route.page || is_endpoint_request(event))) {
|
|
396
401
|
response = await render_endpoint(event, await route.endpoint(), state);
|
|
397
402
|
} else if (route.page) {
|
|
398
|
-
|
|
403
|
+
if (page_methods.has(method)) {
|
|
404
|
+
response = await render_page(event, route.page, options, manifest, state, resolve_opts);
|
|
405
|
+
} else {
|
|
406
|
+
const allowed_methods = new Set(allowed_page_methods);
|
|
407
|
+
const node = await manifest._.nodes[route.page.leaf]();
|
|
408
|
+
if (node?.server?.actions) {
|
|
409
|
+
allowed_methods.add('POST');
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (method === 'OPTIONS') {
|
|
413
|
+
// This will deny CORS preflight requests implicitly because we don't
|
|
414
|
+
// add the required CORS headers to the response.
|
|
415
|
+
response = new Response(null, {
|
|
416
|
+
status: 204,
|
|
417
|
+
headers: {
|
|
418
|
+
allow: Array.from(allowed_methods.values()).join(', ')
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
} else {
|
|
422
|
+
const mod = [...allowed_methods].reduce((acc, curr) => {
|
|
423
|
+
acc[curr] = true;
|
|
424
|
+
return acc;
|
|
425
|
+
}, /** @type {Record<string, any>} */ ({}));
|
|
426
|
+
response = method_not_allowed(mod, method);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
399
429
|
} else {
|
|
400
430
|
// a route will always have a page or an endpoint, but TypeScript
|
|
401
431
|
// doesn't know that
|
|
402
432
|
throw new Error('This should never happen');
|
|
403
433
|
}
|
|
404
434
|
|
|
435
|
+
// If the route contains a page and an endpoint, we need to add a
|
|
436
|
+
// `Vary: Accept` header to the response because of browser caching
|
|
437
|
+
if (request.method === 'GET' && route.page && route.endpoint) {
|
|
438
|
+
const vary = response.headers
|
|
439
|
+
.get('vary')
|
|
440
|
+
?.split(',')
|
|
441
|
+
?.map((v) => v.trim().toLowerCase());
|
|
442
|
+
if (!(vary?.includes('accept') || vary?.includes('*'))) {
|
|
443
|
+
response.headers.append('Vary', 'Accept');
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
405
447
|
return response;
|
|
406
448
|
}
|
|
407
449
|
|
|
@@ -4,6 +4,7 @@ import { coalesce_to_error } from '../../utils/error.js';
|
|
|
4
4
|
import { negotiate } from '../../utils/http.js';
|
|
5
5
|
import { HttpError } from '../control.js';
|
|
6
6
|
import { fix_stack_trace } from '../shared-server.js';
|
|
7
|
+
import { ENDPOINT_METHODS } from '../../constants.js';
|
|
7
8
|
|
|
8
9
|
/** @param {any} body */
|
|
9
10
|
export function is_pojo(body) {
|
|
@@ -34,9 +35,7 @@ export function method_not_allowed(mod, method) {
|
|
|
34
35
|
|
|
35
36
|
/** @param {Partial<Record<import('types').HttpMethod, any>>} mod */
|
|
36
37
|
export function allowed_methods(mod) {
|
|
37
|
-
const allowed =
|
|
38
|
-
(method) => method in mod
|
|
39
|
-
);
|
|
38
|
+
const allowed = Array.from(ENDPOINT_METHODS).filter((method) => method in mod);
|
|
40
39
|
|
|
41
40
|
if ('GET' in mod || 'HEAD' in mod) allowed.push('HEAD');
|
|
42
41
|
|
package/src/utils/exports.js
CHANGED
package/src/version.js
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -408,7 +408,7 @@ declare module '@sveltejs/kit' {
|
|
|
408
408
|
/**
|
|
409
409
|
* SvelteKit will preload the JavaScript modules needed for the initial page to avoid import 'waterfalls', resulting in faster application startup. There
|
|
410
410
|
* are three strategies with different trade-offs:
|
|
411
|
-
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers,
|
|
411
|
+
* - `modulepreload` - uses `<link rel="modulepreload">`. This delivers the best results in Chromium-based browsers, in Firefox 115+, and Safari 17+. It is ignored in older browsers.
|
|
412
412
|
* - `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.
|
|
413
413
|
* - `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.
|
|
414
414
|
* @default "modulepreload"
|