@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.20
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 +58 -36
- package/src/cli.js +14 -11
- package/src/constants.js +6 -1
- package/src/core/adapt/builder.js +54 -60
- package/src/core/adapt/index.js +2 -5
- package/src/core/config/index.js +141 -76
- package/src/core/config/options.js +260 -260
- package/src/core/config/types.d.ts +1 -1
- package/src/core/env.js +143 -13
- package/src/core/generate_manifest/index.js +18 -15
- package/src/core/postbuild/analyse.js +7 -19
- package/src/core/postbuild/crawl.js +22 -6
- package/src/core/postbuild/entities.js +8 -2
- package/src/core/postbuild/fallback.js +4 -2
- package/src/core/postbuild/prerender.js +193 -69
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/create_manifest_data/conflict.js +1 -1
- package/src/core/sync/create_manifest_data/index.js +72 -52
- package/src/core/sync/sync.js +35 -26
- package/src/core/sync/ts.js +1 -1
- package/src/core/sync/utils.js +22 -2
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +105 -56
- package/src/core/sync/write_client_manifest.js +13 -28
- package/src/core/sync/write_env.js +7 -5
- package/src/core/sync/write_server.js +25 -33
- package/src/core/sync/write_tsconfig/index.js +274 -0
- package/src/core/sync/write_tsconfig/test-app/package.json +7 -0
- package/src/core/sync/write_tsconfig/utils.js +77 -0
- package/src/core/sync/write_tsconfig/validate.js +128 -0
- package/src/core/sync/write_types/index.js +119 -116
- package/src/core/utils.js +30 -5
- package/src/exports/env/index.js +77 -0
- package/src/exports/env/public.d.ts +55 -0
- package/src/exports/hooks/index.js +3 -9
- package/src/exports/hooks/public.d.ts +194 -0
- package/src/exports/hooks/sequence.js +9 -6
- package/src/exports/index.js +53 -20
- package/src/exports/internal/client.js +5 -0
- package/src/exports/internal/env.js +8 -5
- package/src/exports/internal/index.js +1 -90
- package/src/exports/internal/{event.js → server/event.js} +1 -2
- package/src/exports/internal/server/index.js +37 -0
- package/src/exports/internal/server/telemetry.js +95 -0
- package/src/exports/internal/shared.js +90 -0
- package/src/exports/node/index.js +64 -22
- package/src/exports/params/index.js +70 -0
- package/src/exports/params/public.d.ts +63 -0
- package/src/exports/public.d.ts +219 -1118
- package/src/exports/url.js +86 -0
- package/src/exports/vite/build/build_server.js +53 -64
- package/src/exports/vite/build/remote.js +24 -19
- package/src/exports/vite/build/utils.js +0 -8
- package/src/exports/vite/dev/index.js +199 -125
- package/src/exports/vite/index.js +1514 -833
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +32 -24
- package/src/exports/vite/utils.js +83 -45
- package/src/pathname.js +55 -0
- package/src/runner.js +15 -0
- package/src/runtime/app/env/internal.js +4 -4
- package/src/runtime/app/env/types.d.ts +1 -1
- package/src/runtime/app/environment/index.js +3 -3
- package/src/runtime/app/{forms.js → forms/index.js} +73 -42
- package/src/runtime/app/forms/public.d.ts +2 -0
- package/src/runtime/app/forms/types.d.ts +56 -0
- package/src/runtime/app/internal/transport.js +53 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/{navigation.js → navigation/index.js} +2 -1
- package/src/runtime/app/navigation/public.d.ts +237 -0
- package/src/runtime/app/paths/client.js +37 -37
- package/src/runtime/app/paths/index.js +1 -1
- package/src/runtime/app/paths/internal/client.js +34 -2
- package/src/runtime/app/paths/internal/server.js +6 -23
- package/src/runtime/app/paths/internal.d.ts +3 -0
- package/src/runtime/app/paths/public.d.ts +1 -29
- package/src/runtime/app/paths/server.js +36 -17
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +2 -2
- package/src/runtime/app/server/public.d.ts +519 -0
- package/src/runtime/app/server/remote/command.js +13 -11
- package/src/runtime/app/server/remote/form.js +61 -39
- package/src/runtime/app/server/remote/prerender.js +45 -45
- package/src/runtime/app/server/remote/query.js +106 -108
- package/src/runtime/app/server/remote/requested.js +27 -19
- package/src/runtime/app/server/remote/shared.js +75 -75
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/client.js +4 -2
- package/src/runtime/app/state/index.js +7 -5
- package/src/runtime/app/state/public.d.ts +72 -0
- package/src/runtime/app/state/server.js +3 -0
- package/src/runtime/app/stores.js +15 -78
- package/src/runtime/client/bundle.js +1 -1
- package/src/runtime/client/client-entry.js +3 -0
- package/src/runtime/client/client.js +1336 -648
- package/src/runtime/client/constants.js +3 -6
- package/src/runtime/client/entry.js +24 -3
- package/src/runtime/client/fetcher.js +25 -25
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/parse.js +1 -1
- package/src/runtime/client/payload.js +17 -0
- package/src/runtime/client/remote-functions/cache.svelte.js +3 -1
- package/src/runtime/client/remote-functions/command.svelte.js +37 -61
- package/src/runtime/client/remote-functions/form.svelte.js +267 -178
- package/src/runtime/client/remote-functions/prerender.svelte.js +32 -11
- package/src/runtime/client/remote-functions/query/index.js +10 -17
- package/src/runtime/client/remote-functions/query/instance.svelte.js +64 -18
- package/src/runtime/client/remote-functions/query/proxy.js +5 -5
- package/src/runtime/client/remote-functions/query-batch.svelte.js +61 -70
- package/src/runtime/client/remote-functions/query-live/index.js +1 -1
- package/src/runtime/client/remote-functions/query-live/instance.svelte.js +63 -21
- package/src/runtime/client/remote-functions/query-live/iterator.js +15 -12
- package/src/runtime/client/remote-functions/query-live/proxy.js +2 -12
- package/src/runtime/client/remote-functions/shared.svelte.js +90 -65
- package/src/runtime/client/snapshots.js +147 -0
- package/src/runtime/client/state.svelte.js +94 -55
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/client/types.d.ts +13 -9
- package/src/runtime/client/utils.js +22 -110
- package/src/runtime/components/root.svelte +56 -0
- package/src/runtime/env/dynamic/private.js +7 -0
- package/src/runtime/env/dynamic/public.js +7 -0
- package/src/runtime/env/static/private.js +6 -0
- package/src/runtime/env/static/public.js +6 -0
- package/src/runtime/form-utils.js +172 -61
- package/src/runtime/pathname.js +20 -32
- package/src/runtime/props.svelte.js +72 -0
- package/src/runtime/server/constants.js +0 -3
- package/src/runtime/server/cookie.js +70 -53
- package/src/runtime/server/csrf.js +65 -0
- package/src/runtime/server/data/index.js +48 -52
- package/src/runtime/server/dev.js +22 -0
- package/src/runtime/server/endpoint.js +3 -4
- package/src/runtime/server/env_module.js +0 -5
- package/src/runtime/server/errors.js +160 -0
- package/src/runtime/server/fetch.js +31 -38
- package/src/runtime/server/index.js +90 -64
- package/src/runtime/server/internal.js +71 -0
- package/src/runtime/server/page/actions.js +84 -64
- package/src/runtime/server/page/crypto.js +2 -2
- package/src/runtime/server/page/csp.js +88 -104
- package/src/runtime/server/page/data_serializer.js +22 -23
- package/src/runtime/server/page/index.js +35 -53
- package/src/runtime/server/page/load_data.js +47 -54
- package/src/runtime/server/page/render.js +172 -238
- package/src/runtime/server/page/respond_with_error.js +16 -30
- package/src/runtime/server/page/serialize_data.js +2 -13
- package/src/runtime/server/page/server_routing.js +85 -26
- package/src/runtime/server/remote-functions.js +639 -0
- package/src/runtime/server/respond.js +188 -129
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/state.js +53 -0
- package/src/runtime/server/utils.js +12 -154
- package/src/runtime/shared.js +20 -40
- package/src/runtime/utils.js +3 -0
- package/src/types/ambient-private.d.ts +11 -1
- package/src/types/ambient.d.ts +87 -36
- package/src/types/global-private.d.ts +25 -25
- package/src/types/internal.d.ts +160 -150
- package/src/types/private.d.ts +41 -1
- package/src/utils/error.js +28 -4
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/filesystem.js +1 -23
- package/src/utils/fork.js +7 -2
- package/src/utils/hash.js +21 -0
- package/src/utils/http.js +8 -7
- package/src/utils/import.js +9 -2
- package/src/utils/imports.js +83 -0
- package/src/utils/mime.js +9 -0
- package/src/utils/page_nodes.js +6 -7
- package/src/utils/params.js +67 -0
- package/src/utils/regex.js +9 -0
- package/src/utils/routing.js +145 -73
- package/src/utils/shared-iterator.js +5 -0
- package/src/utils/streaming.js +14 -4
- package/src/utils/url.js +33 -2
- package/src/version.js +1 -1
- package/types/index.d.ts +2291 -2135
- package/types/index.d.ts.map +116 -108
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_root.js +0 -148
- package/src/core/sync/write_tsconfig.js +0 -250
- package/src/exports/internal/server.js +0 -22
- package/src/exports/node/polyfills.js +0 -30
- package/src/runtime/server/app.js +0 -9
- package/src/runtime/server/remote.js +0 -457
- package/src/runtime/shared-server.js +0 -7
- package/src/runtime/telemetry/otel.js +0 -21
- package/src/runtime/telemetry/record_span.js +0 -65
- package/src/types/synthetic/$lib.md +0 -5
- /package/src/exports/internal/{remote-functions.js → server/remote-functions.js} +0 -0
- /package/src/{runtime/telemetry/noop.js → telemetry.js} +0 -0
|
@@ -1,63 +1,76 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { KitConfig } from '@sveltejs/kit' */
|
|
2
|
+
/** @import { EnvVarConfig } from '@sveltejs/kit/env' */
|
|
2
3
|
/** @import { Options, SvelteConfig } from '@sveltejs/vite-plugin-svelte' */
|
|
3
4
|
/** @import { PreprocessorGroup } from 'svelte/compiler' */
|
|
4
|
-
/** @import {
|
|
5
|
+
/** @import { Asset, BuildData, ManifestData, Prerendered, RemoteChunk, RemoteInternals, RouteData, ServerMetadata, ValidatedConfig, ValidatedKitConfig } from 'types' */
|
|
6
|
+
/** @import { Manifest, Plugin, ResolvedConfig, Rolldown, UserConfig, ViteDevServer } from 'vite' */
|
|
5
7
|
import fs from 'node:fs';
|
|
6
8
|
import path from 'node:path';
|
|
7
9
|
import process from 'node:process';
|
|
8
10
|
import { styleText } from 'node:util';
|
|
11
|
+
import MagicString from 'magic-string';
|
|
9
12
|
import { loadEnv } from 'vite';
|
|
10
13
|
import { exactRegex, prefixRegex } from 'rolldown/filter';
|
|
11
14
|
|
|
12
|
-
import { copy,
|
|
15
|
+
import { copy, read, resolve_entry } from '../../utils/filesystem.js';
|
|
13
16
|
import { posixify } from '../../utils/os.js';
|
|
17
|
+
import { to_fs } from '../../utils/vite.js';
|
|
14
18
|
import {
|
|
15
19
|
create_sveltekit_env,
|
|
16
20
|
create_sveltekit_env_public,
|
|
17
21
|
resolve_explicit_env_entry,
|
|
22
|
+
create_sveltekit_env_service_worker,
|
|
18
23
|
create_sveltekit_env_service_worker_dev,
|
|
19
|
-
create_sveltekit_env_private
|
|
24
|
+
create_sveltekit_env_private,
|
|
25
|
+
create_exported_declarations
|
|
20
26
|
} from '../../core/env.js';
|
|
21
27
|
import * as sync from '../../core/sync/sync.js';
|
|
22
|
-
import {
|
|
28
|
+
import { load_and_validate_params } from '../../utils/params.js';
|
|
23
29
|
import { runtime_directory, logger } from '../../core/utils.js';
|
|
24
30
|
import { generate_manifest } from '../../core/generate_manifest/index.js';
|
|
25
31
|
import { build_server_nodes } from './build/build_server.js';
|
|
26
|
-
import {
|
|
27
|
-
import { dev } from './dev/index.js';
|
|
32
|
+
import { find_deps, resolve_symlinks } from './build/utils.js';
|
|
33
|
+
import { dev, invalidate_module } from './dev/index.js';
|
|
28
34
|
import { preview } from './preview/index.js';
|
|
29
35
|
import {
|
|
30
36
|
error_for_missing_config,
|
|
31
37
|
get_config_aliases,
|
|
38
|
+
is_remote_module,
|
|
32
39
|
normalize_id,
|
|
33
|
-
|
|
40
|
+
remote_module_pattern,
|
|
41
|
+
server_only_directory_pattern,
|
|
42
|
+
server_only_module_pattern
|
|
34
43
|
} from './utils.js';
|
|
35
44
|
import { stackless } from '../../utils/error.js';
|
|
45
|
+
import { adapt } from '../../core/adapt/index.js';
|
|
36
46
|
import { write_client_manifest } from '../../core/sync/write_client_manifest.js';
|
|
37
47
|
import prerender from '../../core/postbuild/prerender.js';
|
|
38
48
|
import analyse from '../../core/postbuild/analyse.js';
|
|
39
49
|
import { s } from '../../utils/misc.js';
|
|
40
50
|
import { hash } from '../../utils/hash.js';
|
|
41
51
|
import { dedent } from '../../core/sync/utils.js';
|
|
52
|
+
import {
|
|
53
|
+
is_app_route,
|
|
54
|
+
is_endpoint_route,
|
|
55
|
+
is_page_route
|
|
56
|
+
} from '../../core/sync/create_manifest_data/index.js';
|
|
57
|
+
import { get_import_aliases, get_hash_import_keys } from '../../utils/imports.js';
|
|
42
58
|
import {
|
|
43
59
|
app_env_private,
|
|
44
60
|
app_server,
|
|
45
|
-
service_worker,
|
|
46
61
|
sveltekit_env,
|
|
47
62
|
sveltekit_env_private,
|
|
48
63
|
sveltekit_env_service_worker,
|
|
49
|
-
|
|
64
|
+
sveltekit_manifest_data,
|
|
50
65
|
sveltekit_env_public_client,
|
|
51
66
|
sveltekit_env_public_server
|
|
52
67
|
} from './module_ids.js';
|
|
53
68
|
import { import_peer } from '../../utils/import.js';
|
|
54
69
|
import { compact } from '../../utils/array.js';
|
|
55
70
|
import { should_ignore, has_children } from './static_analysis/utils.js';
|
|
56
|
-
import { process_config } from '../../core/config/index.js';
|
|
71
|
+
import { process_config, split_config, validate_config } from '../../core/config/index.js';
|
|
57
72
|
import { treeshake_prerendered_remotes } from './build/remote.js';
|
|
58
|
-
|
|
59
|
-
/** @type {string} */
|
|
60
|
-
let root;
|
|
73
|
+
import { get_runner } from '../../runner.js';
|
|
61
74
|
|
|
62
75
|
/** @type {import('./types.js').EnforcedConfig} */
|
|
63
76
|
const enforced_config = {
|
|
@@ -89,14 +102,28 @@ const enforced_config = {
|
|
|
89
102
|
resolve: {
|
|
90
103
|
alias: {
|
|
91
104
|
$app: true,
|
|
92
|
-
$
|
|
93
|
-
'$service-worker': true
|
|
105
|
+
$env: true
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
108
|
};
|
|
97
109
|
|
|
98
110
|
const options_regex = /(export\s+const\s+(prerender|csr|ssr|trailingSlash))\s*=/s;
|
|
99
111
|
|
|
112
|
+
const removed_modules = [
|
|
113
|
+
{
|
|
114
|
+
name: '$lib',
|
|
115
|
+
pattern: /^\$lib(?:\/.*|\?.*)?$/,
|
|
116
|
+
message:
|
|
117
|
+
"`$lib` has been removed. Use `#lib` instead: https://svelte.dev/docs/kit/$lib. To keep using `$lib`, add `alias: { '$lib': 'src/lib' }` to your SvelteKit config."
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: '$service-worker',
|
|
121
|
+
pattern: /^\$service-worker(?:\?.*)?$/,
|
|
122
|
+
message:
|
|
123
|
+
'`$service-worker` has been removed. Use `immutable`, `assets` and `prerendered` from `$app/manifest`, `version` from `$app/env`, and `resolve(...)` from `$app/paths` instead: https://svelte.dev/docs/kit/$service-worker'
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
|
|
100
127
|
/** @type {Set<string>} */
|
|
101
128
|
const warned = new Set();
|
|
102
129
|
|
|
@@ -112,7 +139,7 @@ const warning_preprocessor = {
|
|
|
112
139
|
const fixed = basename.replace('.svelte', '(.server).js/ts');
|
|
113
140
|
|
|
114
141
|
const message =
|
|
115
|
-
`\n${styleText(['bold', 'red'], path.relative(
|
|
142
|
+
`\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
|
|
116
143
|
`\`${match[1]}\` will be ignored — move it to ${fixed} instead. See https://svelte.dev/docs/kit/page-options for more information.`;
|
|
117
144
|
|
|
118
145
|
if (!warned.has(message)) {
|
|
@@ -129,7 +156,7 @@ const warning_preprocessor = {
|
|
|
129
156
|
|
|
130
157
|
if (basename.startsWith('+layout.') && !has_children(content, true)) {
|
|
131
158
|
const message =
|
|
132
|
-
`\n${styleText(['bold', 'red'], path.relative(
|
|
159
|
+
`\n${styleText(['bold', 'red'], path.relative(process.cwd(), filename))}\n` +
|
|
133
160
|
'`<slot />` or `{@render ...}` tag' +
|
|
134
161
|
' missing — inner content will not be rendered';
|
|
135
162
|
|
|
@@ -146,101 +173,63 @@ let vite_plugin_svelte;
|
|
|
146
173
|
|
|
147
174
|
/**
|
|
148
175
|
* Returns the SvelteKit Vite plugins.
|
|
149
|
-
*
|
|
150
|
-
*
|
|
176
|
+
* Any options that don't belong to SvelteKit are passed through to `vite-plugin-svelte`.
|
|
177
|
+
*
|
|
178
|
+
* Since version 3.0.0 you must pass [configuration](configuration) directly.
|
|
179
|
+
*
|
|
180
|
+
* Since version 2.62.0 you can pass configuration directly, in which case `svelte.config.js` is ignored.
|
|
181
|
+
*
|
|
182
|
+
* @param {KitConfig & Omit<Options, 'onwarn'> & Pick<SvelteConfig, 'vitePlugin'>} [config]
|
|
151
183
|
* @returns {Promise<Plugin[]>}
|
|
152
184
|
*/
|
|
153
185
|
export async function sveltekit(config) {
|
|
154
186
|
const cwd = process.cwd();
|
|
155
187
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (!config) {
|
|
168
|
-
throw new Error(message);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
console.warn(message);
|
|
188
|
+
// any options passed to the plugin that SvelteKit doesn't use itself are
|
|
189
|
+
// forwarded to vite-plugin-svelte, which does its own validation
|
|
190
|
+
const split = split_config(config ?? {});
|
|
191
|
+
const svelte_config = validate_config(split.svelte_config);
|
|
192
|
+
|
|
193
|
+
if (Array.isArray(svelte_config.preprocess)) {
|
|
194
|
+
svelte_config.preprocess.push(warning_preprocessor);
|
|
195
|
+
} else if (svelte_config.preprocess) {
|
|
196
|
+
svelte_config.preprocess = [svelte_config.preprocess, warning_preprocessor];
|
|
197
|
+
} else {
|
|
198
|
+
svelte_config.preprocess = warning_preprocessor;
|
|
172
199
|
}
|
|
173
200
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
201
|
+
vite_plugin_svelte = await import_peer('@sveltejs/vite-plugin-svelte', cwd);
|
|
202
|
+
|
|
203
|
+
/** @type {Partial<Options>} */
|
|
204
|
+
const inline_vps_config = {
|
|
205
|
+
preprocess: svelte_config.preprocess,
|
|
206
|
+
...(svelte_config.vitePlugin ?? {}),
|
|
207
|
+
// pass through any options that SvelteKit doesn't use itself, so that
|
|
208
|
+
// the options SvelteKit manages always take precedence
|
|
209
|
+
...split.vite_plugin_svelte_config,
|
|
210
|
+
// we don't want vite-plugin-svelte to load the svelte.config.js file because
|
|
211
|
+
// we expect options to be passed through the SvelteKit Vite plugin
|
|
178
212
|
configFile: false
|
|
179
213
|
};
|
|
180
214
|
|
|
181
|
-
|
|
215
|
+
// vite-plugin-svelte inline config options need to be added conditionally
|
|
216
|
+
// because passing undefined causes it to crash
|
|
217
|
+
if (svelte_config.extensions) {
|
|
218
|
+
inline_vps_config.extensions = svelte_config.extensions;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (svelte_config.compilerOptions) {
|
|
222
|
+
inline_vps_config.compilerOptions = svelte_config.compilerOptions;
|
|
223
|
+
}
|
|
182
224
|
|
|
183
|
-
return [
|
|
184
|
-
plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }),
|
|
185
|
-
...vite_plugin_svelte.svelte(vite_plugin_svelte_options),
|
|
186
|
-
...kit({
|
|
187
|
-
svelte_config,
|
|
188
|
-
adapter: svelte_config.kit.adapter
|
|
189
|
-
})
|
|
190
|
-
];
|
|
225
|
+
return [...vite_plugin_svelte.svelte(inline_vps_config), ...kit({ svelte_config })];
|
|
191
226
|
}
|
|
192
227
|
|
|
193
|
-
/** @param {
|
|
228
|
+
/** @param {UserConfig | ResolvedConfig} vite_config */
|
|
194
229
|
function resolve_root(vite_config) {
|
|
195
230
|
return posixify(vite_config.root ? path.resolve(vite_config.root) : process.cwd());
|
|
196
231
|
}
|
|
197
232
|
|
|
198
|
-
/**
|
|
199
|
-
* Resolves the Svelte config using the `vite.config.root` setting before any
|
|
200
|
-
* of our other plugins try to access the config objects
|
|
201
|
-
* @param {{
|
|
202
|
-
* vite_plugin_svelte_options: import('@sveltejs/vite-plugin-svelte').Options;
|
|
203
|
-
* svelte_config: import('types').ValidatedConfig;
|
|
204
|
-
* }} options
|
|
205
|
-
* @return {import('vite').Plugin}
|
|
206
|
-
*/
|
|
207
|
-
function plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }) {
|
|
208
|
-
return {
|
|
209
|
-
name: 'vite-plugin-sveltekit-resolve-svelte-config',
|
|
210
|
-
// make sure it runs first
|
|
211
|
-
enforce: 'pre',
|
|
212
|
-
config: {
|
|
213
|
-
order: 'pre',
|
|
214
|
-
handler(config) {
|
|
215
|
-
root = resolve_root(config);
|
|
216
|
-
|
|
217
|
-
/** @type {import('@sveltejs/vite-plugin-svelte').Options['preprocess']} */
|
|
218
|
-
let preprocess = svelte_config.preprocess;
|
|
219
|
-
if (Array.isArray(preprocess)) {
|
|
220
|
-
preprocess = [...preprocess, warning_preprocessor];
|
|
221
|
-
} else if (preprocess) {
|
|
222
|
-
preprocess = [preprocess, warning_preprocessor];
|
|
223
|
-
} else {
|
|
224
|
-
preprocess = warning_preprocessor;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
vite_plugin_svelte_options.extensions = svelte_config.extensions;
|
|
228
|
-
vite_plugin_svelte_options.preprocess = preprocess;
|
|
229
|
-
vite_plugin_svelte_options.onwarn = svelte_config.onwarn;
|
|
230
|
-
vite_plugin_svelte_options.compilerOptions = { ...svelte_config.compilerOptions };
|
|
231
|
-
Object.assign(vite_plugin_svelte_options, svelte_config.vitePlugin);
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
// TODO: do we even need to set `root` based on the final Vite config?
|
|
235
|
-
configResolved: {
|
|
236
|
-
order: 'pre',
|
|
237
|
-
handler(config) {
|
|
238
|
-
root = resolve_root(config);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
233
|
/**
|
|
245
234
|
* Returns the SvelteKit Vite plugin. Vite executes Rolldown hooks as well as some of its own.
|
|
246
235
|
* Background reading is available at:
|
|
@@ -252,15 +241,20 @@ function plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }) {
|
|
|
252
241
|
* - https://rolldown.rs/apis/plugin-api#output-generation-hooks
|
|
253
242
|
*
|
|
254
243
|
* @param {object} opts
|
|
255
|
-
* @param {
|
|
256
|
-
* @
|
|
257
|
-
* @return {import('vite').Plugin[]}
|
|
244
|
+
* @param {ValidatedConfig} opts.svelte_config
|
|
245
|
+
* @return {Plugin[]}
|
|
258
246
|
*/
|
|
259
|
-
function kit({ svelte_config
|
|
247
|
+
function kit({ svelte_config }) {
|
|
260
248
|
/** @type {typeof import('vite')} */
|
|
261
249
|
let vite;
|
|
262
250
|
|
|
263
|
-
/**
|
|
251
|
+
/**
|
|
252
|
+
* The posix-ified root of the project based on the Vite configuration.
|
|
253
|
+
* @type {string}
|
|
254
|
+
*/
|
|
255
|
+
let root;
|
|
256
|
+
|
|
257
|
+
/** @type {ValidatedKitConfig} */
|
|
264
258
|
let kit;
|
|
265
259
|
/** @type {string} `kit.outDir` but posix-ified */
|
|
266
260
|
let out_dir;
|
|
@@ -279,45 +273,86 @@ function kit({ svelte_config, adapter }) {
|
|
|
279
273
|
/** @type {Record<string, string>} */
|
|
280
274
|
let env;
|
|
281
275
|
|
|
282
|
-
/** @type {
|
|
276
|
+
/** @type {ManifestData} */
|
|
283
277
|
let manifest_data;
|
|
284
278
|
|
|
285
|
-
/** @type {
|
|
286
|
-
let build_metadata =
|
|
279
|
+
/** @type {ServerMetadata | null} set at build time once analysis has finished */
|
|
280
|
+
let build_metadata = null;
|
|
287
281
|
|
|
288
282
|
/** @type {UserConfig} */
|
|
289
283
|
let initial_config;
|
|
290
284
|
|
|
291
285
|
/** @type {string | null} */
|
|
292
|
-
let service_worker_entry_file
|
|
293
|
-
/** @type {import('node:path').ParsedPath} */
|
|
294
|
-
let parsed_service_worker;
|
|
295
|
-
|
|
286
|
+
let service_worker_entry_file;
|
|
296
287
|
/** @type {string} */
|
|
297
288
|
let normalized_cwd;
|
|
298
|
-
/** @type {string} */
|
|
299
|
-
let
|
|
289
|
+
/** @type {Array<{ alias: string, path: string }>} */
|
|
290
|
+
let normalized_aliases;
|
|
300
291
|
/** @type {string} */
|
|
301
292
|
let normalized_node_modules;
|
|
293
|
+
/** @type {string} */
|
|
294
|
+
let normalized_routes;
|
|
295
|
+
/** @type {string} */
|
|
296
|
+
let normalized_assets;
|
|
302
297
|
/**
|
|
303
298
|
* A map showing which features (such as `$app/server:read`) are defined
|
|
304
299
|
* in which chunks, so that we can later determine which routes use which features
|
|
305
300
|
* @type {Record<string, string[]>}
|
|
306
301
|
*/
|
|
307
|
-
|
|
302
|
+
let tracked_features = {};
|
|
308
303
|
|
|
309
304
|
const sourcemapIgnoreList = /** @param {string} relative_path */ (relative_path) =>
|
|
310
305
|
relative_path.includes('node_modules') || relative_path.includes(kit.outDir);
|
|
311
306
|
|
|
307
|
+
/** @type {string} name for `globalThis.__sveltekit_xxx` */
|
|
308
|
+
let kit_global;
|
|
309
|
+
|
|
310
|
+
/** @type {Plugin} */
|
|
311
|
+
const plugin_resolve_root = {
|
|
312
|
+
name: 'vite-plugin-sveltekit-resolve-root',
|
|
313
|
+
// make sure it runs first
|
|
314
|
+
enforce: 'pre',
|
|
315
|
+
config: {
|
|
316
|
+
order: 'pre',
|
|
317
|
+
handler(config) {
|
|
318
|
+
root = resolve_root(config);
|
|
319
|
+
|
|
320
|
+
for (const file of ['svelte.config.js', 'svelte.config.ts']) {
|
|
321
|
+
if (fs.existsSync(path.join(root, file))) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`${file} is no longer used. Please pass configuration via the \`sveltekit(...)\` plugin in your Vite config.`
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
|
|
312
331
|
/** @type {Plugin} */
|
|
313
332
|
const plugin_setup = {
|
|
314
333
|
name: 'vite-plugin-sveltekit-setup',
|
|
315
334
|
api: {
|
|
316
335
|
options: svelte_config
|
|
317
336
|
},
|
|
337
|
+
resolveId: {
|
|
338
|
+
filter: { id: removed_modules.map(({ pattern }) => pattern) },
|
|
339
|
+
async handler(id, importer, options) {
|
|
340
|
+
const resolved = await this.resolve(id, importer, { ...options, skipSelf: true });
|
|
341
|
+
if (resolved) return resolved;
|
|
318
342
|
|
|
319
|
-
|
|
320
|
-
|
|
343
|
+
const aliases = svelte_config.kit.alias;
|
|
344
|
+
for (const { name, pattern, message } of removed_modules) {
|
|
345
|
+
if (!pattern.test(id)) continue;
|
|
346
|
+
|
|
347
|
+
// If the user re-added an alias for this module (as the migration message
|
|
348
|
+
// suggests), a failed resolution means a genuine missing file rather than
|
|
349
|
+
// use of the removed module. Let Vite report the real "not found" error
|
|
350
|
+
// instead of the misleading migration message.
|
|
351
|
+
if (name in aliases || `${name}/*` in aliases) return;
|
|
352
|
+
|
|
353
|
+
throw stackless(message);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
321
356
|
},
|
|
322
357
|
|
|
323
358
|
/**
|
|
@@ -330,32 +365,56 @@ function kit({ svelte_config, adapter }) {
|
|
|
330
365
|
initial_config = config;
|
|
331
366
|
is_build = config_env.command === 'build';
|
|
332
367
|
|
|
333
|
-
({ kit } = svelte_config);
|
|
368
|
+
({ kit } = process_config(svelte_config, root));
|
|
334
369
|
out_dir = posixify(kit.outDir);
|
|
335
370
|
out = `${out_dir}/output`;
|
|
336
371
|
|
|
337
372
|
version_hash = hash(kit.version.name);
|
|
338
373
|
|
|
339
|
-
|
|
374
|
+
kit_global = is_build
|
|
375
|
+
? `globalThis.__sveltekit_${version_hash}`
|
|
376
|
+
: 'globalThis.__sveltekit_dev';
|
|
340
377
|
|
|
341
|
-
|
|
342
|
-
parsed_service_worker = path.parse(kit.files.serviceWorker);
|
|
378
|
+
env = loadEnv(config_env.mode, kit.env.dir, '');
|
|
343
379
|
|
|
344
380
|
vite = await import_peer('vite', root);
|
|
345
381
|
|
|
346
382
|
normalized_cwd = vite.normalizePath(root);
|
|
347
|
-
|
|
383
|
+
normalized_aliases = get_import_aliases(root, vite.normalizePath.bind(vite));
|
|
348
384
|
normalized_node_modules = vite.normalizePath(path.resolve(root, 'node_modules'));
|
|
385
|
+
normalized_routes = vite.normalizePath(path.resolve(root, kit.files.routes));
|
|
386
|
+
normalized_assets = vite.normalizePath(path.resolve(root, kit.files.assets));
|
|
387
|
+
|
|
388
|
+
// Add `#`-prefixed import keys to the enforced config so users are warned
|
|
389
|
+
// if they try to set them in their Vite config's resolve.alias
|
|
390
|
+
const enforced_alias = /** @type {Record<string, true>} */ (
|
|
391
|
+
/** @type {any} */ (enforced_config.resolve).alias
|
|
392
|
+
);
|
|
393
|
+
for (const key of get_hash_import_keys(root)) {
|
|
394
|
+
enforced_alias[key] = true;
|
|
395
|
+
}
|
|
349
396
|
|
|
350
397
|
const allow = new Set([
|
|
351
|
-
kit.files.lib,
|
|
352
398
|
kit.files.routes,
|
|
399
|
+
kit.files.src,
|
|
353
400
|
kit.outDir,
|
|
354
401
|
path.resolve(root, kit.files.src),
|
|
355
402
|
path.resolve(root, 'node_modules'),
|
|
356
|
-
|
|
403
|
+
// ensures that the client entry is served even if it's located outside
|
|
404
|
+
// the local node_modules, such as the pnpm global virtual store
|
|
405
|
+
runtime_directory,
|
|
406
|
+
path.resolve('node_modules'),
|
|
407
|
+
// include the directory that contains the workspaces declaration
|
|
408
|
+
// which usually also contains hoisted packages
|
|
409
|
+
// see https://vite.dev/guide/api-javascript#searchforworkspaceroot
|
|
410
|
+
path.resolve(vite.searchForWorkspaceRoot(process.cwd()), 'node_modules')
|
|
357
411
|
]);
|
|
358
412
|
|
|
413
|
+
// Add directories from `#`-prefixed package.json imports to the allow list
|
|
414
|
+
for (const { path: alias_path } of normalized_aliases) {
|
|
415
|
+
allow.add(alias_path);
|
|
416
|
+
}
|
|
417
|
+
|
|
359
418
|
// We can only add directories to the allow list, so we find out
|
|
360
419
|
// if there's a client hooks file and pass its directory
|
|
361
420
|
const client_hooks = resolve_entry(kit.files.hooks.client);
|
|
@@ -366,10 +425,23 @@ function kit({ svelte_config, adapter }) {
|
|
|
366
425
|
// dev and preview config can be shared
|
|
367
426
|
/** @type {UserConfig} */
|
|
368
427
|
const new_config = {
|
|
428
|
+
environments: {
|
|
429
|
+
ssr: {
|
|
430
|
+
build: {
|
|
431
|
+
sourcemap:
|
|
432
|
+
config.environments?.ssr?.build?.sourcemap ?? config.build?.sourcemap ?? true
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
},
|
|
369
436
|
resolve: {
|
|
370
437
|
alias: [
|
|
371
438
|
{ find: '__SERVER__', replacement: `${generated}/server` },
|
|
372
439
|
{ find: '$app', replacement: `${runtime_directory}/app` },
|
|
440
|
+
{ find: '$env', replacement: `${runtime_directory}/env` },
|
|
441
|
+
{
|
|
442
|
+
find: '__sveltekit/server',
|
|
443
|
+
replacement: `${runtime_directory}/server/internal.js`
|
|
444
|
+
},
|
|
373
445
|
...get_config_aliases(kit, root)
|
|
374
446
|
]
|
|
375
447
|
},
|
|
@@ -381,7 +453,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
381
453
|
sourcemapIgnoreList,
|
|
382
454
|
watch: {
|
|
383
455
|
ignored: [
|
|
384
|
-
// Ignore all siblings of config.
|
|
456
|
+
// Ignore all siblings of config.outDir/generated
|
|
385
457
|
`${out_dir}/!(generated)`
|
|
386
458
|
]
|
|
387
459
|
}
|
|
@@ -402,7 +474,9 @@ function kit({ svelte_config, adapter }) {
|
|
|
402
474
|
// this does not affect app code, just handling of imported libraries that use $app or $env
|
|
403
475
|
'$app',
|
|
404
476
|
'$env'
|
|
405
|
-
]
|
|
477
|
+
],
|
|
478
|
+
// avoid Vite dev server reloading the first time a page is requested
|
|
479
|
+
include: ['@sveltejs/kit > devalue', '@sveltejs/kit > esm-env']
|
|
406
480
|
},
|
|
407
481
|
ssr: {
|
|
408
482
|
noExternal: [
|
|
@@ -421,30 +495,34 @@ function kit({ svelte_config, adapter }) {
|
|
|
421
495
|
}
|
|
422
496
|
};
|
|
423
497
|
|
|
498
|
+
// externalize .remote.js files to stop dependency tracing during prebundling
|
|
424
499
|
if (kit.experimental.remoteFunctions) {
|
|
425
|
-
// treat .remote.js files as empty for the purposes of prebundling
|
|
426
|
-
const remote_id_filter = new RegExp(
|
|
427
|
-
`.remote(${kit.moduleExtensions.join('|')})$`.replaceAll('.', '\\.')
|
|
428
|
-
);
|
|
429
500
|
// @ts-expect-error optimizeDeps is already set above
|
|
430
501
|
new_config.optimizeDeps.rolldownOptions ??= {};
|
|
431
502
|
// @ts-expect-error
|
|
432
503
|
new_config.optimizeDeps.rolldownOptions.plugins ??= [];
|
|
433
504
|
// @ts-expect-error
|
|
434
|
-
new_config.optimizeDeps.rolldownOptions.plugins.push(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
505
|
+
new_config.optimizeDeps.rolldownOptions.plugins.push(
|
|
506
|
+
/** @type {Rolldown.Plugin} */ ({
|
|
507
|
+
name: 'vite-plugin-sveltekit-setup:optimize-remote-functions',
|
|
508
|
+
resolveId: {
|
|
509
|
+
filter: { id: remote_module_pattern },
|
|
510
|
+
async handler(id, importer) {
|
|
511
|
+
const resolved = await this.resolve(id, importer, { skipSelf: true });
|
|
512
|
+
if (!resolved) return { id, external: true };
|
|
513
|
+
if (!is_remote_module(resolved.id)) return;
|
|
514
|
+
// a servable /@fs url; 'absolute' stops rolldown relativizing it in the deps bundle
|
|
515
|
+
return { id: to_fs(resolved.id), external: 'absolute' };
|
|
516
|
+
}
|
|
440
517
|
}
|
|
441
|
-
}
|
|
442
|
-
|
|
518
|
+
})
|
|
519
|
+
);
|
|
443
520
|
}
|
|
444
521
|
|
|
445
522
|
const define = {
|
|
446
|
-
__SVELTEKIT_APP_DIR__: s(kit.appDir),
|
|
523
|
+
__SVELTEKIT_APP_DIR__: s(posixify(kit.appDir)),
|
|
447
524
|
__SVELTEKIT_APP_VERSION__: s(kit.version.name),
|
|
525
|
+
__SVELTEKIT_APP_VERSION_CHECKS_ENABLED__: s(kit.output.bundleStrategy !== 'inline'),
|
|
448
526
|
__SVELTEKIT_EMBEDDED__: s(kit.embedded),
|
|
449
527
|
__SVELTEKIT_FORK_PRELOADS__: s(kit.experimental.forkPreloads),
|
|
450
528
|
__SVELTEKIT_PATHS_ASSETS__: s(kit.paths.assets),
|
|
@@ -452,16 +530,17 @@ function kit({ svelte_config, adapter }) {
|
|
|
452
530
|
__SVELTEKIT_PATHS_RELATIVE__: s(kit.paths.relative),
|
|
453
531
|
__SVELTEKIT_CLIENT_ROUTING__: s(kit.router.resolution === 'client'),
|
|
454
532
|
__SVELTEKIT_HASH_ROUTING__: s(kit.router.type === 'hash'),
|
|
455
|
-
__SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.
|
|
456
|
-
|
|
457
|
-
|
|
533
|
+
__SVELTEKIT_SERVER_TRACING_ENABLED__: s(kit.tracing.server),
|
|
534
|
+
__SVELTEKIT_SUPPORTS_ASYNC__: s(
|
|
535
|
+
svelte_config.compilerOptions?.experimental?.async ?? false
|
|
536
|
+
),
|
|
458
537
|
__SVELTEKIT_DEV__: s(!is_build)
|
|
459
538
|
};
|
|
460
539
|
|
|
461
540
|
if (is_build) {
|
|
462
541
|
new_config.define = {
|
|
463
542
|
...define,
|
|
464
|
-
__SVELTEKIT_ADAPTER_NAME__: s(adapter?.name),
|
|
543
|
+
__SVELTEKIT_ADAPTER_NAME__: s(kit.adapter?.name),
|
|
465
544
|
__SVELTEKIT_APP_VERSION_FILE__: s(`${kit.appDir}/version.json`),
|
|
466
545
|
__SVELTEKIT_APP_VERSION_POLL_INTERVAL__: s(kit.version.pollInterval)
|
|
467
546
|
};
|
|
@@ -471,18 +550,44 @@ function kit({ svelte_config, adapter }) {
|
|
|
471
550
|
new_config.define = {
|
|
472
551
|
...define,
|
|
473
552
|
__SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0',
|
|
474
|
-
__SVELTEKIT_PAYLOAD__: '
|
|
553
|
+
__SVELTEKIT_PAYLOAD__: kit_global, // only relevant when bundleStrategy !== 'split'
|
|
475
554
|
__SVELTEKIT_HAS_SERVER_LOAD__: 'true',
|
|
476
555
|
__SVELTEKIT_HAS_UNIVERSAL_LOAD__: 'true'
|
|
477
556
|
};
|
|
478
557
|
|
|
479
558
|
// These Kit dependencies are packaged as CommonJS, which means they must always be externalized.
|
|
480
559
|
// Without this, the tests will still pass but `pnpm dev` will fail in projects that link `@sveltejs/kit`.
|
|
481
|
-
|
|
482
|
-
|
|
560
|
+
//
|
|
561
|
+
// `@opentelemetry/api` must be externalized so that `instrumentation.server.js` and the
|
|
562
|
+
// SvelteKit runtime share a single instance of the module (the global tracer/propagation
|
|
563
|
+
// is set on that instance — two bundled copies would mean instrumentation hooks are
|
|
564
|
+
// invisible to the runtime). Externalizing also prevents the bundler from colocating
|
|
565
|
+
// `@opentelemetry/api` into a shared chunk that also contains application modules, which
|
|
566
|
+
// would cause those modules to be evaluated before `Server.init()` sets env vars — see
|
|
567
|
+
// https://github.com/sveltejs/kit/issues/16288
|
|
568
|
+
/** @type {NonNullable<UserConfig['ssr']>} */ (new_config.ssr).external = [
|
|
569
|
+
'cookie',
|
|
570
|
+
'@opentelemetry/api'
|
|
483
571
|
];
|
|
484
572
|
}
|
|
485
573
|
|
|
574
|
+
// Vite's `define` is a compile-time text replacement, but Vitest strips
|
|
575
|
+
// user `define` from the server config and reinstalls the values only as
|
|
576
|
+
// `globalThis` properties inside test workers, so anything
|
|
577
|
+
// that runs outside of a test will freak out over
|
|
578
|
+
// them not being defined
|
|
579
|
+
if (process.env.VITEST === 'true') {
|
|
580
|
+
for (const key in new_config.define) {
|
|
581
|
+
const value = new_config.define[key];
|
|
582
|
+
try {
|
|
583
|
+
/** @type {Record<string, any>} */ (globalThis)[key] = JSON.parse(value);
|
|
584
|
+
} catch {
|
|
585
|
+
// `kit_global` isn't JSON, so don't try to parse it. We may one day
|
|
586
|
+
// need to define it in Vitest somehow but for now, ignore it
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
486
591
|
warn_overridden_config(config, new_config);
|
|
487
592
|
|
|
488
593
|
return new_config;
|
|
@@ -494,6 +599,24 @@ function kit({ svelte_config, adapter }) {
|
|
|
494
599
|
*/
|
|
495
600
|
configResolved(config) {
|
|
496
601
|
vite_config = config;
|
|
602
|
+
|
|
603
|
+
const unsupported_plugins = vite_config.plugins.filter((plugin) => plugin.transformIndexHtml);
|
|
604
|
+
if (unsupported_plugins.length) {
|
|
605
|
+
const verbose = vite_config.logLevel === 'info';
|
|
606
|
+
const log = logger({ verbose });
|
|
607
|
+
|
|
608
|
+
const list = unsupported_plugins
|
|
609
|
+
.map((plugin) => ` - ${plugin.name || '(missing plugin name)'}`)
|
|
610
|
+
.join('\n');
|
|
611
|
+
|
|
612
|
+
log.warn(
|
|
613
|
+
dedent`
|
|
614
|
+
The following plugins may not work correctly because they use the \`transformIndexHtml\` hook which is not supported:
|
|
615
|
+
|
|
616
|
+
${list}
|
|
617
|
+
`
|
|
618
|
+
);
|
|
619
|
+
}
|
|
497
620
|
}
|
|
498
621
|
};
|
|
499
622
|
|
|
@@ -507,13 +630,9 @@ function kit({ svelte_config, adapter }) {
|
|
|
507
630
|
const plugin_virtual_modules = {
|
|
508
631
|
name: 'vite-plugin-sveltekit-virtual-modules',
|
|
509
632
|
|
|
510
|
-
applyToEnvironment(environment) {
|
|
511
|
-
return environment.name !== 'serviceWorker';
|
|
512
|
-
},
|
|
513
|
-
|
|
514
633
|
async configResolved(config) {
|
|
515
634
|
explicit_env_entry = resolve_explicit_env_entry(kit);
|
|
516
|
-
explicit_env_config = await sync.env(kit, explicit_env_entry, config.root, config.mode);
|
|
635
|
+
explicit_env_config = await sync.env(vite, kit, explicit_env_entry, config.root, config.mode);
|
|
517
636
|
},
|
|
518
637
|
|
|
519
638
|
configureServer(server) {
|
|
@@ -527,6 +646,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
527
646
|
if (file === explicit_env_entry || file === resolved) {
|
|
528
647
|
explicit_env_entry = resolved;
|
|
529
648
|
explicit_env_config = await sync.env(
|
|
649
|
+
vite,
|
|
530
650
|
kit,
|
|
531
651
|
explicit_env_entry,
|
|
532
652
|
vite_config.root,
|
|
@@ -534,93 +654,59 @@ function kit({ svelte_config, adapter }) {
|
|
|
534
654
|
);
|
|
535
655
|
|
|
536
656
|
for (const id of [sveltekit_env, sveltekit_env_public_client]) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (module) {
|
|
540
|
-
server.moduleGraph.invalidateModule(module);
|
|
541
|
-
}
|
|
657
|
+
invalidate_module(server, id);
|
|
542
658
|
}
|
|
543
659
|
|
|
544
|
-
server.
|
|
660
|
+
server.hot.send({ type: 'full-reload' });
|
|
545
661
|
}
|
|
546
662
|
});
|
|
547
663
|
},
|
|
548
664
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
}
|
|
665
|
+
applyToEnvironment(environment) {
|
|
666
|
+
return environment.name !== 'serviceWorker';
|
|
667
|
+
},
|
|
553
668
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
const importer_is_service_worker =
|
|
563
|
-
parsed_importer.dir === parsed_service_worker.dir &&
|
|
564
|
-
parsed_importer.name === parsed_service_worker.name;
|
|
565
|
-
|
|
566
|
-
if (
|
|
567
|
-
importer_is_service_worker &&
|
|
568
|
-
id !== '$service-worker' &&
|
|
569
|
-
id !== 'virtual:$app/env/public' &&
|
|
570
|
-
id !== '__sveltekit/env/service-worker'
|
|
571
|
-
) {
|
|
572
|
-
throw new Error(
|
|
573
|
-
`Cannot import ${normalize_id(
|
|
574
|
-
id,
|
|
575
|
-
normalized_lib,
|
|
576
|
-
normalized_cwd
|
|
577
|
-
)} into service-worker code. Only the modules $service-worker and $app/env/public are available in service workers.`
|
|
578
|
-
);
|
|
669
|
+
resolveId: {
|
|
670
|
+
filter: {
|
|
671
|
+
id: [prefixRegex('__sveltekit/')]
|
|
672
|
+
},
|
|
673
|
+
handler(id) {
|
|
674
|
+
if (id === '__sveltekit/manifest') {
|
|
675
|
+
return `${out_dir}/generated/client-optimized/app.js`;
|
|
579
676
|
}
|
|
580
|
-
}
|
|
581
677
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
if (id === '__sveltekit/remote') {
|
|
588
|
-
return `${runtime_directory}/client/remote-functions/index.js`;
|
|
589
|
-
}
|
|
678
|
+
if (id === '__sveltekit/remote') {
|
|
679
|
+
return `${runtime_directory}/client/remote-functions/index.js`;
|
|
680
|
+
}
|
|
590
681
|
|
|
591
|
-
if (id.startsWith('__sveltekit/')) {
|
|
592
682
|
return `\0virtual:${id}`;
|
|
593
683
|
}
|
|
594
684
|
},
|
|
685
|
+
|
|
595
686
|
load: {
|
|
596
687
|
filter: {
|
|
597
688
|
id: [
|
|
598
|
-
exactRegex(service_worker),
|
|
599
689
|
exactRegex(sveltekit_env),
|
|
600
690
|
exactRegex(sveltekit_env_private),
|
|
601
691
|
exactRegex(sveltekit_env_public_client),
|
|
602
692
|
exactRegex(sveltekit_env_public_server),
|
|
603
693
|
exactRegex(sveltekit_env_service_worker),
|
|
604
|
-
exactRegex(
|
|
694
|
+
exactRegex(sveltekit_manifest_data)
|
|
605
695
|
]
|
|
606
696
|
},
|
|
607
697
|
handler(id) {
|
|
608
|
-
const global = is_build
|
|
609
|
-
? `globalThis.__sveltekit_${version_hash}`
|
|
610
|
-
: 'globalThis.__sveltekit_dev';
|
|
611
|
-
|
|
612
698
|
switch (id) {
|
|
613
|
-
case
|
|
614
|
-
return
|
|
699
|
+
case sveltekit_manifest_data:
|
|
700
|
+
return create_manifest_data_module(is_build, manifest_data);
|
|
615
701
|
|
|
616
702
|
case sveltekit_env:
|
|
617
|
-
return create_sveltekit_env(explicit_env_config, env, explicit_env_entry);
|
|
703
|
+
return create_sveltekit_env(explicit_env_config, env, explicit_env_entry, !is_build);
|
|
618
704
|
|
|
619
705
|
case sveltekit_env_public_client:
|
|
620
706
|
return create_sveltekit_env_public(
|
|
621
707
|
explicit_env_config,
|
|
622
708
|
env,
|
|
623
|
-
`
|
|
709
|
+
`import { payload } from ${s(`${runtime_directory}/client/payload.js`)};\nconst env = payload.env;`
|
|
624
710
|
);
|
|
625
711
|
|
|
626
712
|
case sveltekit_env_public_server:
|
|
@@ -634,23 +720,21 @@ function kit({ svelte_config, adapter }) {
|
|
|
634
720
|
return create_sveltekit_env_private(explicit_env_config, env);
|
|
635
721
|
|
|
636
722
|
case sveltekit_env_service_worker:
|
|
637
|
-
return
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
`;
|
|
653
|
-
}
|
|
723
|
+
return is_build
|
|
724
|
+
? create_sveltekit_env_service_worker(
|
|
725
|
+
explicit_env_config,
|
|
726
|
+
env,
|
|
727
|
+
kit.version.name,
|
|
728
|
+
kit_global,
|
|
729
|
+
kit.paths.base,
|
|
730
|
+
kit.appDir
|
|
731
|
+
)
|
|
732
|
+
: create_sveltekit_env_service_worker_dev(
|
|
733
|
+
explicit_env_config,
|
|
734
|
+
env,
|
|
735
|
+
kit.version.name,
|
|
736
|
+
kit_global
|
|
737
|
+
);
|
|
654
738
|
}
|
|
655
739
|
}
|
|
656
740
|
}
|
|
@@ -658,11 +742,10 @@ function kit({ svelte_config, adapter }) {
|
|
|
658
742
|
|
|
659
743
|
/** @type {Map<string, Set<string>>} */
|
|
660
744
|
const import_map = new Map();
|
|
661
|
-
const server_only_pattern = /.*\.server\..+/;
|
|
662
745
|
|
|
663
746
|
/**
|
|
664
747
|
* Ensures that client-side code can't accidentally import server-side code,
|
|
665
|
-
* whether in `*.server.js` files, `$app/server`,
|
|
748
|
+
* whether in `*.server.js` files, `$app/server`, any `/server/` directory, or `$app/env/private`
|
|
666
749
|
* @type {Plugin}
|
|
667
750
|
*/
|
|
668
751
|
const plugin_guard = {
|
|
@@ -673,7 +756,8 @@ function kit({ svelte_config, adapter }) {
|
|
|
673
756
|
enforce: 'pre',
|
|
674
757
|
|
|
675
758
|
applyToEnvironment(environment) {
|
|
676
|
-
|
|
759
|
+
// the import map is only read for client-side violations in `load`, so skip other environments
|
|
760
|
+
return environment.config.consumer === 'client';
|
|
677
761
|
},
|
|
678
762
|
|
|
679
763
|
resolveId: {
|
|
@@ -688,7 +772,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
688
772
|
const resolved = await this.resolve(id, importer, { ...options, skipSelf: true });
|
|
689
773
|
|
|
690
774
|
if (resolved) {
|
|
691
|
-
const normalized = normalize_id(resolved.id,
|
|
775
|
+
const normalized = normalize_id(resolved.id, normalized_aliases, normalized_cwd);
|
|
692
776
|
|
|
693
777
|
let importers = import_map.get(normalized);
|
|
694
778
|
|
|
@@ -697,7 +781,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
697
781
|
import_map.set(normalized, importers);
|
|
698
782
|
}
|
|
699
783
|
|
|
700
|
-
importers.add(normalize_id(importer,
|
|
784
|
+
importers.add(normalize_id(importer, normalized_aliases, normalized_cwd));
|
|
701
785
|
}
|
|
702
786
|
}
|
|
703
787
|
}
|
|
@@ -708,31 +792,29 @@ function kit({ svelte_config, adapter }) {
|
|
|
708
792
|
id: [
|
|
709
793
|
exactRegex(app_server),
|
|
710
794
|
exactRegex(app_env_private),
|
|
711
|
-
|
|
712
|
-
|
|
795
|
+
server_only_module_pattern,
|
|
796
|
+
server_only_directory_pattern
|
|
713
797
|
]
|
|
714
798
|
},
|
|
715
799
|
handler(id) {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
// skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context
|
|
719
|
-
const is_internal =
|
|
720
|
-
id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules);
|
|
721
|
-
|
|
722
|
-
const normalized = normalize_id(id, normalized_lib, normalized_cwd);
|
|
800
|
+
const normalized = normalize_id(id, normalized_aliases, normalized_cwd);
|
|
723
801
|
|
|
724
|
-
|
|
725
|
-
normalized === '$app/env/private' ||
|
|
726
|
-
normalized === '$app/server' ||
|
|
727
|
-
normalized.startsWith('$lib/server/') ||
|
|
728
|
-
(is_internal && server_only_pattern.test(path.basename(id)));
|
|
802
|
+
let is_server_only = normalized === '$app/env/private' || normalized === '$app/server';
|
|
729
803
|
|
|
730
804
|
// skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
805
|
+
if (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules)) {
|
|
806
|
+
// e.g. `server.ts` or `foo.server.ts`
|
|
807
|
+
is_server_only ||= server_only_module_pattern.test(id);
|
|
808
|
+
|
|
809
|
+
// e.g. `server/foo.ts`, unless in `src/routes` or `static`
|
|
810
|
+
is_server_only ||=
|
|
811
|
+
server_only_directory_pattern.test(id) &&
|
|
812
|
+
!id.startsWith(normalized_routes + '/') &&
|
|
813
|
+
!id.startsWith(normalized_assets + '/');
|
|
734
814
|
}
|
|
735
815
|
|
|
816
|
+
if (!is_server_only) return;
|
|
817
|
+
|
|
736
818
|
// in dev, this doesn't exist, so we need to create it
|
|
737
819
|
manifest_data ??= sync.all(svelte_config, root).manifest_data;
|
|
738
820
|
|
|
@@ -746,58 +828,78 @@ function kit({ svelte_config, adapter }) {
|
|
|
746
828
|
if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client);
|
|
747
829
|
if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal);
|
|
748
830
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
let includes_remote_file = false;
|
|
831
|
+
if (service_worker_entry_file) {
|
|
832
|
+
entrypoints.add(posixify(path.relative(root, service_worker_entry_file)));
|
|
833
|
+
}
|
|
753
834
|
|
|
754
|
-
|
|
835
|
+
// Walk up the import graph from the server-only module, looking for a chain
|
|
836
|
+
// that leads back to a client entrypoint. We search all candidates (not just
|
|
837
|
+
// the first) because a module can be imported by both server and client code,
|
|
838
|
+
// and a greedy first-match could follow a server-only branch that never
|
|
839
|
+
// reaches an entrypoint — see https://github.com/sveltejs/kit/issues/16232
|
|
840
|
+
/** @type {Set<string>} */
|
|
841
|
+
const visited = new Set([normalized]);
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* @param {string} current
|
|
845
|
+
* @param {string[]} chain
|
|
846
|
+
* @returns {string[] | null}
|
|
847
|
+
*/
|
|
848
|
+
function find_chain(current, chain) {
|
|
755
849
|
const importers = import_map.get(current);
|
|
756
|
-
if (!importers)
|
|
757
|
-
|
|
758
|
-
const candidates = Array.from(importers).filter((importer) => !chain.includes(importer));
|
|
759
|
-
if (candidates.length === 0) break;
|
|
850
|
+
if (!importers) return null;
|
|
760
851
|
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
return current.endsWith(`.remote${ext}`);
|
|
765
|
-
});
|
|
852
|
+
for (const importer of importers) {
|
|
853
|
+
if (visited.has(importer)) continue;
|
|
854
|
+
visited.add(importer);
|
|
766
855
|
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
.map((id, i) => {
|
|
771
|
-
return `${' '.repeat(i + 1)}${id}`;
|
|
772
|
-
})
|
|
773
|
-
.join(' imports\n');
|
|
774
|
-
|
|
775
|
-
if (includes_remote_file) {
|
|
776
|
-
error_for_missing_config(
|
|
777
|
-
'remote functions',
|
|
778
|
-
'kit.experimental.remoteFunctions',
|
|
779
|
-
'true'
|
|
780
|
-
);
|
|
856
|
+
const next_chain = [...chain, importer];
|
|
857
|
+
if (entrypoints.has(importer)) {
|
|
858
|
+
return next_chain;
|
|
781
859
|
}
|
|
860
|
+
const result = find_chain(importer, next_chain);
|
|
861
|
+
if (result) return result;
|
|
862
|
+
}
|
|
863
|
+
return null;
|
|
864
|
+
}
|
|
782
865
|
|
|
783
|
-
|
|
784
|
-
message += `\n\n${pyramid}`;
|
|
785
|
-
message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`;
|
|
866
|
+
const chain = find_chain(normalized, [normalized]);
|
|
786
867
|
|
|
787
|
-
|
|
868
|
+
if (chain) {
|
|
869
|
+
if (chain.some((id) => remote_module_pattern.test(id))) {
|
|
870
|
+
error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true');
|
|
788
871
|
}
|
|
872
|
+
|
|
873
|
+
const pyramid = chain
|
|
874
|
+
.reverse()
|
|
875
|
+
.map((id, i) => {
|
|
876
|
+
return `${' '.repeat(i + 1)}${id}`;
|
|
877
|
+
})
|
|
878
|
+
.join(' imports\n');
|
|
879
|
+
|
|
880
|
+
let message = `Cannot import ${normalized} into code that runs in the browser, as this could leak sensitive information.`;
|
|
881
|
+
message += `\n\n${pyramid}`;
|
|
882
|
+
message += `\n\nIf you're only using the import as a type, change it to \`import type\`.`;
|
|
883
|
+
|
|
884
|
+
throw stackless(message);
|
|
789
885
|
}
|
|
790
886
|
|
|
791
|
-
|
|
887
|
+
// No chain from this server-only module to a client entrypoint was found —
|
|
888
|
+
// the module is only imported from server code, which is valid.
|
|
792
889
|
}
|
|
890
|
+
},
|
|
891
|
+
|
|
892
|
+
// avoid watch mode rebuilds using stale import map data
|
|
893
|
+
buildEnd() {
|
|
894
|
+
import_map.clear();
|
|
793
895
|
}
|
|
794
896
|
};
|
|
795
897
|
|
|
796
898
|
/** @type {ViteDevServer} */
|
|
797
899
|
let dev_server;
|
|
798
900
|
|
|
799
|
-
/** @type {
|
|
800
|
-
|
|
901
|
+
/** @type {RemoteChunk[]} */
|
|
902
|
+
let remotes = [];
|
|
801
903
|
|
|
802
904
|
/** @type {Map<string, string>} Maps remote hash -> original module id */
|
|
803
905
|
const remote_original_by_hash = new Map();
|
|
@@ -810,7 +912,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
810
912
|
name: 'vite-plugin-sveltekit-remote',
|
|
811
913
|
|
|
812
914
|
applyToEnvironment(environment) {
|
|
813
|
-
return environment.name !== 'serviceWorker';
|
|
915
|
+
return svelte_config.kit.experimental.remoteFunctions && environment.name !== 'serviceWorker';
|
|
814
916
|
},
|
|
815
917
|
|
|
816
918
|
// prevent other plugins from resolving our remote virtual module
|
|
@@ -828,10 +930,6 @@ function kit({ svelte_config, adapter }) {
|
|
|
828
930
|
id: prefixRegex('\0sveltekit-remote:')
|
|
829
931
|
},
|
|
830
932
|
handler(id) {
|
|
831
|
-
if (!kit.experimental.remoteFunctions) {
|
|
832
|
-
return null;
|
|
833
|
-
}
|
|
834
|
-
|
|
835
933
|
// On-the-fly generated entry point for remote file just forwards the original module
|
|
836
934
|
// We're not using manualChunks because it can cause problems with circular dependencies
|
|
837
935
|
// (e.g. https://github.com/sveltejs/kit/issues/14679) and module ordering in general
|
|
@@ -844,234 +942,345 @@ function kit({ svelte_config, adapter }) {
|
|
|
844
942
|
},
|
|
845
943
|
|
|
846
944
|
configureServer(_dev_server) {
|
|
847
|
-
if (!kit.experimental.remoteFunctions) {
|
|
848
|
-
return;
|
|
849
|
-
}
|
|
850
|
-
|
|
851
945
|
dev_server = _dev_server;
|
|
852
946
|
},
|
|
853
947
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
}
|
|
948
|
+
transform: {
|
|
949
|
+
filter: {
|
|
950
|
+
id: remote_module_pattern
|
|
951
|
+
},
|
|
952
|
+
async handler(code, id) {
|
|
953
|
+
if (!is_remote_module(id)) return;
|
|
858
954
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
955
|
+
const file = posixify(path.relative(root, id));
|
|
956
|
+
const remote = {
|
|
957
|
+
hash: hash(file),
|
|
958
|
+
file
|
|
959
|
+
};
|
|
863
960
|
|
|
864
|
-
|
|
865
|
-
const remote = {
|
|
866
|
-
hash: hash(file),
|
|
867
|
-
file
|
|
868
|
-
};
|
|
961
|
+
if (this.environment.name === 'ssr') remotes.push(remote);
|
|
869
962
|
|
|
870
|
-
|
|
963
|
+
if (this.environment.config.consumer !== 'client') {
|
|
964
|
+
// we need to add an `await Promise.resolve()` because if the user imports this function
|
|
965
|
+
// on the client AND in a load function when loading the client module we will trigger
|
|
966
|
+
// an import during dev. During a link preload, the module can be mistakenly
|
|
967
|
+
// loaded and transformed twice and the first time all its exports would be undefined
|
|
968
|
+
// triggering a dev server error. By adding a microtask we ensure that the module is fully loaded
|
|
969
|
+
const ms = new MagicString(code);
|
|
871
970
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
971
|
+
// Extra newlines to prevent syntax errors around missing semicolons or comments
|
|
972
|
+
ms.append(
|
|
973
|
+
'\n\n' +
|
|
974
|
+
dedent`
|
|
975
|
+
import * as $$_self_$$ from './${path.basename(id)}';
|
|
976
|
+
import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal/server';
|
|
878
977
|
|
|
879
|
-
|
|
880
|
-
code +=
|
|
881
|
-
'\n\n' +
|
|
882
|
-
dedent`
|
|
883
|
-
import * as $$_self_$$ from './${path.basename(id)}';
|
|
884
|
-
import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal';
|
|
978
|
+
${dev_server ? 'await Promise.resolve()' : ''}
|
|
885
979
|
|
|
886
|
-
|
|
980
|
+
$$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)});
|
|
887
981
|
|
|
888
|
-
|
|
982
|
+
for (const [name, fn] of Object.entries($$_self_$$)) {
|
|
983
|
+
fn.__.id = ${s(remote.hash)} + '/' + name;
|
|
984
|
+
fn.__.name = name;
|
|
985
|
+
}
|
|
986
|
+
`
|
|
987
|
+
);
|
|
889
988
|
|
|
890
|
-
for
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
type: 'chunk',
|
|
902
|
-
id: `\0sveltekit-remote:${remote.hash}`,
|
|
903
|
-
name: `remote-${remote.hash}`
|
|
904
|
-
});
|
|
905
|
-
emitted_remote_hashes.add(remote.hash);
|
|
989
|
+
// Emit a dedicated entry chunk for this remote in SSR builds (prod only)
|
|
990
|
+
if (!dev_server) {
|
|
991
|
+
remote_original_by_hash.set(remote.hash, id);
|
|
992
|
+
if (!emitted_remote_hashes.has(remote.hash)) {
|
|
993
|
+
this.emitFile({
|
|
994
|
+
type: 'chunk',
|
|
995
|
+
id: `\0sveltekit-remote:${remote.hash}`,
|
|
996
|
+
name: `remote-${remote.hash}`
|
|
997
|
+
});
|
|
998
|
+
emitted_remote_hashes.add(remote.hash);
|
|
999
|
+
}
|
|
906
1000
|
}
|
|
1001
|
+
|
|
1002
|
+
return {
|
|
1003
|
+
code: ms.toString(),
|
|
1004
|
+
map: ms.generateMap({ hires: 'boundary' })
|
|
1005
|
+
};
|
|
907
1006
|
}
|
|
908
1007
|
|
|
909
|
-
|
|
910
|
-
|
|
1008
|
+
// For the client, read the exports and create a new module that only contains fetch functions with the correct metadata
|
|
1009
|
+
|
|
1010
|
+
/** @type {Map<string, RemoteInternals['type']>} */
|
|
1011
|
+
const map = new Map();
|
|
911
1012
|
|
|
912
|
-
|
|
1013
|
+
// in dev, load the server module here (which will result in this hook
|
|
1014
|
+
// being called again with `opts.ssr === true` if the module isn't
|
|
1015
|
+
// already loaded) so we can determine what it exports
|
|
1016
|
+
if (dev_server) {
|
|
1017
|
+
const module = await get_runner(vite, dev_server).import(id);
|
|
913
1018
|
|
|
914
|
-
|
|
915
|
-
|
|
1019
|
+
for (const [name, value] of Object.entries(module)) {
|
|
1020
|
+
const type = value?.__?.type;
|
|
1021
|
+
if (type) {
|
|
1022
|
+
map.set(name, type);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
916
1026
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
1027
|
+
// in prod, we already built and analysed the server code before
|
|
1028
|
+
// building the client code, so `remotes` is populated
|
|
1029
|
+
else if (build_metadata?.remotes) {
|
|
1030
|
+
const exports = build_metadata?.remotes.get(remote.hash);
|
|
1031
|
+
if (!exports) throw new Error('Expected to find metadata for remote file ' + id);
|
|
922
1032
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
if (type) {
|
|
926
|
-
map.set(name, type);
|
|
1033
|
+
for (const [name, value] of exports) {
|
|
1034
|
+
map.set(name, value.type);
|
|
927
1035
|
}
|
|
928
1036
|
}
|
|
929
|
-
}
|
|
930
1037
|
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1038
|
+
const { namespace, declarations, reexports } = create_exported_declarations(
|
|
1039
|
+
map.keys(),
|
|
1040
|
+
(name, ns) => `${ns}.${map.get(name)}('${remote.hash}/${name}')`,
|
|
1041
|
+
'__remote'
|
|
1042
|
+
);
|
|
1043
|
+
|
|
1044
|
+
let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${declarations.join('\n')}`;
|
|
1045
|
+
if (reexports.length > 0) {
|
|
1046
|
+
result += `\nexport { ${reexports.join(', ')} };`;
|
|
1047
|
+
}
|
|
1048
|
+
result += '\n';
|
|
936
1049
|
|
|
937
|
-
|
|
938
|
-
|
|
1050
|
+
if (dev_server) {
|
|
1051
|
+
result += `\nimport.meta.hot?.accept();\n`;
|
|
939
1052
|
}
|
|
1053
|
+
|
|
1054
|
+
return {
|
|
1055
|
+
code: result,
|
|
1056
|
+
map: null
|
|
1057
|
+
};
|
|
940
1058
|
}
|
|
1059
|
+
},
|
|
941
1060
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1061
|
+
buildEnd() {
|
|
1062
|
+
if (this.environment.config.consumer === 'server') {
|
|
1063
|
+
emitted_remote_hashes.clear();
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
};
|
|
945
1067
|
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1068
|
+
/** @type {Plugin} */
|
|
1069
|
+
const plugin_remote_guard = {
|
|
1070
|
+
name: 'vite-plugin-sveltekit-remote-guard',
|
|
949
1071
|
|
|
950
|
-
|
|
1072
|
+
applyToEnvironment() {
|
|
1073
|
+
return !svelte_config.kit.experimental.remoteFunctions;
|
|
1074
|
+
},
|
|
951
1075
|
|
|
952
|
-
|
|
953
|
-
|
|
1076
|
+
transform: {
|
|
1077
|
+
filter: {
|
|
1078
|
+
id: new RegExp(
|
|
1079
|
+
`.remote(${svelte_config.kit.moduleExtensions.join('|')})$`.replaceAll('.', '\\.')
|
|
1080
|
+
)
|
|
1081
|
+
},
|
|
1082
|
+
handler() {
|
|
1083
|
+
error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true');
|
|
954
1084
|
}
|
|
955
|
-
|
|
956
|
-
return {
|
|
957
|
-
code: result
|
|
958
|
-
};
|
|
959
1085
|
}
|
|
960
1086
|
};
|
|
961
1087
|
|
|
962
|
-
/** @type {
|
|
963
|
-
let
|
|
964
|
-
/** @type {
|
|
1088
|
+
/** @type {Manifest} */
|
|
1089
|
+
let vite_server_manifest;
|
|
1090
|
+
/** @type {Manifest | null} */
|
|
1091
|
+
let vite_client_manifest = null;
|
|
1092
|
+
/** @type {Prerendered} */
|
|
965
1093
|
let prerendered;
|
|
966
1094
|
|
|
967
|
-
/** @type {
|
|
968
|
-
let
|
|
969
|
-
/** @type {string} */
|
|
970
|
-
let
|
|
1095
|
+
/** @type {Array<{ path: string }> | null} */
|
|
1096
|
+
let immutable = null;
|
|
1097
|
+
/** @type {string | null} */
|
|
1098
|
+
let manifest_data_code = null;
|
|
971
1099
|
|
|
972
1100
|
/**
|
|
973
1101
|
* Creates the service worker virtual modules
|
|
974
|
-
* @type {
|
|
1102
|
+
* @type {Plugin}
|
|
975
1103
|
*/
|
|
976
1104
|
const plugin_service_worker = {
|
|
977
1105
|
name: 'vite-plugin-sveltekit-service-worker',
|
|
978
1106
|
|
|
1107
|
+
config(config) {
|
|
1108
|
+
service_worker_entry_file = resolve_entry(kit.files.serviceWorker);
|
|
1109
|
+
|
|
1110
|
+
if (!service_worker_entry_file) return;
|
|
1111
|
+
|
|
1112
|
+
service_worker_entry_file = posixify(service_worker_entry_file);
|
|
1113
|
+
|
|
1114
|
+
if (kit.paths.assets) {
|
|
1115
|
+
throw new Error('Cannot use service worker alongside config.paths.assets');
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
const user_service_worker_output_config =
|
|
1119
|
+
config.environments?.serviceWorker?.build?.rolldownOptions?.output;
|
|
1120
|
+
|
|
1121
|
+
/** @type {import('vite').UserConfig} */
|
|
1122
|
+
const new_config = {
|
|
1123
|
+
environments: {
|
|
1124
|
+
serviceWorker: {
|
|
1125
|
+
build: {
|
|
1126
|
+
modulePreload: false,
|
|
1127
|
+
rolldownOptions: {
|
|
1128
|
+
external: [`${kit.paths.base}/${kit.appDir}/env.js`],
|
|
1129
|
+
input: {
|
|
1130
|
+
'service-worker': service_worker_entry_file
|
|
1131
|
+
},
|
|
1132
|
+
output: {
|
|
1133
|
+
format: 'es',
|
|
1134
|
+
entryFileNames: 'service-worker.js',
|
|
1135
|
+
assetFileNames: `${kit.appDir}/immutable/assets/[name].[hash][extname]`,
|
|
1136
|
+
codeSplitting:
|
|
1137
|
+
(Array.isArray(user_service_worker_output_config)
|
|
1138
|
+
? user_service_worker_output_config[0].codeSplitting
|
|
1139
|
+
: user_service_worker_output_config?.codeSplitting) ?? false
|
|
1140
|
+
}
|
|
1141
|
+
},
|
|
1142
|
+
outDir: `${out}/client`,
|
|
1143
|
+
minify: initial_config.build?.minify,
|
|
1144
|
+
// avoid overwriting the client build Vite manifest
|
|
1145
|
+
manifest: '.vite/service-worker-manifest.json'
|
|
1146
|
+
},
|
|
1147
|
+
consumer: 'client'
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
|
|
1152
|
+
warn_overridden_config(config, new_config);
|
|
1153
|
+
|
|
1154
|
+
return new_config;
|
|
1155
|
+
},
|
|
1156
|
+
|
|
1157
|
+
// our serviceWorker environment only exists when building because Vite only
|
|
1158
|
+
// supports the default client environment during development (for now)
|
|
979
1159
|
applyToEnvironment(environment) {
|
|
980
1160
|
return environment.name === 'serviceWorker';
|
|
981
1161
|
},
|
|
982
1162
|
|
|
983
1163
|
resolveId: {
|
|
1164
|
+
filter: {
|
|
1165
|
+
id: [prefixRegex('__sveltekit/')]
|
|
1166
|
+
},
|
|
984
1167
|
handler(id) {
|
|
985
|
-
|
|
986
|
-
// ids with :$ don't work with reverse proxies like nginx
|
|
987
|
-
return `\0virtual:${id.substring(1)}`;
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
if (id.startsWith('__sveltekit')) {
|
|
991
|
-
return `\0virtual:${id}`;
|
|
992
|
-
}
|
|
1168
|
+
return `\0virtual:${id}`;
|
|
993
1169
|
}
|
|
994
1170
|
},
|
|
995
1171
|
|
|
996
|
-
load
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
${Array.from(build)
|
|
1015
|
-
.map((file) => `base + ${s(`/${file}`)}`)
|
|
1016
|
-
.join(',\n')}
|
|
1172
|
+
load: {
|
|
1173
|
+
filter: {
|
|
1174
|
+
id: [
|
|
1175
|
+
exactRegex('\0virtual:app/manifest'),
|
|
1176
|
+
exactRegex(sveltekit_manifest_data),
|
|
1177
|
+
exactRegex(sveltekit_env_service_worker),
|
|
1178
|
+
exactRegex(sveltekit_env_public_client)
|
|
1179
|
+
]
|
|
1180
|
+
},
|
|
1181
|
+
handler(id) {
|
|
1182
|
+
if (!manifest_data_code) {
|
|
1183
|
+
// the client build computes `immutable`, unless it was skipped
|
|
1184
|
+
// because every route has `csr: false`
|
|
1185
|
+
immutable ??= collect_immutable(vite_server_manifest, kit.appDir, new Set());
|
|
1186
|
+
|
|
1187
|
+
manifest_data_code = dedent`
|
|
1188
|
+
export const immutable = [
|
|
1189
|
+
${immutable.map((entry) => s(entry)).join(',\n')}
|
|
1017
1190
|
];
|
|
1018
1191
|
|
|
1019
|
-
export const
|
|
1020
|
-
${manifest_data.assets
|
|
1021
|
-
.filter((asset) => kit.serviceWorker.files(asset.file))
|
|
1022
|
-
.map((asset) => `base + ${s(`/${asset.file}`)}`)
|
|
1023
|
-
.join(',\n')}
|
|
1192
|
+
export const assets = [
|
|
1193
|
+
${stringify_assets(manifest_data.assets)}
|
|
1024
1194
|
];
|
|
1025
1195
|
|
|
1026
1196
|
export const prerendered = [
|
|
1027
|
-
${prerendered.paths.map((path) =>
|
|
1197
|
+
${prerendered.paths.map((path) => s({ path: path.replace(kit.paths.base, '').slice(1) })).join(',\n')}
|
|
1028
1198
|
];
|
|
1029
1199
|
|
|
1030
|
-
export const
|
|
1031
|
-
|
|
1032
|
-
|
|
1200
|
+
export const routes = [
|
|
1201
|
+
${stringify_routes(manifest_data.routes)}
|
|
1202
|
+
];
|
|
1203
|
+
`;
|
|
1204
|
+
}
|
|
1033
1205
|
|
|
1034
|
-
|
|
1206
|
+
if (id === '\0virtual:app/manifest') {
|
|
1207
|
+
return `export { immutable, assets, prerendered, routes } from '__sveltekit/manifest-data';`;
|
|
1208
|
+
}
|
|
1035
1209
|
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1210
|
+
if (id === sveltekit_manifest_data) {
|
|
1211
|
+
return manifest_data_code;
|
|
1212
|
+
}
|
|
1039
1213
|
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1214
|
+
if (id === sveltekit_env_service_worker) {
|
|
1215
|
+
return is_build
|
|
1216
|
+
? create_sveltekit_env_service_worker(
|
|
1217
|
+
explicit_env_config,
|
|
1218
|
+
env,
|
|
1219
|
+
kit.version.name,
|
|
1220
|
+
kit_global,
|
|
1221
|
+
kit.paths.base,
|
|
1222
|
+
kit.appDir
|
|
1223
|
+
)
|
|
1224
|
+
: create_sveltekit_env_service_worker_dev(
|
|
1225
|
+
explicit_env_config,
|
|
1226
|
+
env,
|
|
1227
|
+
kit.version.name,
|
|
1228
|
+
kit_global
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1043
1231
|
|
|
1044
|
-
|
|
1045
|
-
|
|
1232
|
+
if (id === sveltekit_env_public_client) {
|
|
1233
|
+
return create_sveltekit_env_public(
|
|
1234
|
+
explicit_env_config,
|
|
1235
|
+
env,
|
|
1236
|
+
`const env = ${kit_global}.env;`
|
|
1237
|
+
);
|
|
1238
|
+
}
|
|
1046
1239
|
}
|
|
1240
|
+
},
|
|
1047
1241
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1242
|
+
generateBundle(_, bundle) {
|
|
1243
|
+
const invalid_modules = new Set();
|
|
1244
|
+
const modules = new Map([
|
|
1245
|
+
[`${runtime_directory}/app/forms/index.js`, '$app/forms'],
|
|
1246
|
+
[`${runtime_directory}/app/navigation/index.js`, '$app/navigation'],
|
|
1247
|
+
[`${runtime_directory}/app/state/index.js`, '$app/state']
|
|
1248
|
+
]);
|
|
1249
|
+
|
|
1250
|
+
for (const output of Object.values(bundle)) {
|
|
1251
|
+
if (output.type !== 'chunk') continue;
|
|
1252
|
+
|
|
1253
|
+
for (const id of output.moduleIds) {
|
|
1254
|
+
const module = modules.get(id);
|
|
1255
|
+
if (module) invalid_modules.add(module);
|
|
1256
|
+
}
|
|
1050
1257
|
}
|
|
1051
1258
|
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1259
|
+
if (invalid_modules.size > 0) {
|
|
1260
|
+
throw new Error(
|
|
1261
|
+
`Cannot import ${Array.from(modules.values())
|
|
1262
|
+
.filter((module) => invalid_modules.has(module))
|
|
1263
|
+
.join(', ')} into service-worker code.`
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1059
1266
|
}
|
|
1060
1267
|
};
|
|
1061
1268
|
|
|
1062
1269
|
/** @type {Plugin} */
|
|
1063
1270
|
const plugin_service_worker_env = {
|
|
1064
1271
|
name: 'vite-plugin-sveltekit-service-worker-env',
|
|
1065
|
-
|
|
1272
|
+
applyToEnvironment(environment) {
|
|
1273
|
+
return !!service_worker_entry_file && environment.config.consumer === 'client';
|
|
1274
|
+
},
|
|
1066
1275
|
transform: {
|
|
1067
|
-
|
|
1068
|
-
id
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
// in
|
|
1072
|
-
//
|
|
1073
|
-
//
|
|
1074
|
-
//
|
|
1276
|
+
handler(code, id) {
|
|
1277
|
+
if (id !== service_worker_entry_file) return;
|
|
1278
|
+
|
|
1279
|
+
// prepend the service worker with an import that configures
|
|
1280
|
+
// `env`, in case `$app/env/public` is imported. In production
|
|
1281
|
+
// this is required: dynamic public env vars aren't known at
|
|
1282
|
+
// build time, so `env.js` is loaded at runtime. In dev, the
|
|
1283
|
+
// imported module just inlines the current values instead.
|
|
1075
1284
|
return {
|
|
1076
1285
|
code: `import '__sveltekit/env/service-worker';\n${code}`
|
|
1077
1286
|
};
|
|
@@ -1079,14 +1288,15 @@ function kit({ svelte_config, adapter }) {
|
|
|
1079
1288
|
}
|
|
1080
1289
|
};
|
|
1081
1290
|
|
|
1291
|
+
/** @type {Map<string, Rolldown.RolldownOutput['output']>} */
|
|
1292
|
+
const watch_build_output = new Map();
|
|
1293
|
+
/** @type {(() => Promise<void>) | null} */
|
|
1294
|
+
let finalise = null;
|
|
1295
|
+
|
|
1082
1296
|
/** @type {Plugin} */
|
|
1083
1297
|
const plugin_compile = {
|
|
1084
1298
|
name: 'vite-plugin-sveltekit-compile',
|
|
1085
1299
|
|
|
1086
|
-
applyToEnvironment(environment) {
|
|
1087
|
-
return environment.name !== 'serviceWorker';
|
|
1088
|
-
},
|
|
1089
|
-
|
|
1090
1300
|
/**
|
|
1091
1301
|
* Build the SvelteKit-provided Vite config to be merged with the user's vite.config.js file.
|
|
1092
1302
|
* @see https://vitejs.dev/guide/api-plugin.html#config
|
|
@@ -1099,12 +1309,13 @@ function kit({ svelte_config, adapter }) {
|
|
|
1099
1309
|
let new_config;
|
|
1100
1310
|
|
|
1101
1311
|
if (is_build) {
|
|
1102
|
-
const
|
|
1312
|
+
const app_immutable = `${kit.appDir}/immutable`;
|
|
1103
1313
|
|
|
1104
1314
|
/** @type {Record<string, string>} */
|
|
1105
1315
|
const server_input = {
|
|
1106
1316
|
index: `${runtime_directory}/server/index.js`,
|
|
1107
1317
|
internal: `${out_dir}/generated/server/internal.js`,
|
|
1318
|
+
env: '__sveltekit/env',
|
|
1108
1319
|
['remote-entry']: `${runtime_directory}/app/server/remote/index.js`
|
|
1109
1320
|
};
|
|
1110
1321
|
|
|
@@ -1133,11 +1344,10 @@ function kit({ svelte_config, adapter }) {
|
|
|
1133
1344
|
}
|
|
1134
1345
|
});
|
|
1135
1346
|
|
|
1136
|
-
// ...and
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
});
|
|
1347
|
+
// ...and the params file
|
|
1348
|
+
if (manifest_data.params) {
|
|
1349
|
+
server_input['entries/params'] = path.resolve(root, manifest_data.params);
|
|
1350
|
+
}
|
|
1141
1351
|
|
|
1142
1352
|
// ...and the hooks files
|
|
1143
1353
|
if (manifest_data.hooks.server) {
|
|
@@ -1155,15 +1365,8 @@ function kit({ svelte_config, adapter }) {
|
|
|
1155
1365
|
path.join(kit.files.src, 'instrumentation.server')
|
|
1156
1366
|
);
|
|
1157
1367
|
if (server_instrumentation) {
|
|
1158
|
-
if (adapter && !adapter.supports?.instrumentation?.()) {
|
|
1159
|
-
throw new Error(`${server_instrumentation} is unsupported in ${adapter.name}.`);
|
|
1160
|
-
}
|
|
1161
|
-
if (!kit.experimental.instrumentation.server) {
|
|
1162
|
-
error_for_missing_config(
|
|
1163
|
-
'`instrumentation.server.js`',
|
|
1164
|
-
'kit.experimental.instrumentation.server',
|
|
1165
|
-
'true'
|
|
1166
|
-
);
|
|
1368
|
+
if (kit.adapter && !kit.adapter.supports?.instrumentation?.()) {
|
|
1369
|
+
throw new Error(`${server_instrumentation} is unsupported in ${kit.adapter.name}.`);
|
|
1167
1370
|
}
|
|
1168
1371
|
server_input['instrumentation.server'] = server_instrumentation;
|
|
1169
1372
|
}
|
|
@@ -1175,6 +1378,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
1175
1378
|
client_input['bundle'] = `${runtime_directory}/client/bundle.js`;
|
|
1176
1379
|
} else {
|
|
1177
1380
|
client_input['entry/start'] = `${runtime_directory}/client/entry.js`;
|
|
1381
|
+
client_input['entry/payload'] = `${runtime_directory}/client/payload.js`;
|
|
1178
1382
|
client_input['entry/app'] = `${out_dir}/generated/client-optimized/app.js`;
|
|
1179
1383
|
manifest_data.nodes.forEach((node, i) => {
|
|
1180
1384
|
if (node.component || node.universal) {
|
|
@@ -1185,20 +1389,25 @@ function kit({ svelte_config, adapter }) {
|
|
|
1185
1389
|
|
|
1186
1390
|
const inline = svelte_config.kit.output.bundleStrategy === 'inline';
|
|
1187
1391
|
|
|
1188
|
-
const config_base = assets_base(kit);
|
|
1189
|
-
|
|
1190
1392
|
/** @type {string} */
|
|
1191
|
-
const base = kit.paths.assets || kit.paths.base
|
|
1192
|
-
const root_to_assets =
|
|
1393
|
+
const base = (kit.paths.assets || kit.paths.base) + '/';
|
|
1394
|
+
const root_to_assets = app_immutable + '/assets/';
|
|
1193
1395
|
const assets_to_root =
|
|
1194
|
-
|
|
1396
|
+
app_immutable
|
|
1195
1397
|
.split('/')
|
|
1196
1398
|
.map(() => '..')
|
|
1197
1399
|
.join('/') + '/../';
|
|
1198
1400
|
|
|
1401
|
+
const relative = kit.paths.relative !== false || !!kit.paths.assets;
|
|
1402
|
+
|
|
1199
1403
|
new_config = {
|
|
1200
1404
|
appType: 'custom',
|
|
1201
|
-
|
|
1405
|
+
// Affects how Vite loads JS assets on the client.
|
|
1406
|
+
// If the initial HTML we render uses an absolute path for assets,
|
|
1407
|
+
// the additional chunks Vite loads must also use an absolute path.
|
|
1408
|
+
// Otherwise, you end up with additional chunks being loaded relative
|
|
1409
|
+
// to the current chunk rather than the root.
|
|
1410
|
+
base: relative ? './' : base,
|
|
1202
1411
|
build: {
|
|
1203
1412
|
cssCodeSplit: !inline,
|
|
1204
1413
|
cssMinify:
|
|
@@ -1207,7 +1416,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
1207
1416
|
rolldownOptions: {
|
|
1208
1417
|
output: {
|
|
1209
1418
|
name: `__sveltekit_${version_hash}.app`,
|
|
1210
|
-
assetFileNames: `${
|
|
1419
|
+
assetFileNames: `${app_immutable}/assets/[name].[hash][extname]`,
|
|
1211
1420
|
hoistTransitiveImports: false,
|
|
1212
1421
|
sourcemapIgnoreList
|
|
1213
1422
|
},
|
|
@@ -1223,6 +1432,12 @@ function kit({ svelte_config, adapter }) {
|
|
|
1223
1432
|
}
|
|
1224
1433
|
|
|
1225
1434
|
handler(warning);
|
|
1435
|
+
},
|
|
1436
|
+
watch: {
|
|
1437
|
+
exclude: [
|
|
1438
|
+
// Ignore all siblings of config.outDir/generated
|
|
1439
|
+
`${out_dir}/generated/**`
|
|
1440
|
+
]
|
|
1226
1441
|
}
|
|
1227
1442
|
},
|
|
1228
1443
|
emptyOutDir: false,
|
|
@@ -1246,7 +1461,7 @@ function kit({ svelte_config, adapter }) {
|
|
|
1246
1461
|
}
|
|
1247
1462
|
}
|
|
1248
1463
|
},
|
|
1249
|
-
//
|
|
1464
|
+
// these are stubs that will be replaced after the initial server build
|
|
1250
1465
|
define: {
|
|
1251
1466
|
__SVELTEKIT_HAS_SERVER_LOAD__: 'true',
|
|
1252
1467
|
__SVELTEKIT_HAS_UNIVERSAL_LOAD__: 'true',
|
|
@@ -1260,9 +1475,27 @@ function kit({ svelte_config, adapter }) {
|
|
|
1260
1475
|
input: inline ? client_input['bundle'] : client_input,
|
|
1261
1476
|
output: {
|
|
1262
1477
|
format: inline ? 'iife' : 'esm',
|
|
1263
|
-
entryFileNames: `${
|
|
1264
|
-
chunkFileNames:
|
|
1265
|
-
|
|
1478
|
+
entryFileNames: `${app_immutable}/[name].[hash].js`,
|
|
1479
|
+
chunkFileNames: (/** @type {Rolldown.PreRenderedChunk} */ chunk_info) => {
|
|
1480
|
+
// The manifest data chunk gets a fixed (non-hashed) filename so
|
|
1481
|
+
// that importers' content hashes are stable regardless of the
|
|
1482
|
+
// manifest content — this breaks the content-hash feedback loop
|
|
1483
|
+
if (chunk_info.name === 'sveltekit-manifest') {
|
|
1484
|
+
return `${kit.appDir}/manifest.js`;
|
|
1485
|
+
}
|
|
1486
|
+
return `${app_immutable}/chunks/[hash].js`;
|
|
1487
|
+
},
|
|
1488
|
+
codeSplitting:
|
|
1489
|
+
svelte_config.kit.output.bundleStrategy === 'split'
|
|
1490
|
+
? {
|
|
1491
|
+
groups: [
|
|
1492
|
+
{
|
|
1493
|
+
name: 'sveltekit-manifest',
|
|
1494
|
+
test: sveltekit_manifest_data
|
|
1495
|
+
}
|
|
1496
|
+
]
|
|
1497
|
+
}
|
|
1498
|
+
: false
|
|
1266
1499
|
},
|
|
1267
1500
|
// This silences Rolldown warnings about not supporting `import.meta`
|
|
1268
1501
|
// for the `iife` output format. We don't care because it's
|
|
@@ -1277,68 +1510,42 @@ function kit({ svelte_config, adapter }) {
|
|
|
1277
1510
|
}
|
|
1278
1511
|
},
|
|
1279
1512
|
define: {
|
|
1280
|
-
__SVELTEKIT_PAYLOAD__:
|
|
1513
|
+
__SVELTEKIT_PAYLOAD__:
|
|
1514
|
+
svelte_config.kit.output.bundleStrategy !== 'split' ? kit_global : 'undefined'
|
|
1281
1515
|
}
|
|
1282
1516
|
}
|
|
1283
1517
|
},
|
|
1284
1518
|
experimental: {
|
|
1285
|
-
//
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
// static dir files
|
|
1314
|
-
return assets_to_root + filename;
|
|
1315
|
-
}
|
|
1519
|
+
// Allows us to use relative paths in as many places as we can
|
|
1520
|
+
renderBuiltUrl(filename, { ssr, hostType }) {
|
|
1521
|
+
if (hostType === 'js') {
|
|
1522
|
+
// SSR builds should use an absolute path in JS modules to
|
|
1523
|
+
// match the default Vite behaviour
|
|
1524
|
+
if (ssr) return base + filename;
|
|
1525
|
+
|
|
1526
|
+
// We could always use a relative asset base path here, but it's better for performance not to.
|
|
1527
|
+
// E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'.
|
|
1528
|
+
// That's larger and takes longer to run and also causes an HTML diff between SSR and client
|
|
1529
|
+
// causing us to do a more expensive hydration check.
|
|
1530
|
+
return { relative };
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
if (!relative) return;
|
|
1534
|
+
|
|
1535
|
+
// ensure assets loaded by CSS files are loaded relative to the
|
|
1536
|
+
// CSS file rather than the default of relative to the root
|
|
1537
|
+
|
|
1538
|
+
// _app/immutable/assets files
|
|
1539
|
+
if (filename.startsWith(root_to_assets)) {
|
|
1540
|
+
return `./${filename.slice(root_to_assets.length)}`;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
// static dir files
|
|
1544
|
+
return assets_to_root + filename;
|
|
1545
|
+
}
|
|
1316
1546
|
},
|
|
1317
1547
|
publicDir: kit.files.assets
|
|
1318
1548
|
};
|
|
1319
|
-
|
|
1320
|
-
if (service_worker_entry_file) {
|
|
1321
|
-
/** @type {Record<string, import('vite').EnvironmentOptions>} */ (
|
|
1322
|
-
new_config.environments
|
|
1323
|
-
).serviceWorker = {
|
|
1324
|
-
build: {
|
|
1325
|
-
modulePreload: false,
|
|
1326
|
-
rolldownOptions: {
|
|
1327
|
-
input: {
|
|
1328
|
-
'service-worker': service_worker_entry_file
|
|
1329
|
-
},
|
|
1330
|
-
output: {
|
|
1331
|
-
entryFileNames: 'service-worker.js',
|
|
1332
|
-
assetFileNames: `${kit.appDir}/immutable/assets/[name].[hash][extname]`,
|
|
1333
|
-
codeSplitting: false
|
|
1334
|
-
}
|
|
1335
|
-
},
|
|
1336
|
-
outDir: `${out}/client`,
|
|
1337
|
-
minify: initial_config.build?.minify
|
|
1338
|
-
},
|
|
1339
|
-
consumer: 'client'
|
|
1340
|
-
};
|
|
1341
|
-
}
|
|
1342
1549
|
} else {
|
|
1343
1550
|
new_config = {
|
|
1344
1551
|
appType: 'custom',
|
|
@@ -1366,16 +1573,32 @@ function kit({ svelte_config, adapter }) {
|
|
|
1366
1573
|
* Adds the SvelteKit middleware to do SSR in dev mode.
|
|
1367
1574
|
* @see https://vitejs.dev/guide/api-plugin.html#configureserver
|
|
1368
1575
|
*/
|
|
1369
|
-
async configureServer(
|
|
1370
|
-
return await dev(
|
|
1576
|
+
async configureServer(server) {
|
|
1577
|
+
return await dev(
|
|
1578
|
+
vite,
|
|
1579
|
+
server,
|
|
1580
|
+
vite_config,
|
|
1581
|
+
svelte_config,
|
|
1582
|
+
() => remotes,
|
|
1583
|
+
root,
|
|
1584
|
+
(data) => {
|
|
1585
|
+
manifest_data = data;
|
|
1586
|
+
// Invalidate the manifest data module so it reloads with new routes/files
|
|
1587
|
+
invalidate_module(server, sveltekit_manifest_data);
|
|
1588
|
+
}
|
|
1589
|
+
);
|
|
1371
1590
|
},
|
|
1372
1591
|
|
|
1373
1592
|
/**
|
|
1374
1593
|
* Adds the SvelteKit middleware to do SSR in preview mode.
|
|
1375
1594
|
* @see https://vitejs.dev/guide/api-plugin.html#configurepreviewserver
|
|
1376
1595
|
*/
|
|
1377
|
-
configurePreviewServer(
|
|
1378
|
-
return preview(
|
|
1596
|
+
configurePreviewServer(server) {
|
|
1597
|
+
return preview(server, vite_config, svelte_config);
|
|
1598
|
+
},
|
|
1599
|
+
|
|
1600
|
+
applyToEnvironment(environment) {
|
|
1601
|
+
return environment.name !== 'serviceWorker';
|
|
1379
1602
|
},
|
|
1380
1603
|
|
|
1381
1604
|
renderChunk(code, chunk) {
|
|
@@ -1392,7 +1615,16 @@ function kit({ svelte_config, adapter }) {
|
|
|
1392
1615
|
}
|
|
1393
1616
|
},
|
|
1394
1617
|
|
|
1395
|
-
generateBundle() {
|
|
1618
|
+
generateBundle(_options, bundle) {
|
|
1619
|
+
// a watched build returns a watcher rather than the build output from
|
|
1620
|
+
// `builder.build` so we need to retrieve it from the generateBundle hook
|
|
1621
|
+
if (this.meta.watchMode) {
|
|
1622
|
+
watch_build_output.set(
|
|
1623
|
+
this.environment.name,
|
|
1624
|
+
/** @type {Rolldown.RolldownOutput['output']} */ (Object.values(bundle))
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1396
1628
|
if (this.environment.config.consumer !== 'client') return;
|
|
1397
1629
|
|
|
1398
1630
|
this.emitFile({
|
|
@@ -1403,330 +1635,540 @@ function kit({ svelte_config, adapter }) {
|
|
|
1403
1635
|
},
|
|
1404
1636
|
|
|
1405
1637
|
async buildApp(builder) {
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
rimraf(out);
|
|
1409
|
-
}
|
|
1410
|
-
mkdirp(out);
|
|
1638
|
+
fs.rmSync(out, { force: true, recursive: true });
|
|
1639
|
+
fs.mkdirSync(out, { recursive: true });
|
|
1411
1640
|
|
|
1412
|
-
const
|
|
1413
|
-
await builder.build(builder.environments.ssr)
|
|
1414
|
-
);
|
|
1415
|
-
|
|
1416
|
-
const verbose = vite_config.logLevel === 'info';
|
|
1641
|
+
const verbose = builder.config.logLevel === 'info';
|
|
1417
1642
|
const log = logger({ verbose });
|
|
1418
1643
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1644
|
+
let ssr_build = await builder.build(builder.environments.ssr);
|
|
1645
|
+
|
|
1646
|
+
/** @param {Rolldown.RolldownOutput['output']} server_chunks */
|
|
1647
|
+
const process_ssr_build = async (server_chunks) => {
|
|
1648
|
+
// Replace manifest placeholders in SSR output. `assets` and `routes`
|
|
1649
|
+
// are known from `manifest_data`. `immutable` and `prerendered` are not
|
|
1650
|
+
// known yet — they get sentinel strings that are replaced after
|
|
1651
|
+
// the client build and after prerendering respectively.
|
|
1652
|
+
replace_manifest_placeholder_variables(server_chunks, `${out}/server`, {
|
|
1653
|
+
assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
|
|
1654
|
+
routes: get_manifest_routes(manifest_data.routes)
|
|
1655
|
+
});
|
|
1656
|
+
|
|
1657
|
+
vite_server_manifest = /** @type {Manifest} */ (
|
|
1658
|
+
JSON.parse(read(`${out}/server/.vite/manifest.json`))
|
|
1659
|
+
);
|
|
1432
1660
|
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1661
|
+
const manifest_path = `${out}/server/manifest-full.js`;
|
|
1662
|
+
const assets_path = `${kit.appDir}/immutable/assets`;
|
|
1663
|
+
|
|
1664
|
+
/** @type {BuildData} */
|
|
1665
|
+
const build_data = {
|
|
1666
|
+
app_dir: kit.appDir,
|
|
1667
|
+
app_path: `${kit.paths.base.slice(1)}${kit.paths.base ? '/' : ''}${kit.appDir}`,
|
|
1668
|
+
manifest_data,
|
|
1669
|
+
out_dir: out,
|
|
1670
|
+
service_worker: service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable?
|
|
1671
|
+
client: null,
|
|
1672
|
+
server_manifest: vite_server_manifest
|
|
1673
|
+
};
|
|
1674
|
+
|
|
1675
|
+
fs.writeFileSync(
|
|
1676
|
+
manifest_path,
|
|
1677
|
+
`export const manifest = ${generate_manifest({
|
|
1678
|
+
build_data,
|
|
1679
|
+
prerendered: [],
|
|
1680
|
+
relative_path: '.',
|
|
1681
|
+
routes: manifest_data.routes,
|
|
1682
|
+
remotes,
|
|
1683
|
+
root
|
|
1684
|
+
})};\n`
|
|
1685
|
+
);
|
|
1686
|
+
|
|
1687
|
+
// first, build server nodes without the client manifest so we can analyse it
|
|
1688
|
+
build_server_nodes(
|
|
1689
|
+
out,
|
|
1690
|
+
kit,
|
|
1691
|
+
manifest_data,
|
|
1692
|
+
vite_server_manifest,
|
|
1693
|
+
null,
|
|
1694
|
+
assets_path,
|
|
1695
|
+
server_chunks,
|
|
1442
1696
|
root
|
|
1443
|
-
|
|
1444
|
-
);
|
|
1697
|
+
);
|
|
1445
1698
|
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
const { metadata } = await analyse({
|
|
1449
|
-
hash: kit.router.type === 'hash',
|
|
1450
|
-
manifest_path,
|
|
1451
|
-
manifest_data,
|
|
1452
|
-
server_manifest,
|
|
1453
|
-
tracked_features,
|
|
1454
|
-
env,
|
|
1455
|
-
out,
|
|
1456
|
-
remotes,
|
|
1457
|
-
root,
|
|
1458
|
-
vite_config_file: vite_config.configFile
|
|
1459
|
-
});
|
|
1699
|
+
log.info('Analysing routes');
|
|
1460
1700
|
|
|
1461
|
-
|
|
1701
|
+
const { metadata } = await analyse({
|
|
1702
|
+
hash: kit.router.type === 'hash',
|
|
1703
|
+
manifest_path,
|
|
1704
|
+
manifest_data,
|
|
1705
|
+
server_manifest: vite_server_manifest,
|
|
1706
|
+
tracked_features,
|
|
1707
|
+
env,
|
|
1708
|
+
remotes,
|
|
1709
|
+
vite_config_file: vite_config.configFile
|
|
1710
|
+
});
|
|
1711
|
+
build_metadata = metadata;
|
|
1462
1712
|
|
|
1463
|
-
|
|
1713
|
+
log.info('Building app');
|
|
1464
1714
|
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
kit,
|
|
1468
|
-
manifest_data,
|
|
1469
|
-
`${out_dir}/generated/client-optimized`,
|
|
1470
|
-
metadata.nodes
|
|
1471
|
-
);
|
|
1715
|
+
const server_assets = `${out}/server/${assets_path}`;
|
|
1716
|
+
const client_assets = `${out}/client/${assets_path}`;
|
|
1472
1717
|
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1718
|
+
const skip_client_build = manifest_data.nodes.every(
|
|
1719
|
+
(node) => node.page_options?.csr === false
|
|
1720
|
+
);
|
|
1721
|
+
|
|
1722
|
+
if (skip_client_build) {
|
|
1723
|
+
copy(server_assets, client_assets);
|
|
1724
|
+
copy(kit.files.assets, `${out}/client`);
|
|
1725
|
+
} else {
|
|
1726
|
+
// ...and build the client
|
|
1727
|
+
write_client_manifest(
|
|
1728
|
+
kit,
|
|
1729
|
+
manifest_data,
|
|
1730
|
+
`${out_dir}/generated/client-optimized`,
|
|
1731
|
+
build_metadata.nodes
|
|
1732
|
+
);
|
|
1476
1733
|
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1734
|
+
// Through the finished analysis we can now check if any node has server or universal load functions
|
|
1735
|
+
const nodes = Object.values(build_metadata.nodes);
|
|
1736
|
+
const has_server_load = nodes.some((node) => node.has_server_load);
|
|
1737
|
+
const has_universal_load = nodes.some((node) => node.has_universal_load);
|
|
1480
1738
|
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1739
|
+
if (builder.environments.client.config.define) {
|
|
1740
|
+
builder.environments.client.config.define.__SVELTEKIT_HAS_SERVER_LOAD__ =
|
|
1741
|
+
s(has_server_load);
|
|
1742
|
+
builder.environments.client.config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ =
|
|
1743
|
+
s(has_universal_load);
|
|
1744
|
+
}
|
|
1487
1745
|
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1746
|
+
const client_build = await builder.build(builder.environments.client);
|
|
1747
|
+
const client_chunks = await normalise_build(
|
|
1748
|
+
builder.environments.client.name,
|
|
1749
|
+
client_build,
|
|
1750
|
+
watch_build_output
|
|
1751
|
+
);
|
|
1491
1752
|
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1753
|
+
// We use `build.ssrEmitAssets` so that asset URLs created from
|
|
1754
|
+
// imports in server-only modules correspond to files in the build,
|
|
1755
|
+
// but we don't want to copy over CSS imports as these are already
|
|
1756
|
+
// accounted for in the client bundle. In most cases it would be
|
|
1757
|
+
// a no-op, but for SSR builds `url(...)` paths are handled
|
|
1758
|
+
// differently (relative for client, absolute for server)
|
|
1759
|
+
// resulting in different hashes, and thus duplication
|
|
1760
|
+
const ssr_stylesheets = new Set(
|
|
1761
|
+
Object.values(vite_server_manifest)
|
|
1762
|
+
.map((chunk) => chunk.css ?? [])
|
|
1763
|
+
.flat()
|
|
1764
|
+
);
|
|
1504
1765
|
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1766
|
+
if (fs.existsSync(server_assets)) {
|
|
1767
|
+
for (const file of fs.readdirSync(server_assets)) {
|
|
1768
|
+
const src = `${server_assets}/${file}`;
|
|
1769
|
+
const dest = `${client_assets}/${file}`;
|
|
1508
1770
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
const dest = `${client_assets}/${file}`;
|
|
1771
|
+
if (fs.existsSync(dest) || ssr_stylesheets.has(`${assets_path}/${file}`)) {
|
|
1772
|
+
continue;
|
|
1773
|
+
}
|
|
1513
1774
|
|
|
1514
|
-
|
|
1515
|
-
|
|
1775
|
+
copy(src, dest);
|
|
1776
|
+
}
|
|
1516
1777
|
}
|
|
1517
1778
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
.readFileSync(src, 'utf-8')
|
|
1522
|
-
.replaceAll(`${kit.paths.base}/${assets_path}`, '.');
|
|
1779
|
+
vite_client_manifest = /** @type {Manifest} */ (
|
|
1780
|
+
JSON.parse(read(`${out}/client/.vite/manifest.json`))
|
|
1781
|
+
);
|
|
1523
1782
|
|
|
1524
|
-
|
|
1525
|
-
|
|
1783
|
+
/**
|
|
1784
|
+
* @param {string} entry
|
|
1785
|
+
* @param {boolean} [add_dynamic_css]
|
|
1786
|
+
*/
|
|
1787
|
+
const deps_of = (entry, add_dynamic_css = false) =>
|
|
1788
|
+
find_deps(
|
|
1789
|
+
/** @type {Manifest} */ (vite_client_manifest),
|
|
1790
|
+
posixify(path.relative(root, entry)),
|
|
1791
|
+
add_dynamic_css,
|
|
1792
|
+
root
|
|
1793
|
+
);
|
|
1526
1794
|
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1795
|
+
// the inline bundle and stylesheet are deleted further down, after
|
|
1796
|
+
// being inlined into the page, so they must not appear in `immutable`
|
|
1797
|
+
/** @type {Set<string>} */
|
|
1798
|
+
const inlined = new Set();
|
|
1799
|
+
/** @type {Rolldown.OutputAsset | undefined} */
|
|
1800
|
+
let inline_style;
|
|
1801
|
+
|
|
1802
|
+
if (kit.output.bundleStrategy === 'inline') {
|
|
1803
|
+
inline_style = /** @type {Rolldown.OutputAsset | undefined} */ (
|
|
1804
|
+
client_chunks.find(
|
|
1805
|
+
(chunk) =>
|
|
1806
|
+
chunk.type === 'asset' &&
|
|
1807
|
+
chunk.names.length === 1 &&
|
|
1808
|
+
chunk.names[0] === 'style.css'
|
|
1809
|
+
)
|
|
1810
|
+
);
|
|
1530
1811
|
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
/**
|
|
1535
|
-
* @param {string} entry
|
|
1536
|
-
* @param {boolean} [add_dynamic_css]
|
|
1537
|
-
*/
|
|
1538
|
-
const deps_of = (entry, add_dynamic_css = false) =>
|
|
1539
|
-
find_deps(client_manifest, posixify(path.relative(root, entry)), add_dynamic_css, root);
|
|
1540
|
-
|
|
1541
|
-
if (svelte_config.kit.output.bundleStrategy === 'split') {
|
|
1542
|
-
const start = deps_of(`${runtime_directory}/client/entry.js`);
|
|
1543
|
-
const app = deps_of(`${out_dir}/generated/client-optimized/app.js`);
|
|
1544
|
-
|
|
1545
|
-
build_data.client = {
|
|
1546
|
-
start: start.file,
|
|
1547
|
-
app: app.file,
|
|
1548
|
-
imports: [...start.imports, ...app.imports],
|
|
1549
|
-
stylesheets: [...start.stylesheets, ...app.stylesheets],
|
|
1550
|
-
fonts: [...start.fonts, ...app.fonts],
|
|
1551
|
-
uses_env_dynamic_public: client_chunks.some(
|
|
1552
|
-
(chunk) => chunk.type === 'chunk' && chunk.modules[sveltekit_env_public_client]
|
|
1553
|
-
)
|
|
1554
|
-
};
|
|
1812
|
+
inlined.add(deps_of(`${runtime_directory}/client/bundle.js`).file);
|
|
1813
|
+
if (inline_style) inlined.add(inline_style.fileName);
|
|
1814
|
+
}
|
|
1555
1815
|
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
`${out_dir}/generated/client-optimized/nodes/${i}.js`,
|
|
1567
|
-
root
|
|
1568
|
-
).chunk.file;
|
|
1569
|
-
|
|
1570
|
-
return { file, css: deps.stylesheets };
|
|
1571
|
-
}
|
|
1816
|
+
// Replace manifest placeholders in client output. `immutable` is
|
|
1817
|
+
// computed from the Vite client manifest, `assets` and `routes`
|
|
1818
|
+
// from `manifest_data`. `prerendered` is left as a placeholder
|
|
1819
|
+
// for now — it's replaced after prerendering completes.
|
|
1820
|
+
immutable = collect_immutable(vite_client_manifest, kit.appDir, inlined);
|
|
1821
|
+
|
|
1822
|
+
replace_manifest_placeholder_variables(client_chunks, `${out}/client`, {
|
|
1823
|
+
immutable,
|
|
1824
|
+
assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
|
|
1825
|
+
routes: get_manifest_routes(manifest_data.routes)
|
|
1572
1826
|
});
|
|
1573
|
-
build_data.client.nodes = nodes.map((node) => node?.file);
|
|
1574
|
-
build_data.client.css = nodes.map((node) => node?.css);
|
|
1575
1827
|
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1828
|
+
// Now that the client build is done, replace the `build` sentinel
|
|
1829
|
+
// in the SSR output with the real build files
|
|
1830
|
+
replace_manifest_placeholder_strings(`${out}/server`, { immutable });
|
|
1579
1831
|
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1832
|
+
const has_explicit_dynamic_public_env = Object.values(explicit_env_config ?? {}).some(
|
|
1833
|
+
(variable) => variable.public && !variable.static
|
|
1834
|
+
);
|
|
1835
|
+
|
|
1836
|
+
// the app only depends on runtime public env if it imports `$app/env/public`
|
|
1837
|
+
// *and* at least one public env var is actually dynamic (non-static)
|
|
1838
|
+
const uses_env_dynamic_public =
|
|
1839
|
+
has_explicit_dynamic_public_env &&
|
|
1840
|
+
client_chunks.some(
|
|
1841
|
+
(chunk) => chunk.type === 'chunk' && chunk.modules[sveltekit_env_public_client]
|
|
1842
|
+
);
|
|
1843
|
+
|
|
1844
|
+
if (kit.output.bundleStrategy === 'split') {
|
|
1845
|
+
const start_entry = posixify(
|
|
1846
|
+
path.relative(root, `${runtime_directory}/client/entry.js`)
|
|
1847
|
+
);
|
|
1848
|
+
const start = find_deps(vite_client_manifest, start_entry, false, root);
|
|
1849
|
+
const runtime_entry = resolve_symlinks(vite_client_manifest, start_entry, root).chunk
|
|
1850
|
+
.dynamicImports?.[0]; // client/entry.js dynamically imports client/client-entry.js
|
|
1851
|
+
if (!runtime_entry) throw new Error('Could not find the client runtime chunk');
|
|
1852
|
+
const runtime = find_deps(vite_client_manifest, runtime_entry, false, root);
|
|
1853
|
+
const app = deps_of(`${out_dir}/generated/client-optimized/app.js`);
|
|
1854
|
+
|
|
1855
|
+
build_data.client = {
|
|
1856
|
+
start: start.file,
|
|
1857
|
+
app: app.file,
|
|
1858
|
+
imports: Array.from(
|
|
1859
|
+
new Set([
|
|
1860
|
+
...start.imports,
|
|
1861
|
+
runtime.file,
|
|
1862
|
+
...runtime.imports,
|
|
1863
|
+
app.file,
|
|
1864
|
+
...app.imports
|
|
1865
|
+
])
|
|
1866
|
+
),
|
|
1867
|
+
stylesheets: [...start.stylesheets, ...runtime.stylesheets, ...app.stylesheets],
|
|
1868
|
+
fonts: [...start.fonts, ...runtime.fonts, ...app.fonts],
|
|
1869
|
+
uses_env_dynamic_public
|
|
1870
|
+
};
|
|
1871
|
+
|
|
1872
|
+
// In case of server-side route resolution, we create a purpose-built route manifest that is
|
|
1873
|
+
// similar to that on the client, with as much information computed upfront so that we
|
|
1874
|
+
// don't need to include any code of the actual routes in the server bundle.
|
|
1875
|
+
if (kit.router.resolution === 'server') {
|
|
1876
|
+
const nodes = manifest_data.nodes.map((node, i) => {
|
|
1877
|
+
if (node.component || node.universal) {
|
|
1878
|
+
const entry = `${out_dir}/generated/client-optimized/nodes/${i}.js`;
|
|
1879
|
+
const deps = deps_of(entry, true);
|
|
1880
|
+
const file = resolve_symlinks(
|
|
1881
|
+
/** @type {Manifest} */ (vite_client_manifest),
|
|
1882
|
+
`${out_dir}/generated/client-optimized/nodes/${i}.js`,
|
|
1883
|
+
root
|
|
1884
|
+
).chunk.file;
|
|
1885
|
+
|
|
1886
|
+
return { file, css: deps.stylesheets };
|
|
1887
|
+
}
|
|
1888
|
+
});
|
|
1889
|
+
build_data.client.nodes = nodes.map((node) => node?.file);
|
|
1890
|
+
build_data.client.css = nodes.map((node) => node?.css);
|
|
1891
|
+
|
|
1892
|
+
build_data.client.routes = compact(
|
|
1893
|
+
manifest_data.routes.map((route) => {
|
|
1894
|
+
if (!route.page) return;
|
|
1895
|
+
|
|
1896
|
+
return {
|
|
1897
|
+
id: route.id,
|
|
1898
|
+
pattern: route.pattern,
|
|
1899
|
+
params: route.params,
|
|
1900
|
+
layouts: route.page.layouts.map((l) =>
|
|
1901
|
+
l !== undefined ? [metadata.nodes[l].has_server_load, l] : undefined
|
|
1902
|
+
),
|
|
1903
|
+
errors: route.page.errors,
|
|
1904
|
+
leaf: [metadata.nodes[route.page.leaf].has_server_load, route.page.leaf]
|
|
1905
|
+
};
|
|
1906
|
+
})
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
} else {
|
|
1910
|
+
const start = deps_of(`${runtime_directory}/client/bundle.js`);
|
|
1911
|
+
|
|
1912
|
+
build_data.client = {
|
|
1913
|
+
start: start.file,
|
|
1914
|
+
imports: start.imports,
|
|
1915
|
+
stylesheets: start.stylesheets,
|
|
1916
|
+
fonts: start.fonts,
|
|
1917
|
+
uses_env_dynamic_public
|
|
1918
|
+
};
|
|
1919
|
+
|
|
1920
|
+
if (kit.output.bundleStrategy === 'inline') {
|
|
1921
|
+
build_data.client.inline = {
|
|
1922
|
+
script: read(`${out}/client/${start.file}`),
|
|
1923
|
+
style: /** @type {string | undefined} */ (inline_style?.source)
|
|
1589
1924
|
};
|
|
1590
|
-
|
|
1925
|
+
|
|
1926
|
+
// the bundle and stylesheet are inlined into the page, so the
|
|
1927
|
+
// emitted files are never loaded
|
|
1928
|
+
fs.unlinkSync(`${out}/client/${start.file}`);
|
|
1929
|
+
fs.rmSync(`${out}/client/${start.file}.map`, { force: true });
|
|
1930
|
+
if (inline_style) fs.unlinkSync(`${out}/client/${inline_style.fileName}`);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
// regenerate manifest now that we have client entry...
|
|
1935
|
+
fs.writeFileSync(
|
|
1936
|
+
manifest_path,
|
|
1937
|
+
`export const manifest = ${generate_manifest({
|
|
1938
|
+
build_data,
|
|
1939
|
+
prerendered: [],
|
|
1940
|
+
relative_path: '.',
|
|
1941
|
+
routes: manifest_data.routes,
|
|
1942
|
+
remotes,
|
|
1943
|
+
root
|
|
1944
|
+
})};\n`
|
|
1591
1945
|
);
|
|
1592
|
-
}
|
|
1593
|
-
} else {
|
|
1594
|
-
const start = deps_of(`${runtime_directory}/client/bundle.js`);
|
|
1595
|
-
|
|
1596
|
-
build_data.client = {
|
|
1597
|
-
start: start.file,
|
|
1598
|
-
imports: start.imports,
|
|
1599
|
-
stylesheets: start.stylesheets,
|
|
1600
|
-
fonts: start.fonts,
|
|
1601
|
-
uses_env_dynamic_public: client_chunks.some(
|
|
1602
|
-
(chunk) => chunk.type === 'chunk' && chunk.modules[sveltekit_env_public_client]
|
|
1603
|
-
)
|
|
1604
|
-
};
|
|
1605
1946
|
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1947
|
+
// regenerate nodes with the client manifest...
|
|
1948
|
+
build_server_nodes(
|
|
1949
|
+
out,
|
|
1950
|
+
kit,
|
|
1951
|
+
manifest_data,
|
|
1952
|
+
vite_server_manifest,
|
|
1953
|
+
vite_client_manifest,
|
|
1954
|
+
assets_path,
|
|
1955
|
+
client_chunks,
|
|
1956
|
+
root
|
|
1612
1957
|
);
|
|
1958
|
+
}
|
|
1613
1959
|
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1960
|
+
// ...and prerender
|
|
1961
|
+
let prerender_results;
|
|
1962
|
+
try {
|
|
1963
|
+
prerender_results = await prerender({
|
|
1964
|
+
hash: kit.router.type === 'hash',
|
|
1965
|
+
out,
|
|
1966
|
+
manifest_path,
|
|
1967
|
+
metadata,
|
|
1968
|
+
verbose,
|
|
1969
|
+
env,
|
|
1970
|
+
vite_config_file: vite_config.configFile,
|
|
1971
|
+
is_tty: process.stdout.isTTY
|
|
1972
|
+
});
|
|
1973
|
+
|
|
1974
|
+
// this silly hack is necessary to ensure that stderr from prerender is flushed before we continue
|
|
1975
|
+
await new Promise((f) => setTimeout(f, 0));
|
|
1976
|
+
} catch (e) {
|
|
1977
|
+
if (e instanceof Error && e.message === '__handled__') {
|
|
1978
|
+
// error details are already logged inside `prerender`, don't duplicate them
|
|
1979
|
+
throw stackless('Prerendering failed');
|
|
1980
|
+
} else {
|
|
1981
|
+
// Unforeseen error, rethrow as-is
|
|
1982
|
+
throw e;
|
|
1983
|
+
}
|
|
1618
1984
|
}
|
|
1619
|
-
}
|
|
1620
1985
|
|
|
1621
|
-
|
|
1622
|
-
fs.writeFileSync(
|
|
1623
|
-
manifest_path,
|
|
1624
|
-
`export const manifest = ${generate_manifest({
|
|
1625
|
-
build_data,
|
|
1626
|
-
prerendered: [],
|
|
1627
|
-
relative_path: '.',
|
|
1628
|
-
routes: manifest_data.routes,
|
|
1629
|
-
remotes,
|
|
1630
|
-
root
|
|
1631
|
-
})};\n`
|
|
1632
|
-
);
|
|
1986
|
+
prerendered = prerender_results.prerendered;
|
|
1633
1987
|
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
client_manifest,
|
|
1641
|
-
assets_path,
|
|
1642
|
-
client_chunks,
|
|
1643
|
-
root
|
|
1644
|
-
);
|
|
1988
|
+
// Replace the `prerendered` sentinel in both SSR and client output
|
|
1989
|
+
// with the real prerendered paths. The other sentinels (`build`)
|
|
1990
|
+
// were already replaced after the client build.
|
|
1991
|
+
const prerendered_paths = prerendered.paths.map((p) => {
|
|
1992
|
+
return { path: p.replace(kit.paths.base, '').slice(1) };
|
|
1993
|
+
});
|
|
1645
1994
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
hash: kit.router.type === 'hash',
|
|
1649
|
-
out,
|
|
1650
|
-
manifest_path,
|
|
1651
|
-
metadata,
|
|
1652
|
-
verbose,
|
|
1653
|
-
env,
|
|
1654
|
-
vite_config_file: vite_config.configFile
|
|
1655
|
-
});
|
|
1656
|
-
prerendered = prerender_results.prerendered;
|
|
1995
|
+
replace_manifest_placeholder_strings(`${out}/server`, { prerendered: prerendered_paths });
|
|
1996
|
+
replace_manifest_placeholder_strings(`${out}/client`, { prerendered: prerendered_paths });
|
|
1657
1997
|
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
);
|
|
1998
|
+
// For `inline` strategy, the entry file was deleted and read into
|
|
1999
|
+
// `build_data.client.inline.script` — replace the sentinel there too
|
|
2000
|
+
if (build_data.client?.inline?.script) {
|
|
2001
|
+
build_data.client.inline.script = build_data.client.inline.script.replaceAll(
|
|
2002
|
+
'"__sveltekit_manifest_prerendered__"',
|
|
2003
|
+
JSON.stringify(prerendered_paths)
|
|
2004
|
+
);
|
|
2005
|
+
}
|
|
1667
2006
|
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2007
|
+
// generate a new manifest that doesn't include prerendered pages
|
|
2008
|
+
fs.writeFileSync(
|
|
2009
|
+
`${out}/server/manifest.js`,
|
|
2010
|
+
`export const manifest = ${generate_manifest({
|
|
2011
|
+
build_data,
|
|
2012
|
+
prerendered: prerendered.paths,
|
|
2013
|
+
relative_path: '.',
|
|
2014
|
+
routes: manifest_data.routes.filter(
|
|
2015
|
+
(route) => prerender_results.prerender_map.get(route.id) !== true
|
|
2016
|
+
),
|
|
2017
|
+
remotes,
|
|
2018
|
+
root
|
|
2019
|
+
})};\n`
|
|
2020
|
+
);
|
|
2021
|
+
|
|
2022
|
+
await treeshake_prerendered_remotes(
|
|
2023
|
+
vite,
|
|
2024
|
+
out,
|
|
1678
2025
|
remotes,
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
2026
|
+
remote_original_by_hash,
|
|
2027
|
+
metadata,
|
|
2028
|
+
process.cwd(),
|
|
2029
|
+
server_chunks,
|
|
2030
|
+
vite_config.build.sourcemap
|
|
2031
|
+
);
|
|
1682
2032
|
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
2033
|
+
// defer until after other buildApp hooks have run
|
|
2034
|
+
finalise = async () => {
|
|
2035
|
+
// defer creating the service worker to avoid other plugins from
|
|
2036
|
+
// overwriting it if they run a client environment build
|
|
2037
|
+
if (service_worker_entry_file) {
|
|
2038
|
+
log.info('Building service worker');
|
|
1687
2039
|
|
|
1688
|
-
|
|
2040
|
+
// mirror client settings that we couldn't set per environment in the config hook
|
|
2041
|
+
builder.environments.serviceWorker.config.define =
|
|
2042
|
+
builder.environments.client.config.define;
|
|
2043
|
+
builder.environments.serviceWorker.config.resolve.alias = [
|
|
2044
|
+
...get_config_aliases(kit, vite_config.root)
|
|
2045
|
+
];
|
|
1689
2046
|
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
2047
|
+
// we have to overwrite this because it can't be configured per environment in the config hook
|
|
2048
|
+
builder.environments.serviceWorker.config.experimental.renderBuiltUrl = (filename) => {
|
|
2049
|
+
return {
|
|
2050
|
+
runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname`
|
|
2051
|
+
};
|
|
2052
|
+
};
|
|
2053
|
+
|
|
2054
|
+
const service_worker_build = await builder.build(builder.environments.serviceWorker);
|
|
2055
|
+
await normalise_build(
|
|
2056
|
+
builder.environments.serviceWorker.name,
|
|
2057
|
+
service_worker_build,
|
|
2058
|
+
watch_build_output
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
console.log(
|
|
2063
|
+
`\nRun ${styleText(['bold', 'cyan'], 'npm run preview')} to preview your production build locally.`
|
|
2064
|
+
);
|
|
2065
|
+
|
|
2066
|
+
if (kit.adapter) {
|
|
2067
|
+
await adapt(
|
|
2068
|
+
svelte_config,
|
|
2069
|
+
build_data,
|
|
2070
|
+
metadata,
|
|
2071
|
+
prerendered,
|
|
2072
|
+
prerender_results.prerender_map,
|
|
2073
|
+
log,
|
|
2074
|
+
remotes,
|
|
2075
|
+
vite_config,
|
|
2076
|
+
explicit_env_config
|
|
2077
|
+
);
|
|
2078
|
+
} else {
|
|
2079
|
+
log.warn('\nNo adapter specified');
|
|
2080
|
+
|
|
2081
|
+
const link = styleText(['bold', 'cyan'], 'https://svelte.dev/docs/kit/adapters');
|
|
2082
|
+
console.log(
|
|
2083
|
+
`See ${link} to learn how to configure your app to run on the platform of your choosing`
|
|
2084
|
+
);
|
|
2085
|
+
}
|
|
1699
2086
|
};
|
|
2087
|
+
};
|
|
1700
2088
|
|
|
1701
|
-
|
|
2089
|
+
// `vite build`
|
|
2090
|
+
ssr_build = Array.isArray(ssr_build) ? ssr_build[0] : ssr_build;
|
|
2091
|
+
if ('output' in ssr_build) {
|
|
2092
|
+
await load_and_validate_params({
|
|
2093
|
+
routes: manifest_data.routes,
|
|
2094
|
+
params_path: manifest_data.params,
|
|
2095
|
+
root
|
|
2096
|
+
});
|
|
2097
|
+
|
|
2098
|
+
return await process_ssr_build(ssr_build.output);
|
|
1702
2099
|
}
|
|
1703
2100
|
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
);
|
|
2101
|
+
// `vite build --watch`
|
|
2102
|
+
let rebuild = false;
|
|
1707
2103
|
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
log,
|
|
1718
|
-
remotes,
|
|
1719
|
-
vite_config,
|
|
1720
|
-
explicit_env_config
|
|
1721
|
-
);
|
|
1722
|
-
} else {
|
|
1723
|
-
console.log(styleText(['bold', 'yellow'], '\nNo adapter specified'));
|
|
2104
|
+
const before_ssr_build_rerun = async () => {
|
|
2105
|
+
rebuild = true;
|
|
2106
|
+
|
|
2107
|
+
// these are set once per plugin initialisation or when the config hook
|
|
2108
|
+
// runs. However, those don't re-run during watch mode. So, we need to
|
|
2109
|
+
// re-initialise them manually here
|
|
2110
|
+
manifest_data = sync.all(svelte_config, root).manifest_data;
|
|
2111
|
+
|
|
2112
|
+
tracked_features = {};
|
|
1724
2113
|
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
2114
|
+
remotes = [];
|
|
2115
|
+
remote_original_by_hash.clear();
|
|
2116
|
+
emitted_remote_hashes.clear();
|
|
2117
|
+
|
|
2118
|
+
immutable = null;
|
|
2119
|
+
manifest_data_code = null;
|
|
2120
|
+
|
|
2121
|
+
finalise = null;
|
|
2122
|
+
|
|
2123
|
+
fs.mkdirSync(out, { recursive: true });
|
|
2124
|
+
|
|
2125
|
+
explicit_env_entry = resolve_explicit_env_entry(kit);
|
|
2126
|
+
explicit_env_config = await sync.env(
|
|
2127
|
+
vite,
|
|
2128
|
+
kit,
|
|
2129
|
+
explicit_env_entry,
|
|
2130
|
+
vite_config.root,
|
|
2131
|
+
vite_config.mode
|
|
1728
2132
|
);
|
|
1729
|
-
|
|
2133
|
+
|
|
2134
|
+
await load_and_validate_params({
|
|
2135
|
+
routes: manifest_data.routes,
|
|
2136
|
+
params_path: manifest_data.params,
|
|
2137
|
+
root
|
|
2138
|
+
});
|
|
2139
|
+
};
|
|
2140
|
+
|
|
2141
|
+
ssr_build.on('change', before_ssr_build_rerun);
|
|
2142
|
+
ssr_build.on('restart', before_ssr_build_rerun);
|
|
2143
|
+
|
|
2144
|
+
/** @type {PromiseWithResolvers<void>} */
|
|
2145
|
+
const task = Promise.withResolvers();
|
|
2146
|
+
|
|
2147
|
+
ssr_build.on('event', async (event) => {
|
|
2148
|
+
if (event.code === 'ERROR') {
|
|
2149
|
+
return task.reject();
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
if (event.code === 'BUNDLE_END') {
|
|
2153
|
+
try {
|
|
2154
|
+
await process_ssr_build(
|
|
2155
|
+
/** @type {Rolldown.RolldownOutput['output']} */ (
|
|
2156
|
+
watch_build_output.get(builder.environments.ssr.name)
|
|
2157
|
+
)
|
|
2158
|
+
);
|
|
2159
|
+
// buildApp hooks don't rerun in watch mode so we need to run
|
|
2160
|
+
// the deferred steps here on subsequent builds
|
|
2161
|
+
if (rebuild) await finalise?.();
|
|
2162
|
+
} catch (e) {
|
|
2163
|
+
return task.reject(e);
|
|
2164
|
+
} finally {
|
|
2165
|
+
await event.result.close();
|
|
2166
|
+
}
|
|
2167
|
+
return task.resolve();
|
|
2168
|
+
}
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
await task.promise;
|
|
1730
2172
|
}
|
|
1731
2173
|
};
|
|
1732
2174
|
|
|
@@ -1734,23 +2176,32 @@ function kit({ svelte_config, adapter }) {
|
|
|
1734
2176
|
const plugin_adapter = {
|
|
1735
2177
|
name: 'vite-plugin-sveltekit-adapter',
|
|
1736
2178
|
apply: 'build',
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
2179
|
+
buildApp: {
|
|
2180
|
+
// this will run after any buildApp hooks provided by other Vite plugins
|
|
2181
|
+
// see https://vite.dev/guide/api-environment-frameworks#environments-during-build
|
|
2182
|
+
order: 'post',
|
|
2183
|
+
async handler() {
|
|
2184
|
+
await finalise?.();
|
|
2185
|
+
}
|
|
1741
2186
|
}
|
|
1742
2187
|
};
|
|
1743
2188
|
|
|
1744
|
-
return [
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
2189
|
+
return /** @type {Plugin[]} */ (
|
|
2190
|
+
[
|
|
2191
|
+
svelte_config.kit.adapter?.vite?.plugins?.pre,
|
|
2192
|
+
plugin_resolve_root,
|
|
2193
|
+
plugin_setup,
|
|
2194
|
+
plugin_remote_guard,
|
|
2195
|
+
plugin_remote,
|
|
2196
|
+
plugin_virtual_modules,
|
|
2197
|
+
process.env.TEST !== 'true' ? plugin_guard : undefined,
|
|
2198
|
+
plugin_service_worker,
|
|
2199
|
+
plugin_service_worker_env,
|
|
2200
|
+
plugin_compile,
|
|
2201
|
+
plugin_adapter,
|
|
2202
|
+
svelte_config.kit.adapter?.vite?.plugins?.post
|
|
2203
|
+
].filter(Boolean)
|
|
2204
|
+
);
|
|
1754
2205
|
}
|
|
1755
2206
|
|
|
1756
2207
|
/**
|
|
@@ -1785,13 +2236,14 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
|
|
|
1785
2236
|
for (const key in enforced_config) {
|
|
1786
2237
|
if (typeof config === 'object' && key in config && key in resolved_config) {
|
|
1787
2238
|
const enforced = enforced_config[key];
|
|
2239
|
+
const resolved = resolved_config[key];
|
|
1788
2240
|
|
|
1789
2241
|
if (enforced === true) {
|
|
1790
|
-
if (config[key] !==
|
|
2242
|
+
if (comparable(config[key]) !== comparable(resolved)) {
|
|
1791
2243
|
out.push(path + key);
|
|
1792
2244
|
}
|
|
1793
2245
|
} else {
|
|
1794
|
-
find_overridden_config(config[key],
|
|
2246
|
+
find_overridden_config(config[key], resolved, enforced, path + key + '.', out);
|
|
1795
2247
|
}
|
|
1796
2248
|
}
|
|
1797
2249
|
}
|
|
@@ -1799,20 +2251,249 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
|
|
|
1799
2251
|
}
|
|
1800
2252
|
|
|
1801
2253
|
/**
|
|
1802
|
-
*
|
|
2254
|
+
* Collects the content-hashed files of a Vite manifest, in the shape of
|
|
2255
|
+
* `$app/manifest`'s `immutable` export.
|
|
2256
|
+
*
|
|
2257
|
+
* @param {Manifest} manifest
|
|
2258
|
+
* @param {string} app_dir
|
|
2259
|
+
* @param {Set<string>} inlined files deleted from the output after being inlined into the page
|
|
2260
|
+
* @returns {Array<{ path: string }>}
|
|
2261
|
+
*/
|
|
2262
|
+
const collect_immutable = (manifest, app_dir, inlined) => {
|
|
2263
|
+
const prefix = `${app_dir}/immutable`;
|
|
2264
|
+
|
|
2265
|
+
/** @type {Set<string>} */
|
|
2266
|
+
const files = new Set();
|
|
2267
|
+
|
|
2268
|
+
/** @param {string} file */
|
|
2269
|
+
const add = (file) => {
|
|
2270
|
+
if (file.startsWith(prefix) && !inlined.has(file)) files.add(file);
|
|
2271
|
+
};
|
|
2272
|
+
|
|
2273
|
+
for (const key in manifest) {
|
|
2274
|
+
const { file, css, assets } = manifest[key];
|
|
2275
|
+
add(file);
|
|
2276
|
+
if (css) for (let i = 0; i < css.length; i++) add(css[i]);
|
|
2277
|
+
if (assets) for (let i = 0; i < assets.length; i++) add(assets[i]);
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
return Array.from(files, (path) => ({ path }));
|
|
2281
|
+
};
|
|
2282
|
+
|
|
2283
|
+
/**
|
|
2284
|
+
* Normalizes a config value for comparison, since Windows paths may use backslashes
|
|
2285
|
+
* and differ in casing (e.g. the drive letter) depending on where they came from.
|
|
2286
|
+
* @param {any} value
|
|
2287
|
+
*/
|
|
2288
|
+
function comparable(value) {
|
|
2289
|
+
if (typeof value !== 'string') return value;
|
|
2290
|
+
const normalized = posixify(value);
|
|
2291
|
+
return process.platform === 'win32' ? normalized.toLowerCase() : normalized;
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
/**
|
|
2295
|
+
* @param {Asset[] | undefined} assets
|
|
2296
|
+
* @returns {string}
|
|
2297
|
+
*/
|
|
2298
|
+
function stringify_assets(assets) {
|
|
2299
|
+
return assets?.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
/**
|
|
2303
|
+
* @param {RouteData[] | undefined} routes
|
|
2304
|
+
* @returns {Array<{ id: string; page: boolean; endpoint: boolean }>}
|
|
2305
|
+
*/
|
|
2306
|
+
function get_manifest_routes(routes) {
|
|
2307
|
+
return (
|
|
2308
|
+
routes?.filter(is_app_route).map((route) => ({
|
|
2309
|
+
id: route.id,
|
|
2310
|
+
page: is_page_route(route),
|
|
2311
|
+
endpoint: is_endpoint_route(route)
|
|
2312
|
+
})) ?? []
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
/**
|
|
2317
|
+
* @param {RouteData[] | undefined} routes
|
|
2318
|
+
* @returns {string}
|
|
1803
2319
|
*/
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
2320
|
+
function stringify_routes(routes) {
|
|
2321
|
+
return get_manifest_routes(routes)
|
|
2322
|
+
.map((route) => s(route))
|
|
2323
|
+
.join(',\n');
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
/**
|
|
2327
|
+
* Creates the `$app/manifest` data module. During development, real values
|
|
2328
|
+
* are emitted for `assets` and `routes` (the only data known at that point).
|
|
2329
|
+
*
|
|
2330
|
+
* During build, bare identifier placeholders (fake globals) are emitted.
|
|
2331
|
+
* The bundler leaves these as unresolved global references in the output,
|
|
2332
|
+
* which are then replaced with real values by scanning the output chunks
|
|
2333
|
+
* after each build completes. This avoids the content-hash feedback loop:
|
|
2334
|
+
* the manifest data lives in its own chunk with a fixed filename, so
|
|
2335
|
+
* importers' hashes are stable regardless of the manifest content.
|
|
2336
|
+
*
|
|
2337
|
+
* @param {boolean} is_build
|
|
2338
|
+
* @param {ManifestData | undefined} manifest_data
|
|
2339
|
+
* @returns {string}
|
|
2340
|
+
*/
|
|
2341
|
+
const create_manifest_data_module = (is_build, manifest_data) => {
|
|
2342
|
+
if (is_build) {
|
|
2343
|
+
// Bare identifiers (fake globals) — the bundler leaves these as
|
|
2344
|
+
// unresolved global references in the output. They are replaced
|
|
2345
|
+
// with real values by `replace_manifest_placeholder_variables`
|
|
2346
|
+
// after each build completes.
|
|
2347
|
+
return dedent`
|
|
2348
|
+
export const immutable = __SVELTEKIT_MANIFEST_IMMUTABLE__;
|
|
2349
|
+
export const assets = __SVELTEKIT_MANIFEST_ASSETS__;
|
|
2350
|
+
export const prerendered = __SVELTEKIT_MANIFEST_PRERENDERED__;
|
|
2351
|
+
export const routes = __SVELTEKIT_MANIFEST_ROUTES__;
|
|
2352
|
+
`;
|
|
1807
2353
|
}
|
|
1808
2354
|
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
2355
|
+
// In dev, `manifest_data` may not be set yet on the very first load,
|
|
2356
|
+
// but `configureServer` (which calls `sync.create`) runs before any
|
|
2357
|
+
// module is served, so it will be set by the time this is called.
|
|
2358
|
+
return dedent`
|
|
2359
|
+
// empty during dev
|
|
2360
|
+
export const immutable = [];
|
|
2361
|
+
export const prerendered = [];
|
|
2362
|
+
|
|
2363
|
+
export const assets = [
|
|
2364
|
+
${stringify_assets(manifest_data?.assets)}
|
|
2365
|
+
];
|
|
2366
|
+
|
|
2367
|
+
export const routes = [
|
|
2368
|
+
${stringify_routes(manifest_data?.routes)}
|
|
2369
|
+
];
|
|
2370
|
+
`;
|
|
2371
|
+
};
|
|
2372
|
+
|
|
2373
|
+
/**
|
|
2374
|
+
* Replaces manifest data placeholder identifiers in output chunks with real
|
|
2375
|
+
* values, or strings that are valid JS (so thecode doesn't crash during prerendering)
|
|
2376
|
+
* but findable on disk for later replacement by `replace_manifest_placeholder_strings`.
|
|
2377
|
+
*
|
|
2378
|
+
* @param {Rolldown.RolldownOutput['output']} chunks
|
|
2379
|
+
* @param {string} output_dir
|
|
2380
|
+
* @param {{
|
|
2381
|
+
* immutable?: Array<{ path: string }>;
|
|
2382
|
+
* assets?: Array<{ path: string }>;
|
|
2383
|
+
* prerendered?: Array<{ path: string }>;
|
|
2384
|
+
* routes?: Array<{ id: string; page: boolean; endpoint: boolean }>;
|
|
2385
|
+
* }} values
|
|
2386
|
+
*/
|
|
2387
|
+
const replace_manifest_placeholder_variables = (chunks, output_dir, values) => {
|
|
2388
|
+
/** @type {Record<string, string>} */
|
|
2389
|
+
const replacements = {
|
|
2390
|
+
__SVELTEKIT_MANIFEST_IMMUTABLE__: JSON.stringify(
|
|
2391
|
+
values.immutable ?? '__sveltekit_manifest_build__'
|
|
2392
|
+
),
|
|
2393
|
+
__SVELTEKIT_MANIFEST_ASSETS__: JSON.stringify(values.assets ?? '__sveltekit_manifest_files__'),
|
|
2394
|
+
__SVELTEKIT_MANIFEST_PRERENDERED__: JSON.stringify(
|
|
2395
|
+
values.prerendered ?? '__sveltekit_manifest_prerendered__'
|
|
2396
|
+
),
|
|
2397
|
+
__SVELTEKIT_MANIFEST_ROUTES__: JSON.stringify(values.routes ?? '__sveltekit_manifest_routes__')
|
|
2398
|
+
};
|
|
2399
|
+
|
|
2400
|
+
for (const chunk of chunks) {
|
|
2401
|
+
if (chunk.type !== 'chunk') continue;
|
|
2402
|
+
if (!chunk.code.includes('__SVELTEKIT_MANIFEST_')) continue;
|
|
2403
|
+
|
|
2404
|
+
let code = chunk.code;
|
|
2405
|
+
|
|
2406
|
+
for (const [identifier, replacement] of Object.entries(replacements)) {
|
|
2407
|
+
code = code.replaceAll(identifier, replacement);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
const file_path = `${output_dir}/${chunk.fileName}`;
|
|
2411
|
+
fs.writeFileSync(file_path, code);
|
|
2412
|
+
}
|
|
2413
|
+
};
|
|
2414
|
+
|
|
2415
|
+
/**
|
|
2416
|
+
* Replaces manifest sentinel strings in files on disk with real values.
|
|
2417
|
+
* This is used for values that weren't known when the first replacement
|
|
2418
|
+
* pass ran (e.g. `build` wasn't known until after the client build,
|
|
2419
|
+
* `prerendered` wasn't known until after prerendering).
|
|
2420
|
+
*
|
|
2421
|
+
* @param {string} dir Directory to scan for .js files
|
|
2422
|
+
* @param {{
|
|
2423
|
+
* immutable?: Array<{ path: string }>;
|
|
2424
|
+
* prerendered?: Array<{ path: string }>;
|
|
2425
|
+
* }} values
|
|
2426
|
+
*/
|
|
2427
|
+
const replace_manifest_placeholder_strings = (dir, values) => {
|
|
2428
|
+
/** @type {Record<string, string>} */
|
|
2429
|
+
const replacements = {};
|
|
2430
|
+
|
|
2431
|
+
if (values.immutable !== undefined) {
|
|
2432
|
+
replacements['__sveltekit_manifest_build__'] = JSON.stringify(values.immutable);
|
|
2433
|
+
}
|
|
2434
|
+
if (values.prerendered !== undefined) {
|
|
2435
|
+
replacements['__sveltekit_manifest_prerendered__'] = JSON.stringify(values.prerendered);
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
for (const file of fs.readdirSync(dir)) {
|
|
2439
|
+
const file_path = `${dir}/${file}`;
|
|
2440
|
+
const stat = fs.statSync(file_path);
|
|
2441
|
+
|
|
2442
|
+
if (stat.isDirectory()) {
|
|
2443
|
+
replace_manifest_placeholder_strings(file_path, values);
|
|
2444
|
+
continue;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
if (!file.endsWith('.js')) continue;
|
|
2448
|
+
|
|
2449
|
+
let code = read(file_path);
|
|
2450
|
+
let changed = false;
|
|
2451
|
+
|
|
2452
|
+
for (const [sentinel, replacement] of Object.entries(replacements)) {
|
|
2453
|
+
if (code.includes(sentinel)) {
|
|
2454
|
+
code = code.replaceAll(`"${sentinel}"`, replacement);
|
|
2455
|
+
changed = true;
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
if (changed) {
|
|
2460
|
+
fs.writeFileSync(file_path, code);
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
};
|
|
2464
|
+
|
|
2465
|
+
/**
|
|
2466
|
+
* Normalises the build output to a consistent format, handling watch mode and multiple environments
|
|
2467
|
+
* @param {string} name The name of the environment
|
|
2468
|
+
* @param {Rolldown.RolldownOutput | Rolldown.RolldownOutput[] | Rolldown.RolldownWatcher} build The return value of builder.build
|
|
2469
|
+
* @param {Map<string, Rolldown.RolldownOutput['output']>} build_output_map
|
|
2470
|
+
* @returns {Promise<Rolldown.RolldownOutput['output']>}
|
|
2471
|
+
*/
|
|
2472
|
+
async function normalise_build(name, build, build_output_map) {
|
|
2473
|
+
if ('output' in build) {
|
|
2474
|
+
return build.output;
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
if (Array.isArray(build)) {
|
|
2478
|
+
return build[0].output;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2481
|
+
/** @type {PromiseWithResolvers<void>} */
|
|
2482
|
+
const bundling = Promise.withResolvers();
|
|
2483
|
+
|
|
2484
|
+
build.on('event', async (event) => {
|
|
2485
|
+
if (event.code === 'ERROR') {
|
|
2486
|
+
await build.close();
|
|
2487
|
+
return bundling.reject(event.error);
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
if (event.code === 'BUNDLE_END') {
|
|
2491
|
+
await build.close();
|
|
2492
|
+
return bundling.resolve();
|
|
2493
|
+
}
|
|
2494
|
+
});
|
|
2495
|
+
|
|
2496
|
+
await bundling.promise;
|
|
2497
|
+
|
|
2498
|
+
return /** @type {Rolldown.RolldownOutput['output']} */ (build_output_map.get(name));
|
|
2499
|
+
}
|