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