@sveltejs/kit 2.56.1 → 2.57.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/config/index.js +22 -2
- package/src/core/config/options.js +20 -4
- package/src/core/postbuild/prerender.js +2 -1
- package/src/core/sync/utils.js +8 -1
- package/src/core/utils.js +1 -2
- package/src/exports/node/index.js +2 -1
- package/src/exports/public.d.ts +24 -17
- package/src/exports/vite/build/build_service_worker.js +1 -1
- package/src/exports/vite/build/remote.js +126 -0
- package/src/exports/vite/dev/index.js +21 -8
- package/src/exports/vite/index.js +35 -22
- package/src/exports/vite/preview/index.js +5 -1
- package/src/exports/vite/utils.js +18 -0
- package/src/runtime/app/forms.js +2 -1
- package/src/runtime/app/server/remote/prerender.js +2 -1
- package/src/runtime/app/server/remote/query.js +2 -4
- package/src/runtime/app/server/remote/requested.js +3 -2
- package/src/runtime/app/server/remote/shared.js +2 -1
- package/src/runtime/client/client.js +7 -8
- package/src/runtime/client/fetcher.js +2 -1
- package/src/runtime/client/remote-functions/form.svelte.js +10 -5
- package/src/runtime/client/remote-functions/query.svelte.js +3 -2
- package/src/runtime/client/utils.js +2 -1
- package/src/runtime/server/fetch.js +4 -3
- package/src/runtime/server/index.js +3 -2
- package/src/runtime/server/page/index.js +3 -2
- package/src/runtime/server/page/load_data.js +4 -3
- package/src/runtime/server/page/render.js +7 -1
- package/src/runtime/server/respond.js +0 -17
- package/src/utils/functions.js +2 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +26 -18
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltejs/kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.57.0",
|
|
4
4
|
"description": "SvelteKit is the fastest way to build Svelte apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@opentelemetry/api": "^1.0.0",
|
|
36
|
-
"@playwright/test": "1.
|
|
36
|
+
"@playwright/test": "^1.59.1",
|
|
37
37
|
"@sveltejs/vite-plugin-svelte": "^6.0.0-next.3",
|
|
38
38
|
"@types/connect": "^3.4.38",
|
|
39
39
|
"@types/node": "^18.19.119",
|
package/src/core/config/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import process from 'node:process';
|
|
4
4
|
import * as url from 'node:url';
|
|
5
5
|
import options from './options.js';
|
|
6
|
+
import { resolve_entry } from '../../utils/filesystem.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Loads the template (src/app.html by default) and validates that it has the
|
|
@@ -96,7 +97,7 @@ export async function load_config({ cwd = process.cwd() } = {}) {
|
|
|
96
97
|
* @returns {import('types').ValidatedConfig}
|
|
97
98
|
*/
|
|
98
99
|
function process_config(config, { cwd = process.cwd() } = {}) {
|
|
99
|
-
const validated = validate_config(config);
|
|
100
|
+
const validated = validate_config(config, cwd);
|
|
100
101
|
|
|
101
102
|
validated.kit.outDir = path.resolve(cwd, validated.kit.outDir);
|
|
102
103
|
|
|
@@ -116,15 +117,17 @@ function process_config(config, { cwd = process.cwd() } = {}) {
|
|
|
116
117
|
|
|
117
118
|
/**
|
|
118
119
|
* @param {import('@sveltejs/kit').Config} config
|
|
120
|
+
* @param {string} [cwd]
|
|
119
121
|
* @returns {import('types').ValidatedConfig}
|
|
120
122
|
*/
|
|
121
|
-
export function validate_config(config) {
|
|
123
|
+
export function validate_config(config, cwd = process.cwd()) {
|
|
122
124
|
if (typeof config !== 'object') {
|
|
123
125
|
throw new Error(
|
|
124
126
|
'The Svelte config file must have a configuration object as its default export. See https://svelte.dev/docs/kit/configuration'
|
|
125
127
|
);
|
|
126
128
|
}
|
|
127
129
|
|
|
130
|
+
/** @type {import('types').ValidatedConfig} */
|
|
128
131
|
const validated = options(config, 'config');
|
|
129
132
|
const files = validated.kit.files;
|
|
130
133
|
|
|
@@ -151,5 +154,22 @@ export function validate_config(config) {
|
|
|
151
154
|
}
|
|
152
155
|
}
|
|
153
156
|
|
|
157
|
+
if (validated.kit.csp?.directives?.['require-trusted-types-for']?.includes('script')) {
|
|
158
|
+
if (!validated.kit.csp?.directives?.['trusted-types']?.includes('svelte-trusted-html')) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
"The `csp.directives['trusted-types']` option must include 'svelte-trusted-html'"
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (
|
|
164
|
+
validated.kit.serviceWorker?.register &&
|
|
165
|
+
resolve_entry(path.resolve(cwd, validated.kit.files.serviceWorker)) &&
|
|
166
|
+
!validated.kit.csp?.directives?.['trusted-types']?.includes('sveltekit-trusted-url')
|
|
167
|
+
) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
"The `csp.directives['trusted-types']` option must include 'sveltekit-trusted-url' when `serviceWorker.register` is true"
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
154
174
|
return validated;
|
|
155
175
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/** @import { Validator } from './types.js' */
|
|
2
|
+
|
|
1
3
|
import process from 'node:process';
|
|
2
4
|
import colors from 'kleur';
|
|
3
|
-
|
|
4
|
-
/** @typedef {import('./types.js').Validator} Validator */
|
|
5
|
+
import { supportsTrustedTypes } from '../sync/utils.js';
|
|
5
6
|
|
|
6
7
|
const directives = object({
|
|
7
8
|
'child-src': string_array(),
|
|
@@ -28,8 +29,14 @@ const directives = object({
|
|
|
28
29
|
'navigate-to': string_array(),
|
|
29
30
|
'report-uri': string_array(),
|
|
30
31
|
'report-to': string_array(),
|
|
31
|
-
'require-trusted-types-for':
|
|
32
|
-
|
|
32
|
+
'require-trusted-types-for': validate(undefined, (input, keypath) => {
|
|
33
|
+
assert_trusted_types_supported(keypath);
|
|
34
|
+
return string_array()(input, keypath);
|
|
35
|
+
}),
|
|
36
|
+
'trusted-types': validate(undefined, (input, keypath) => {
|
|
37
|
+
assert_trusted_types_supported(keypath);
|
|
38
|
+
return string_array()(input, keypath);
|
|
39
|
+
}),
|
|
33
40
|
'upgrade-insecure-requests': boolean(false),
|
|
34
41
|
'require-sri-for': string_array(),
|
|
35
42
|
'block-all-mixed-content': boolean(false),
|
|
@@ -486,4 +493,13 @@ function assert_string(input, keypath) {
|
|
|
486
493
|
}
|
|
487
494
|
}
|
|
488
495
|
|
|
496
|
+
/** @param {string} keypath */
|
|
497
|
+
function assert_trusted_types_supported(keypath) {
|
|
498
|
+
if (!supportsTrustedTypes()) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`${keypath} is not supported by your version of Svelte. Please upgrade to Svelte 5.51.0 or later to use this directive.`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
489
505
|
export default options;
|
|
@@ -3,6 +3,7 @@ import { dirname, join } from 'node:path';
|
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
import { installPolyfills } from '../../exports/node/polyfills.js';
|
|
5
5
|
import { mkdirp, posixify, walk } from '../../utils/filesystem.js';
|
|
6
|
+
import { noop } from '../../utils/functions.js';
|
|
6
7
|
import { decode_uri, is_root_relative, resolve } from '../../utils/url.js';
|
|
7
8
|
import { escape_html } from '../../utils/escape.js';
|
|
8
9
|
import { logger } from '../utils.js';
|
|
@@ -69,7 +70,7 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env }) {
|
|
|
69
70
|
log.error(format(details));
|
|
70
71
|
};
|
|
71
72
|
case 'ignore':
|
|
72
|
-
return
|
|
73
|
+
return noop;
|
|
73
74
|
default:
|
|
74
75
|
// @ts-expect-error TS thinks T might be of a different kind, but it's not
|
|
75
76
|
return (details) => input({ ...details, message: format(details) });
|
package/src/core/sync/utils.js
CHANGED
|
@@ -6,6 +6,8 @@ import { import_peer } from '../../utils/import.js';
|
|
|
6
6
|
/** @type {{ VERSION: string }} */
|
|
7
7
|
const { VERSION } = await import_peer('svelte/compiler');
|
|
8
8
|
|
|
9
|
+
const [MAJOR, MINOR] = VERSION.split('.').map(Number);
|
|
10
|
+
|
|
9
11
|
/** @type {Map<string, string>} */
|
|
10
12
|
const previous_contents = new Map();
|
|
11
13
|
|
|
@@ -74,5 +76,10 @@ export function dedent(strings, ...values) {
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
export function isSvelte5Plus() {
|
|
77
|
-
return
|
|
79
|
+
return MAJOR >= 5;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// TODO 3.0 remove this once we can bump the peerDep range
|
|
83
|
+
export function supportsTrustedTypes() {
|
|
84
|
+
return (MAJOR === 5 && MINOR >= 51) || MAJOR > 5;
|
|
78
85
|
}
|
package/src/core/utils.js
CHANGED
|
@@ -4,6 +4,7 @@ import process from 'node:process';
|
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import colors from 'kleur';
|
|
6
6
|
import { posixify, to_fs } from '../utils/filesystem.js';
|
|
7
|
+
import { noop } from '../utils/functions.js';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Resolved path of the `runtime` directory
|
|
@@ -24,8 +25,6 @@ export const runtime_base = runtime_directory.startsWith(process.cwd())
|
|
|
24
25
|
? `/${path.relative('.', runtime_directory)}`
|
|
25
26
|
: to_fs(runtime_directory);
|
|
26
27
|
|
|
27
|
-
function noop() {}
|
|
28
|
-
|
|
29
28
|
/** @param {{ verbose: boolean }} opts */
|
|
30
29
|
export function logger({ verbose }) {
|
|
31
30
|
/** @type {import('types').Logger} */
|
|
@@ -2,6 +2,7 @@ import { createReadStream } from 'node:fs';
|
|
|
2
2
|
import { Readable } from 'node:stream';
|
|
3
3
|
import * as set_cookie_parser from 'set-cookie-parser';
|
|
4
4
|
import { SvelteKitError } from '../internal/index.js';
|
|
5
|
+
import { noop } from '../../utils/functions.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* @param {import('http').IncomingMessage} req
|
|
@@ -200,7 +201,7 @@ export async function setResponse(res, response) {
|
|
|
200
201
|
|
|
201
202
|
// If the reader has already been interrupted with an error earlier,
|
|
202
203
|
// then it will appear here, it is useless, but it needs to be catch.
|
|
203
|
-
reader.cancel(error).catch(
|
|
204
|
+
reader.cancel(error).catch(noop);
|
|
204
205
|
if (error) res.destroy(error);
|
|
205
206
|
};
|
|
206
207
|
|
package/src/exports/public.d.ts
CHANGED
|
@@ -1893,28 +1893,35 @@ type InputElementProps<T extends keyof InputTypeMap> = T extends 'checkbox' | 'r
|
|
|
1893
1893
|
get files(): FileList | null;
|
|
1894
1894
|
set files(v: FileList | null);
|
|
1895
1895
|
}
|
|
1896
|
-
: T extends 'select'
|
|
1896
|
+
: T extends 'select'
|
|
1897
1897
|
? {
|
|
1898
1898
|
name: string;
|
|
1899
|
-
multiple: T extends 'select' ? false : true;
|
|
1900
1899
|
'aria-invalid': boolean | 'false' | 'true' | undefined;
|
|
1901
|
-
get value(): string
|
|
1902
|
-
set value(v: string
|
|
1900
|
+
get value(): string;
|
|
1901
|
+
set value(v: string);
|
|
1903
1902
|
}
|
|
1904
|
-
: T extends '
|
|
1903
|
+
: T extends 'select multiple'
|
|
1905
1904
|
? {
|
|
1906
1905
|
name: string;
|
|
1906
|
+
multiple: true;
|
|
1907
1907
|
'aria-invalid': boolean | 'false' | 'true' | undefined;
|
|
1908
|
-
get value(): string
|
|
1909
|
-
set value(v: string
|
|
1908
|
+
get value(): string[];
|
|
1909
|
+
set value(v: string[]);
|
|
1910
1910
|
}
|
|
1911
|
-
:
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1911
|
+
: T extends 'text'
|
|
1912
|
+
? {
|
|
1913
|
+
name: string;
|
|
1914
|
+
'aria-invalid': boolean | 'false' | 'true' | undefined;
|
|
1915
|
+
get value(): string | number;
|
|
1916
|
+
set value(v: string | number);
|
|
1917
|
+
}
|
|
1918
|
+
: {
|
|
1919
|
+
name: string;
|
|
1920
|
+
type: T;
|
|
1921
|
+
'aria-invalid': boolean | 'false' | 'true' | undefined;
|
|
1922
|
+
get value(): string | number;
|
|
1923
|
+
set value(v: string | number);
|
|
1924
|
+
};
|
|
1918
1925
|
|
|
1919
1926
|
type RemoteFormFieldMethods<T> = {
|
|
1920
1927
|
/** The values that will be submitted */
|
|
@@ -2075,10 +2082,10 @@ export type RemoteForm<Input extends RemoteFormInput | void, Output> = {
|
|
|
2075
2082
|
callback: (opts: {
|
|
2076
2083
|
form: HTMLFormElement;
|
|
2077
2084
|
data: Input;
|
|
2078
|
-
submit: () => Promise<
|
|
2079
|
-
updates: (...updates: RemoteQueryUpdate[]) => Promise<
|
|
2085
|
+
submit: () => Promise<boolean> & {
|
|
2086
|
+
updates: (...updates: RemoteQueryUpdate[]) => Promise<boolean>;
|
|
2080
2087
|
};
|
|
2081
|
-
}) => void
|
|
2088
|
+
}) => void
|
|
2082
2089
|
): {
|
|
2083
2090
|
method: 'POST';
|
|
2084
2091
|
action: string;
|
|
@@ -110,7 +110,7 @@ export async function build_service_worker(
|
|
|
110
110
|
// .mjs so that esbuild doesn't incorrectly inject `export` https://github.com/vitejs/vite/issues/15379
|
|
111
111
|
entryFileNames: `service-worker.${is_rolldown ? 'js' : 'mjs'}`,
|
|
112
112
|
assetFileNames: `${kit.appDir}/immutable/assets/[name].[hash][extname]`,
|
|
113
|
-
inlineDynamicImports: !is_rolldown
|
|
113
|
+
inlineDynamicImports: !is_rolldown ? true : undefined
|
|
114
114
|
}
|
|
115
115
|
},
|
|
116
116
|
outDir: `${out}/client`,
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/** @import { ServerMetadata } from 'types' */
|
|
2
|
+
/** @import { Rollup } from 'vite' */
|
|
3
|
+
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { Parser } from 'acorn';
|
|
7
|
+
import MagicString from 'magic-string';
|
|
8
|
+
import { posixify } from '../../../utils/filesystem.js';
|
|
9
|
+
import { import_peer } from '../../../utils/import.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {string} out
|
|
13
|
+
* @param {Array<{ hash: string, file: string }>} remotes
|
|
14
|
+
* @param {ServerMetadata} metadata
|
|
15
|
+
* @param {string} cwd
|
|
16
|
+
* @param {Rollup.OutputBundle} server_bundle
|
|
17
|
+
* @param {NonNullable<import('vitest/config').ViteUserConfig['build']>['sourcemap']} sourcemap
|
|
18
|
+
*/
|
|
19
|
+
export async function treeshake_prerendered_remotes(
|
|
20
|
+
out,
|
|
21
|
+
remotes,
|
|
22
|
+
metadata,
|
|
23
|
+
cwd,
|
|
24
|
+
server_bundle,
|
|
25
|
+
sourcemap
|
|
26
|
+
) {
|
|
27
|
+
if (remotes.length === 0) return;
|
|
28
|
+
|
|
29
|
+
const vite = /** @type {typeof import('vite')} */ (await import_peer('vite'));
|
|
30
|
+
|
|
31
|
+
for (const remote of remotes) {
|
|
32
|
+
const exports_map = metadata.remotes.get(remote.hash);
|
|
33
|
+
if (!exports_map) continue;
|
|
34
|
+
|
|
35
|
+
/** @type {string[]} */
|
|
36
|
+
const dynamic = [];
|
|
37
|
+
/** @type {string[]} */
|
|
38
|
+
const prerendered = [];
|
|
39
|
+
|
|
40
|
+
for (const [name, value] of exports_map) {
|
|
41
|
+
(value.dynamic ? dynamic : prerendered).push(name);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (prerendered.length === 0) continue; // nothing to treeshake
|
|
45
|
+
|
|
46
|
+
// remove file extension
|
|
47
|
+
const remote_filename = path.basename(remote.file).split('.').slice(0, -1).join('.');
|
|
48
|
+
|
|
49
|
+
const remote_chunk = Object.values(server_bundle).find((chunk) => {
|
|
50
|
+
return chunk.name === remote_filename;
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
if (!remote_chunk) continue;
|
|
54
|
+
|
|
55
|
+
const chunk_path = posixify(path.relative(cwd, `${out}/server/${remote_chunk.fileName}`));
|
|
56
|
+
|
|
57
|
+
const code = fs.readFileSync(chunk_path, 'utf-8');
|
|
58
|
+
const parsed = Parser.parse(code, { sourceType: 'module', ecmaVersion: 'latest' });
|
|
59
|
+
const modified_code = new MagicString(code);
|
|
60
|
+
|
|
61
|
+
for (const fn of prerendered) {
|
|
62
|
+
for (const node of parsed.body) {
|
|
63
|
+
const declaration =
|
|
64
|
+
node.type === 'ExportNamedDeclaration'
|
|
65
|
+
? node.declaration
|
|
66
|
+
: node.type === 'VariableDeclaration'
|
|
67
|
+
? node
|
|
68
|
+
: null;
|
|
69
|
+
|
|
70
|
+
if (!declaration || declaration.type !== 'VariableDeclaration') continue;
|
|
71
|
+
|
|
72
|
+
for (const declarator of declaration.declarations) {
|
|
73
|
+
if (declarator.id.type === 'Identifier' && declarator.id.name === fn) {
|
|
74
|
+
modified_code.overwrite(
|
|
75
|
+
node.start,
|
|
76
|
+
node.end,
|
|
77
|
+
`const ${fn} = prerender('unchecked', () => { throw new Error('Unexpectedly called prerender function. Did you forget to set { dynamic: true } ?') });`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
for (const node of parsed.body) {
|
|
85
|
+
if (node.type === 'ExportDefaultDeclaration') {
|
|
86
|
+
modified_code.remove(node.start, node.end);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const stubbed = modified_code.toString();
|
|
91
|
+
fs.writeFileSync(chunk_path, stubbed);
|
|
92
|
+
|
|
93
|
+
const bundle = /** @type {import('vite').Rollup.RollupOutput} */ (
|
|
94
|
+
await vite.build({
|
|
95
|
+
configFile: false,
|
|
96
|
+
build: {
|
|
97
|
+
write: false,
|
|
98
|
+
ssr: true,
|
|
99
|
+
target: 'esnext',
|
|
100
|
+
sourcemap,
|
|
101
|
+
rollupOptions: {
|
|
102
|
+
// avoid resolving imports
|
|
103
|
+
external: (id) => !id.endsWith(chunk_path),
|
|
104
|
+
input: {
|
|
105
|
+
treeshaken: chunk_path
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
const chunk = bundle.output.find(
|
|
113
|
+
(output) => output.type === 'chunk' && output.name === 'treeshaken'
|
|
114
|
+
);
|
|
115
|
+
if (chunk && chunk.type === 'chunk') {
|
|
116
|
+
fs.writeFileSync(chunk_path, chunk.code);
|
|
117
|
+
|
|
118
|
+
const chunk_sourcemap = bundle.output.find(
|
|
119
|
+
(output) => output.type === 'asset' && output.fileName === chunk.fileName + '.map'
|
|
120
|
+
);
|
|
121
|
+
if (chunk_sourcemap && chunk_sourcemap.type === 'asset') {
|
|
122
|
+
fs.writeFileSync(chunk_path + '.map', chunk_sourcemap.source);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** @import { RequestEvent } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { PrerenderOption, UniversalNode } from 'types' */
|
|
1
3
|
import fs from 'node:fs';
|
|
2
4
|
import path from 'node:path';
|
|
3
5
|
import process from 'node:process';
|
|
@@ -15,7 +17,7 @@ import { SVELTE_KIT_ASSETS } from '../../../constants.js';
|
|
|
15
17
|
import * as sync from '../../../core/sync/sync.js';
|
|
16
18
|
import { get_mime_lookup, runtime_base } from '../../../core/utils.js';
|
|
17
19
|
import { compact } from '../../../utils/array.js';
|
|
18
|
-
import { not_found } from '../utils.js';
|
|
20
|
+
import { is_chrome_devtools_request, not_found } from '../utils.js';
|
|
19
21
|
import { SCHEME } from '../../../utils/url.js';
|
|
20
22
|
import { check_feature } from '../../../utils/features.js';
|
|
21
23
|
import { escape_html } from '../../../utils/escape.js';
|
|
@@ -34,13 +36,19 @@ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
|
|
|
34
36
|
export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
35
37
|
installPolyfills();
|
|
36
38
|
|
|
39
|
+
/** @type {AsyncLocalStorage<{ event: RequestEvent, config: any, prerender: PrerenderOption }>} */
|
|
37
40
|
const async_local_storage = new AsyncLocalStorage();
|
|
38
41
|
|
|
39
42
|
globalThis.__SVELTEKIT_TRACK__ = (label) => {
|
|
40
43
|
const context = async_local_storage.getStore();
|
|
41
44
|
if (!context || context.prerender === true) return;
|
|
42
45
|
|
|
43
|
-
check_feature(
|
|
46
|
+
check_feature(
|
|
47
|
+
/** @type {string} */ (context.event.route.id),
|
|
48
|
+
context.config,
|
|
49
|
+
label,
|
|
50
|
+
svelte_config.kit.adapter
|
|
51
|
+
);
|
|
44
52
|
};
|
|
45
53
|
|
|
46
54
|
const fetch = globalThis.fetch;
|
|
@@ -68,7 +76,8 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
|
68
76
|
async function loud_ssr_load_module(url) {
|
|
69
77
|
try {
|
|
70
78
|
return await vite.ssrLoadModule(url, { fixStacktrace: true });
|
|
71
|
-
} catch (/** @type {
|
|
79
|
+
} catch (/** @type {unknown} */ e) {
|
|
80
|
+
const err = /** @type {import('rollup').RollupError} */ (e);
|
|
72
81
|
const msg = buildErrorMessage(err, [colors.red(`Internal server error: ${err.message}`)]);
|
|
73
82
|
|
|
74
83
|
if (!vite.config.logger.hasErrorLogged(err)) {
|
|
@@ -77,13 +86,13 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
|
77
86
|
|
|
78
87
|
vite.ws.send({
|
|
79
88
|
type: 'error',
|
|
80
|
-
err: {
|
|
89
|
+
err: /** @type {import('vite').ErrorPayload['err']} */ ({
|
|
81
90
|
...err,
|
|
82
91
|
// these properties are non-enumerable and will
|
|
83
92
|
// not be serialized unless we explicitly include them
|
|
84
93
|
message: err.message,
|
|
85
|
-
stack: err.stack
|
|
86
|
-
}
|
|
94
|
+
stack: err.stack ?? ''
|
|
95
|
+
})
|
|
87
96
|
});
|
|
88
97
|
|
|
89
98
|
throw err;
|
|
@@ -204,7 +213,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
|
204
213
|
|
|
205
214
|
if (node.universal) {
|
|
206
215
|
if (node.page_options?.ssr === false) {
|
|
207
|
-
result.universal = node.page_options;
|
|
216
|
+
result.universal = /** @type {UniversalNode} */ (node.page_options);
|
|
208
217
|
} else {
|
|
209
218
|
// TODO: explain why the file was loaded on the server if we fail to load it
|
|
210
219
|
const { module, module_node } = await resolve(node.universal);
|
|
@@ -437,7 +446,7 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
|
437
446
|
return () => {
|
|
438
447
|
const serve_static_middleware = vite.middlewares.stack.find(
|
|
439
448
|
(middleware) =>
|
|
440
|
-
/** @type {
|
|
449
|
+
/** @type {Function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
|
|
441
450
|
);
|
|
442
451
|
|
|
443
452
|
// Vite will give a 403 on URLs like /test, /static, and /package.json preventing us from
|
|
@@ -467,6 +476,10 @@ export async function dev(vite, vite_config, svelte_config, get_remotes) {
|
|
|
467
476
|
return;
|
|
468
477
|
}
|
|
469
478
|
|
|
479
|
+
if (is_chrome_devtools_request(decoded, res)) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
|
|
470
483
|
if (!decoded.startsWith(svelte_config.kit.paths.base)) {
|
|
471
484
|
return not_found(req, res, svelte_config.kit.paths.base);
|
|
472
485
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/** @import { Options } from '@sveltejs/vite-plugin-svelte' */
|
|
2
|
+
/** @import { PreprocessorGroup } from 'svelte/compiler' */
|
|
3
|
+
/** @import { ConfigEnv, Manifest, Plugin, ResolvedConfig, UserConfig, ViteDevServer } from 'vite' */
|
|
1
4
|
import fs from 'node:fs';
|
|
2
5
|
import path from 'node:path';
|
|
3
6
|
import process from 'node:process';
|
|
@@ -41,6 +44,7 @@ import {
|
|
|
41
44
|
import { import_peer } from '../../utils/import.js';
|
|
42
45
|
import { compact } from '../../utils/array.js';
|
|
43
46
|
import { should_ignore, has_children } from './static_analysis/utils.js';
|
|
47
|
+
import { treeshake_prerendered_remotes } from './build/remote.js';
|
|
44
48
|
|
|
45
49
|
const cwd = posixify(process.cwd());
|
|
46
50
|
|
|
@@ -86,7 +90,7 @@ const options_regex = /(export\s+const\s+(prerender|csr|ssr|trailingSlash))\s*=/
|
|
|
86
90
|
/** @type {Set<string>} */
|
|
87
91
|
const warned = new Set();
|
|
88
92
|
|
|
89
|
-
/** @type {
|
|
93
|
+
/** @type {PreprocessorGroup} */
|
|
90
94
|
const warning_preprocessor = {
|
|
91
95
|
script: ({ content, filename }) => {
|
|
92
96
|
if (!filename) return;
|
|
@@ -129,12 +133,12 @@ const warning_preprocessor = {
|
|
|
129
133
|
|
|
130
134
|
/**
|
|
131
135
|
* Returns the SvelteKit Vite plugins.
|
|
132
|
-
* @returns {Promise<
|
|
136
|
+
* @returns {Promise<Plugin[]>}
|
|
133
137
|
*/
|
|
134
138
|
export async function sveltekit() {
|
|
135
139
|
const svelte_config = await load_config();
|
|
136
140
|
|
|
137
|
-
/** @type {
|
|
141
|
+
/** @type {Options['preprocess']} */
|
|
138
142
|
let preprocess = svelte_config.preprocess;
|
|
139
143
|
if (Array.isArray(preprocess)) {
|
|
140
144
|
preprocess = [...preprocess, warning_preprocessor];
|
|
@@ -144,7 +148,7 @@ export async function sveltekit() {
|
|
|
144
148
|
preprocess = warning_preprocessor;
|
|
145
149
|
}
|
|
146
150
|
|
|
147
|
-
/** @type {
|
|
151
|
+
/** @type {Options} */
|
|
148
152
|
const vite_plugin_svelte_options = {
|
|
149
153
|
configFile: false,
|
|
150
154
|
extensions: svelte_config.extensions,
|
|
@@ -184,10 +188,10 @@ let build_metadata = undefined;
|
|
|
184
188
|
* - https://rollupjs.org/guide/en/#output-generation-hooks
|
|
185
189
|
*
|
|
186
190
|
* @param {{ svelte_config: import('types').ValidatedConfig }} options
|
|
187
|
-
* @return {Promise<
|
|
191
|
+
* @return {Promise<Plugin[]>}
|
|
188
192
|
*/
|
|
189
193
|
async function kit({ svelte_config }) {
|
|
190
|
-
/** @type {import('vite')} */
|
|
194
|
+
/** @type {typeof import('vite')} */
|
|
191
195
|
const vite = await import_peer('vite');
|
|
192
196
|
|
|
193
197
|
// @ts-ignore `vite.rolldownVersion` only exists in `vite 8`
|
|
@@ -198,10 +202,10 @@ async function kit({ svelte_config }) {
|
|
|
198
202
|
|
|
199
203
|
const version_hash = hash(kit.version.name);
|
|
200
204
|
|
|
201
|
-
/** @type {
|
|
205
|
+
/** @type {ResolvedConfig} */
|
|
202
206
|
let vite_config;
|
|
203
207
|
|
|
204
|
-
/** @type {
|
|
208
|
+
/** @type {ConfigEnv} */
|
|
205
209
|
let vite_config_env;
|
|
206
210
|
|
|
207
211
|
/** @type {boolean} */
|
|
@@ -213,7 +217,7 @@ async function kit({ svelte_config }) {
|
|
|
213
217
|
/** @type {() => Promise<void>} */
|
|
214
218
|
let finalise;
|
|
215
219
|
|
|
216
|
-
/** @type {
|
|
220
|
+
/** @type {UserConfig} */
|
|
217
221
|
let initial_config;
|
|
218
222
|
|
|
219
223
|
const service_worker_entry_file = resolve_entry(kit.files.serviceWorker);
|
|
@@ -233,7 +237,7 @@ async function kit({ svelte_config }) {
|
|
|
233
237
|
const sourcemapIgnoreList = /** @param {string} relative_path */ (relative_path) =>
|
|
234
238
|
relative_path.includes('node_modules') || relative_path.includes(kit.outDir);
|
|
235
239
|
|
|
236
|
-
/** @type {
|
|
240
|
+
/** @type {Plugin} */
|
|
237
241
|
const plugin_setup = {
|
|
238
242
|
name: 'vite-plugin-sveltekit-setup',
|
|
239
243
|
|
|
@@ -267,7 +271,7 @@ async function kit({ svelte_config }) {
|
|
|
267
271
|
const generated = path.posix.join(kit.outDir, 'generated');
|
|
268
272
|
|
|
269
273
|
// dev and preview config can be shared
|
|
270
|
-
/** @type {
|
|
274
|
+
/** @type {UserConfig} */
|
|
271
275
|
const new_config = {
|
|
272
276
|
resolve: {
|
|
273
277
|
alias: [
|
|
@@ -437,7 +441,7 @@ async function kit({ svelte_config }) {
|
|
|
437
441
|
}
|
|
438
442
|
};
|
|
439
443
|
|
|
440
|
-
/** @type {
|
|
444
|
+
/** @type {Plugin} */
|
|
441
445
|
const plugin_virtual_modules = {
|
|
442
446
|
name: 'vite-plugin-sveltekit-virtual-modules',
|
|
443
447
|
|
|
@@ -561,7 +565,7 @@ async function kit({ svelte_config }) {
|
|
|
561
565
|
/**
|
|
562
566
|
* Ensures that client-side code can't accidentally import server-side code,
|
|
563
567
|
* whether in `*.server.js` files, `$app/server`, `$lib/server`, or `$env/[static|dynamic]/private`
|
|
564
|
-
* @type {
|
|
568
|
+
* @type {Plugin}
|
|
565
569
|
*/
|
|
566
570
|
const plugin_guard = {
|
|
567
571
|
name: 'vite-plugin-sveltekit-guard',
|
|
@@ -668,7 +672,7 @@ async function kit({ svelte_config }) {
|
|
|
668
672
|
}
|
|
669
673
|
};
|
|
670
674
|
|
|
671
|
-
/** @type {
|
|
675
|
+
/** @type {ViteDevServer} */
|
|
672
676
|
let dev_server;
|
|
673
677
|
|
|
674
678
|
/** @type {Array<{ hash: string, file: string }>} */
|
|
@@ -680,7 +684,7 @@ async function kit({ svelte_config }) {
|
|
|
680
684
|
/** @type {Set<string>} Track which remote hashes have already been emitted */
|
|
681
685
|
const emitted_remote_hashes = new Set();
|
|
682
686
|
|
|
683
|
-
/** @type {
|
|
687
|
+
/** @type {Plugin} */
|
|
684
688
|
const plugin_remote = {
|
|
685
689
|
name: 'vite-plugin-sveltekit-remote',
|
|
686
690
|
|
|
@@ -809,7 +813,7 @@ async function kit({ svelte_config }) {
|
|
|
809
813
|
}
|
|
810
814
|
};
|
|
811
815
|
|
|
812
|
-
/** @type {
|
|
816
|
+
/** @type {Plugin} */
|
|
813
817
|
const plugin_compile = {
|
|
814
818
|
name: 'vite-plugin-sveltekit-compile',
|
|
815
819
|
|
|
@@ -821,7 +825,7 @@ async function kit({ svelte_config }) {
|
|
|
821
825
|
// avoids overwriting the base setting that's also set by Vitest
|
|
822
826
|
order: 'pre',
|
|
823
827
|
handler(config) {
|
|
824
|
-
/** @type {
|
|
828
|
+
/** @type {UserConfig} */
|
|
825
829
|
let new_config;
|
|
826
830
|
|
|
827
831
|
const kit_paths_base = kit.paths.base || '/';
|
|
@@ -1063,13 +1067,13 @@ async function kit({ svelte_config }) {
|
|
|
1063
1067
|
*/
|
|
1064
1068
|
writeBundle: {
|
|
1065
1069
|
sequential: true,
|
|
1066
|
-
async handler(_options) {
|
|
1070
|
+
async handler(_options, server_bundle) {
|
|
1067
1071
|
if (secondary_build_started) return; // only run this once
|
|
1068
1072
|
|
|
1069
1073
|
const verbose = vite_config.logLevel === 'info';
|
|
1070
1074
|
const log = logger({ verbose });
|
|
1071
1075
|
|
|
1072
|
-
/** @type {
|
|
1076
|
+
/** @type {Manifest} */
|
|
1073
1077
|
const server_manifest = JSON.parse(read(`${out}/server/.vite/manifest.json`));
|
|
1074
1078
|
|
|
1075
1079
|
/** @type {import('types').BuildData} */
|
|
@@ -1193,7 +1197,7 @@ async function kit({ svelte_config }) {
|
|
|
1193
1197
|
}
|
|
1194
1198
|
}
|
|
1195
1199
|
|
|
1196
|
-
/** @type {
|
|
1200
|
+
/** @type {Manifest} */
|
|
1197
1201
|
const client_manifest = JSON.parse(read(`${out}/client/.vite/manifest.json`));
|
|
1198
1202
|
|
|
1199
1203
|
/**
|
|
@@ -1318,6 +1322,15 @@ async function kit({ svelte_config }) {
|
|
|
1318
1322
|
env: { ...env.private, ...env.public }
|
|
1319
1323
|
});
|
|
1320
1324
|
|
|
1325
|
+
await treeshake_prerendered_remotes(
|
|
1326
|
+
out,
|
|
1327
|
+
remotes,
|
|
1328
|
+
metadata,
|
|
1329
|
+
cwd,
|
|
1330
|
+
server_bundle,
|
|
1331
|
+
vite_config.build.sourcemap
|
|
1332
|
+
);
|
|
1333
|
+
|
|
1321
1334
|
// generate a new manifest that doesn't include prerendered pages
|
|
1322
1335
|
fs.writeFileSync(
|
|
1323
1336
|
`${out}/server/manifest.js`,
|
|
@@ -1411,8 +1424,8 @@ async function kit({ svelte_config }) {
|
|
|
1411
1424
|
}
|
|
1412
1425
|
|
|
1413
1426
|
/**
|
|
1414
|
-
* @param {
|
|
1415
|
-
* @param {
|
|
1427
|
+
* @param {UserConfig} config
|
|
1428
|
+
* @param {UserConfig} resolved_config
|
|
1416
1429
|
*/
|
|
1417
1430
|
function warn_overridden_config(config, resolved_config) {
|
|
1418
1431
|
const overridden = find_overridden_config(config, resolved_config, enforced_config, '', []);
|