@sveltejs/kit 3.0.0-next.10 → 3.0.0-next.12
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 +1 -1
- package/src/cli.js +8 -8
- package/src/constants.js +3 -1
- package/src/core/adapt/builder.js +3 -6
- package/src/core/config/index.js +6 -1
- package/src/core/config/options.js +54 -104
- package/src/core/env.js +25 -11
- package/src/core/postbuild/fallback.js +2 -1
- package/src/core/postbuild/prerender.js +75 -28
- package/src/core/postbuild/queue.js +2 -1
- package/src/core/sync/sync.js +11 -14
- package/src/core/sync/utils.js +21 -1
- package/src/core/sync/{write_non_ambient.js → write_app_types.js} +23 -21
- package/src/core/sync/write_client_manifest.js +4 -12
- package/src/core/sync/write_env.js +6 -4
- package/src/core/sync/write_server.js +12 -17
- package/src/core/sync/write_tsconfig/index.js +245 -0
- package/src/core/sync/write_tsconfig/utils.js +162 -0
- package/src/core/sync/write_types/index.js +80 -88
- package/src/core/utils.js +28 -3
- package/src/exports/env/index.js +68 -3
- package/src/exports/internal/env.js +6 -3
- package/src/exports/internal/server/index.js +3 -1
- package/src/exports/params.js +9 -4
- package/src/exports/public.d.ts +69 -71
- package/src/exports/vite/dev/index.js +112 -56
- package/src/exports/vite/index.js +483 -258
- package/src/exports/vite/module_ids.js +2 -2
- package/src/exports/vite/preview/index.js +3 -2
- package/src/exports/vite/utils.js +21 -10
- package/src/runner.js +13 -0
- package/src/runtime/app/forms.js +4 -0
- package/src/runtime/app/manifest/index.js +1 -0
- package/src/runtime/app/paths/client.js +30 -30
- package/src/runtime/app/paths/internal/client.js +26 -0
- package/src/runtime/app/paths/server.js +23 -10
- package/src/runtime/app/paths/types.d.ts +11 -19
- package/src/runtime/app/server/index.js +1 -1
- package/src/runtime/app/server/remote/command.js +12 -7
- package/src/runtime/app/server/remote/form.js +29 -26
- package/src/runtime/app/server/remote/prerender.js +9 -2
- package/src/runtime/app/server/remote/query.js +6 -5
- package/src/runtime/app/server/remote/shared.js +48 -30
- package/src/runtime/app/service-worker/index.js +24 -0
- package/src/runtime/app/state/index.js +1 -1
- package/src/runtime/client/client.js +46 -9
- package/src/runtime/client/ndjson.js +1 -1
- package/src/runtime/client/remote-functions/form.svelte.js +43 -51
- package/src/runtime/client/remote-functions/query/index.js +2 -2
- package/src/runtime/client/remote-functions/query-batch.svelte.js +2 -3
- package/src/runtime/client/remote-functions/query-live/iterator.js +5 -2
- package/src/runtime/client/remote-functions/shared.svelte.js +4 -1
- package/src/runtime/client/state.svelte.js +54 -21
- package/src/runtime/client/stream.js +3 -2
- package/src/runtime/form-utils.js +89 -54
- package/src/runtime/server/cookie.js +1 -1
- package/src/runtime/server/data/index.js +32 -29
- package/src/runtime/server/errors.js +135 -0
- package/src/runtime/server/fetch.js +1 -1
- package/src/runtime/server/index.js +20 -10
- package/src/runtime/server/internal.js +25 -0
- package/src/runtime/server/page/actions.js +4 -3
- package/src/runtime/server/page/data_serializer.js +10 -10
- package/src/runtime/server/page/index.js +3 -2
- package/src/runtime/server/page/load_data.js +1 -1
- package/src/runtime/server/page/render.js +22 -35
- package/src/runtime/server/page/respond_with_error.js +6 -5
- package/src/runtime/server/{remote.js → remote-functions.js} +67 -36
- package/src/runtime/server/respond.js +58 -20
- package/src/runtime/server/sourcemaps.js +183 -0
- package/src/runtime/server/utils.js +12 -157
- package/src/types/ambient-private.d.ts +10 -0
- package/src/types/ambient.d.ts +22 -27
- package/src/types/global-private.d.ts +12 -5
- package/src/types/internal.d.ts +19 -9
- package/src/types/private.d.ts +8 -0
- package/src/utils/escape.js +9 -25
- package/src/utils/features.js +1 -1
- package/src/utils/fork.js +7 -2
- package/src/utils/page_nodes.js +3 -5
- package/src/utils/url.js +12 -0
- package/src/version.js +1 -1
- package/types/index.d.ts +152 -120
- package/types/index.d.ts.map +6 -1
- package/src/core/sync/write_ambient.js +0 -18
- package/src/core/sync/write_tsconfig.js +0 -258
- package/src/runtime/shared-server.js +0 -7
- /package/src/core/sync/{write_tsconfig_test → write_tsconfig/test-app}/package.json +0 -0
|
@@ -7,11 +7,13 @@ import fs from 'node:fs';
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import process from 'node:process';
|
|
9
9
|
import { styleText } from 'node:util';
|
|
10
|
+
import MagicString from 'magic-string';
|
|
10
11
|
import { loadEnv } from 'vite';
|
|
11
12
|
import { exactRegex, prefixRegex } from 'rolldown/filter';
|
|
12
13
|
|
|
13
14
|
import { copy, mkdirp, read, resolve_entry, rimraf } from '../../utils/filesystem.js';
|
|
14
15
|
import { posixify } from '../../utils/os.js';
|
|
16
|
+
import { to_fs } from '../../utils/vite.js';
|
|
15
17
|
import {
|
|
16
18
|
create_sveltekit_env,
|
|
17
19
|
create_sveltekit_env_public,
|
|
@@ -22,19 +24,20 @@ import {
|
|
|
22
24
|
create_exported_declarations
|
|
23
25
|
} from '../../core/env.js';
|
|
24
26
|
import * as sync from '../../core/sync/sync.js';
|
|
25
|
-
import { create_assets } from '../../core/sync/create_manifest_data/index.js';
|
|
26
27
|
import { load_and_validate_params } from '../../utils/params.js';
|
|
27
28
|
import { runtime_directory, logger } from '../../core/utils.js';
|
|
28
29
|
import { generate_manifest } from '../../core/generate_manifest/index.js';
|
|
29
30
|
import { build_server_nodes } from './build/build_server.js';
|
|
30
31
|
import { find_deps, resolve_symlinks } from './build/utils.js';
|
|
31
|
-
import { dev } from './dev/index.js';
|
|
32
|
+
import { dev, invalidate_module } from './dev/index.js';
|
|
32
33
|
import { preview } from './preview/index.js';
|
|
33
34
|
import {
|
|
34
35
|
error_for_missing_config,
|
|
35
36
|
get_config_aliases,
|
|
36
37
|
normalize_id,
|
|
37
|
-
|
|
38
|
+
remote_module_pattern,
|
|
39
|
+
server_only_directory_pattern,
|
|
40
|
+
server_only_module_pattern
|
|
38
41
|
} from './utils.js';
|
|
39
42
|
import { stackless } from '../../utils/error.js';
|
|
40
43
|
import { write_client_manifest } from '../../core/sync/write_client_manifest.js';
|
|
@@ -47,11 +50,10 @@ import { get_import_aliases, get_hash_import_keys } from '../../utils/imports.js
|
|
|
47
50
|
import {
|
|
48
51
|
app_env_private,
|
|
49
52
|
app_server,
|
|
50
|
-
service_worker,
|
|
51
53
|
sveltekit_env,
|
|
52
54
|
sveltekit_env_private,
|
|
53
55
|
sveltekit_env_service_worker,
|
|
54
|
-
|
|
56
|
+
sveltekit_manifest_data,
|
|
55
57
|
sveltekit_env_public_client,
|
|
56
58
|
sveltekit_env_public_server
|
|
57
59
|
} from './module_ids.js';
|
|
@@ -60,6 +62,7 @@ import { compact } from '../../utils/array.js';
|
|
|
60
62
|
import { should_ignore, has_children } from './static_analysis/utils.js';
|
|
61
63
|
import { process_config, split_config, validate_config } from '../../core/config/index.js';
|
|
62
64
|
import { treeshake_prerendered_remotes } from './build/remote.js';
|
|
65
|
+
import { get_runner } from '../../runner.js';
|
|
63
66
|
|
|
64
67
|
/**
|
|
65
68
|
* The posix-ified root of the project based on the Vite configuration.
|
|
@@ -98,8 +101,7 @@ const enforced_config = {
|
|
|
98
101
|
resolve: {
|
|
99
102
|
alias: {
|
|
100
103
|
$app: true,
|
|
101
|
-
$env: true
|
|
102
|
-
'$service-worker': true
|
|
104
|
+
$env: true
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
};
|
|
@@ -299,9 +301,6 @@ function kit({ svelte_config }) {
|
|
|
299
301
|
|
|
300
302
|
/** @type {string | null} */
|
|
301
303
|
let service_worker_entry_file;
|
|
302
|
-
/** @type {import('node:path').ParsedPath} */
|
|
303
|
-
let parsed_service_worker;
|
|
304
|
-
|
|
305
304
|
/** @type {string} */
|
|
306
305
|
let normalized_cwd;
|
|
307
306
|
/** @type {Array<{ alias: string, path: string }>} */
|
|
@@ -402,11 +401,23 @@ function kit({ svelte_config }) {
|
|
|
402
401
|
// dev and preview config can be shared
|
|
403
402
|
/** @type {UserConfig} */
|
|
404
403
|
const new_config = {
|
|
404
|
+
environments: {
|
|
405
|
+
ssr: {
|
|
406
|
+
build: {
|
|
407
|
+
sourcemap:
|
|
408
|
+
config.environments?.ssr?.build?.sourcemap ?? config.build?.sourcemap ?? true
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
},
|
|
405
412
|
resolve: {
|
|
406
413
|
alias: [
|
|
407
414
|
{ find: '__SERVER__', replacement: `${generated}/server` },
|
|
408
415
|
{ find: '$app', replacement: `${runtime_directory}/app` },
|
|
409
416
|
{ find: '$env', replacement: `${runtime_directory}/env` },
|
|
417
|
+
{
|
|
418
|
+
find: '__sveltekit/server',
|
|
419
|
+
replacement: `${runtime_directory}/server/internal.js`
|
|
420
|
+
},
|
|
410
421
|
...get_config_aliases(kit, root)
|
|
411
422
|
]
|
|
412
423
|
},
|
|
@@ -458,30 +469,33 @@ function kit({ svelte_config }) {
|
|
|
458
469
|
}
|
|
459
470
|
};
|
|
460
471
|
|
|
472
|
+
// externalize .remote.js files to stop dependency tracing during prebundling
|
|
461
473
|
if (kit.experimental.remoteFunctions) {
|
|
462
|
-
// treat .remote.js files as empty for the purposes of prebundling
|
|
463
|
-
const remote_id_filter = new RegExp(
|
|
464
|
-
`.remote(${kit.moduleExtensions.join('|')})$`.replaceAll('.', '\\.')
|
|
465
|
-
);
|
|
466
474
|
// @ts-expect-error optimizeDeps is already set above
|
|
467
475
|
new_config.optimizeDeps.rolldownOptions ??= {};
|
|
468
476
|
// @ts-expect-error
|
|
469
477
|
new_config.optimizeDeps.rolldownOptions.plugins ??= [];
|
|
470
478
|
// @ts-expect-error
|
|
471
|
-
new_config.optimizeDeps.rolldownOptions.plugins.push(
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
479
|
+
new_config.optimizeDeps.rolldownOptions.plugins.push(
|
|
480
|
+
/** @type {Rolldown.Plugin} */ ({
|
|
481
|
+
name: 'vite-plugin-sveltekit-setup:optimize-remote-functions',
|
|
482
|
+
resolveId: {
|
|
483
|
+
filter: { id: remote_module_pattern },
|
|
484
|
+
async handler(id, importer) {
|
|
485
|
+
const resolved = await this.resolve(id, importer, { skipSelf: true });
|
|
486
|
+
if (!resolved) return { id, external: true };
|
|
487
|
+
// a servable /@fs url; 'absolute' stops rolldown relativizing it in the deps bundle
|
|
488
|
+
return { id: to_fs(resolved.id), external: 'absolute' };
|
|
489
|
+
}
|
|
477
490
|
}
|
|
478
|
-
}
|
|
479
|
-
|
|
491
|
+
})
|
|
492
|
+
);
|
|
480
493
|
}
|
|
481
494
|
|
|
482
495
|
const define = {
|
|
483
496
|
__SVELTEKIT_APP_DIR__: s(posixify(kit.appDir)),
|
|
484
497
|
__SVELTEKIT_APP_VERSION__: s(kit.version.name),
|
|
498
|
+
__SVELTEKIT_APP_VERSION_CHECKS_ENABLED__: s(kit.output.bundleStrategy !== 'inline'),
|
|
485
499
|
__SVELTEKIT_EMBEDDED__: s(kit.embedded),
|
|
486
500
|
__SVELTEKIT_FORK_PRELOADS__: s(kit.experimental.forkPreloads),
|
|
487
501
|
__SVELTEKIT_PATHS_ASSETS__: s(kit.paths.assets),
|
|
@@ -493,7 +507,6 @@ function kit({ svelte_config }) {
|
|
|
493
507
|
__SVELTEKIT_SUPPORTS_ASYNC__: s(
|
|
494
508
|
svelte_config.compilerOptions?.experimental?.async ?? false
|
|
495
509
|
),
|
|
496
|
-
__SVELTEKIT_ROOT__: s(root),
|
|
497
510
|
__SVELTEKIT_DEV__: s(!is_build)
|
|
498
511
|
};
|
|
499
512
|
|
|
@@ -602,14 +615,10 @@ function kit({ svelte_config }) {
|
|
|
602
615
|
);
|
|
603
616
|
|
|
604
617
|
for (const id of [sveltekit_env, sveltekit_env_public_client]) {
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if (module) {
|
|
608
|
-
server.moduleGraph.invalidateModule(module);
|
|
609
|
-
}
|
|
618
|
+
invalidate_module(server, id);
|
|
610
619
|
}
|
|
611
620
|
|
|
612
|
-
server.
|
|
621
|
+
server.hot.send({ type: 'full-reload' });
|
|
613
622
|
}
|
|
614
623
|
});
|
|
615
624
|
},
|
|
@@ -620,18 +629,13 @@ function kit({ svelte_config }) {
|
|
|
620
629
|
|
|
621
630
|
resolveId: {
|
|
622
631
|
filter: {
|
|
623
|
-
id: [
|
|
632
|
+
id: [prefixRegex('__sveltekit/')]
|
|
624
633
|
},
|
|
625
634
|
handler(id) {
|
|
626
635
|
if (id === '__sveltekit/manifest') {
|
|
627
636
|
return `${out_dir}/generated/client-optimized/app.js`;
|
|
628
637
|
}
|
|
629
638
|
|
|
630
|
-
if (id === '$service-worker') {
|
|
631
|
-
// ids with :$ don't work with reverse proxies like nginx
|
|
632
|
-
return `\0virtual:${id.substring(1)}`;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
639
|
if (id === '__sveltekit/remote') {
|
|
636
640
|
return `${runtime_directory}/client/remote-functions/index.js`;
|
|
637
641
|
}
|
|
@@ -643,19 +647,18 @@ function kit({ svelte_config }) {
|
|
|
643
647
|
load: {
|
|
644
648
|
filter: {
|
|
645
649
|
id: [
|
|
646
|
-
exactRegex(service_worker),
|
|
647
650
|
exactRegex(sveltekit_env),
|
|
648
651
|
exactRegex(sveltekit_env_private),
|
|
649
652
|
exactRegex(sveltekit_env_public_client),
|
|
650
653
|
exactRegex(sveltekit_env_public_server),
|
|
651
654
|
exactRegex(sveltekit_env_service_worker),
|
|
652
|
-
exactRegex(
|
|
655
|
+
exactRegex(sveltekit_manifest_data)
|
|
653
656
|
]
|
|
654
657
|
},
|
|
655
658
|
handler(id) {
|
|
656
659
|
switch (id) {
|
|
657
|
-
case
|
|
658
|
-
return
|
|
660
|
+
case sveltekit_manifest_data:
|
|
661
|
+
return create_manifest_data_module(is_build, manifest_data);
|
|
659
662
|
|
|
660
663
|
case sveltekit_env:
|
|
661
664
|
return create_sveltekit_env(explicit_env_config, env, explicit_env_entry, !is_build);
|
|
@@ -682,27 +685,17 @@ function kit({ svelte_config }) {
|
|
|
682
685
|
? create_sveltekit_env_service_worker(
|
|
683
686
|
explicit_env_config,
|
|
684
687
|
env,
|
|
688
|
+
kit.version.name,
|
|
685
689
|
kit_global,
|
|
686
690
|
kit.paths.base,
|
|
687
691
|
kit.appDir
|
|
688
692
|
)
|
|
689
|
-
: create_sveltekit_env_service_worker_dev(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
export let manifest = null;
|
|
696
|
-
|
|
697
|
-
export function set_read_implementation(fn) {
|
|
698
|
-
read_implementation = fn;
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
export function set_manifest(_) {
|
|
702
|
-
manifest = _;
|
|
703
|
-
}
|
|
704
|
-
`;
|
|
705
|
-
}
|
|
693
|
+
: create_sveltekit_env_service_worker_dev(
|
|
694
|
+
explicit_env_config,
|
|
695
|
+
env,
|
|
696
|
+
kit.version.name,
|
|
697
|
+
kit_global
|
|
698
|
+
);
|
|
706
699
|
}
|
|
707
700
|
}
|
|
708
701
|
}
|
|
@@ -710,10 +703,6 @@ function kit({ svelte_config }) {
|
|
|
710
703
|
|
|
711
704
|
/** @type {Map<string, Set<string>>} */
|
|
712
705
|
const import_map = new Map();
|
|
713
|
-
// Matches any ID that has .server. in its filename
|
|
714
|
-
const server_only_module_pattern = /\.server\.[^/]+$/;
|
|
715
|
-
// Matches any ID that has /server/ in its path
|
|
716
|
-
const server_only_directory_pattern = /\/server\//;
|
|
717
706
|
|
|
718
707
|
/**
|
|
719
708
|
* Ensures that client-side code can't accidentally import server-side code,
|
|
@@ -729,7 +718,7 @@ function kit({ svelte_config }) {
|
|
|
729
718
|
|
|
730
719
|
applyToEnvironment(environment) {
|
|
731
720
|
// the import map is only read for client-side violations in `load`, so skip other environments
|
|
732
|
-
return environment.config.consumer === 'client'
|
|
721
|
+
return environment.config.consumer === 'client';
|
|
733
722
|
},
|
|
734
723
|
|
|
735
724
|
resolveId: {
|
|
@@ -769,24 +758,21 @@ function kit({ svelte_config }) {
|
|
|
769
758
|
]
|
|
770
759
|
},
|
|
771
760
|
handler(id) {
|
|
772
|
-
// skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context
|
|
773
|
-
const is_internal =
|
|
774
|
-
id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules);
|
|
775
|
-
|
|
776
761
|
const normalized = normalize_id(id, normalized_aliases, normalized_cwd);
|
|
777
762
|
|
|
778
|
-
|
|
779
|
-
// except those inside the routes or assets directories
|
|
780
|
-
const is_in_routes = id.startsWith(normalized_routes + '/');
|
|
781
|
-
const is_in_assets = id.startsWith(normalized_assets + '/');
|
|
782
|
-
const is_server_only_directory =
|
|
783
|
-
is_internal && !is_in_routes && !is_in_assets && server_only_directory_pattern.test(id);
|
|
763
|
+
let is_server_only = normalized === '$app/env/private' || normalized === '$app/server';
|
|
784
764
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
765
|
+
// skip .server.js files outside the cwd or in node_modules, as the filename might not mean 'server-only module' in this context
|
|
766
|
+
if (id.startsWith(normalized_cwd) && !id.startsWith(normalized_node_modules)) {
|
|
767
|
+
// e.g. `server.ts` or `foo.server.ts`
|
|
768
|
+
is_server_only ||= server_only_module_pattern.test(id);
|
|
769
|
+
|
|
770
|
+
// e.g. `server/foo.ts`, unless in `src/routes` or `static`
|
|
771
|
+
is_server_only ||=
|
|
772
|
+
server_only_directory_pattern.test(id) &&
|
|
773
|
+
!id.startsWith(normalized_routes + '/') &&
|
|
774
|
+
!id.startsWith(normalized_assets + '/');
|
|
775
|
+
}
|
|
790
776
|
|
|
791
777
|
if (!is_server_only) return;
|
|
792
778
|
|
|
@@ -803,6 +789,10 @@ function kit({ svelte_config }) {
|
|
|
803
789
|
if (manifest_data.hooks.client) entrypoints.add(manifest_data.hooks.client);
|
|
804
790
|
if (manifest_data.hooks.universal) entrypoints.add(manifest_data.hooks.universal);
|
|
805
791
|
|
|
792
|
+
if (service_worker_entry_file) {
|
|
793
|
+
entrypoints.add(posixify(path.relative(root, service_worker_entry_file)));
|
|
794
|
+
}
|
|
795
|
+
|
|
806
796
|
// Walk up the import graph from the server-only module, looking for a chain
|
|
807
797
|
// that leads back to a client entrypoint. We search all candidates (not just
|
|
808
798
|
// the first) because a module can be imported by both server and client code,
|
|
@@ -837,6 +827,10 @@ function kit({ svelte_config }) {
|
|
|
837
827
|
const chain = find_chain(normalized, [normalized]);
|
|
838
828
|
|
|
839
829
|
if (chain) {
|
|
830
|
+
if (chain.some((id) => remote_module_pattern.test(id))) {
|
|
831
|
+
error_for_missing_config('remote functions', 'experimental.remoteFunctions', 'true');
|
|
832
|
+
}
|
|
833
|
+
|
|
840
834
|
const pyramid = chain
|
|
841
835
|
.reverse()
|
|
842
836
|
.map((id, i) => {
|
|
@@ -907,109 +901,115 @@ function kit({ svelte_config }) {
|
|
|
907
901
|
dev_server = _dev_server;
|
|
908
902
|
},
|
|
909
903
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
904
|
+
transform: {
|
|
905
|
+
filter: {
|
|
906
|
+
id: remote_module_pattern
|
|
907
|
+
},
|
|
908
|
+
async handler(code, id) {
|
|
909
|
+
const file = posixify(path.relative(root, id));
|
|
910
|
+
const remote = {
|
|
911
|
+
hash: hash(file),
|
|
912
|
+
file
|
|
913
|
+
};
|
|
915
914
|
|
|
916
|
-
|
|
917
|
-
const remote = {
|
|
918
|
-
hash: hash(file),
|
|
919
|
-
file
|
|
920
|
-
};
|
|
915
|
+
remotes.push(remote);
|
|
921
916
|
|
|
922
|
-
|
|
917
|
+
if (this.environment.config.consumer !== 'client') {
|
|
918
|
+
// we need to add an `await Promise.resolve()` because if the user imports this function
|
|
919
|
+
// on the client AND in a load function when loading the client module we will trigger
|
|
920
|
+
// an import during dev. During a link preload, the module can be mistakenly
|
|
921
|
+
// loaded and transformed twice and the first time all its exports would be undefined
|
|
922
|
+
// triggering a dev server error. By adding a microtask we ensure that the module is fully loaded
|
|
923
|
+
const ms = new MagicString(code);
|
|
923
924
|
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
925
|
+
// Extra newlines to prevent syntax errors around missing semicolons or comments
|
|
926
|
+
ms.append(
|
|
927
|
+
'\n\n' +
|
|
928
|
+
dedent`
|
|
929
|
+
import * as $$_self_$$ from './${path.basename(id)}';
|
|
930
|
+
import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal/server';
|
|
930
931
|
|
|
931
|
-
|
|
932
|
-
code +=
|
|
933
|
-
'\n\n' +
|
|
934
|
-
dedent`
|
|
935
|
-
import * as $$_self_$$ from './${path.basename(id)}';
|
|
936
|
-
import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal/server';
|
|
932
|
+
${dev_server ? 'await Promise.resolve()' : ''}
|
|
937
933
|
|
|
938
|
-
|
|
934
|
+
$$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)});
|
|
939
935
|
|
|
940
|
-
|
|
936
|
+
for (const [name, fn] of Object.entries($$_self_$$)) {
|
|
937
|
+
fn.__.id = ${s(remote.hash)} + '/' + name;
|
|
938
|
+
fn.__.name = name;
|
|
939
|
+
}
|
|
940
|
+
`
|
|
941
|
+
);
|
|
941
942
|
|
|
942
|
-
for
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
type: 'chunk',
|
|
954
|
-
id: `\0sveltekit-remote:${remote.hash}`,
|
|
955
|
-
name: `remote-${remote.hash}`
|
|
956
|
-
});
|
|
957
|
-
emitted_remote_hashes.add(remote.hash);
|
|
943
|
+
// Emit a dedicated entry chunk for this remote in SSR builds (prod only)
|
|
944
|
+
if (!dev_server) {
|
|
945
|
+
remote_original_by_hash.set(remote.hash, id);
|
|
946
|
+
if (!emitted_remote_hashes.has(remote.hash)) {
|
|
947
|
+
this.emitFile({
|
|
948
|
+
type: 'chunk',
|
|
949
|
+
id: `\0sveltekit-remote:${remote.hash}`,
|
|
950
|
+
name: `remote-${remote.hash}`
|
|
951
|
+
});
|
|
952
|
+
emitted_remote_hashes.add(remote.hash);
|
|
953
|
+
}
|
|
958
954
|
}
|
|
959
|
-
}
|
|
960
955
|
|
|
961
|
-
|
|
962
|
-
|
|
956
|
+
return {
|
|
957
|
+
code: ms.toString(),
|
|
958
|
+
map: ms.generateMap({ hires: 'boundary' })
|
|
959
|
+
};
|
|
960
|
+
}
|
|
963
961
|
|
|
964
|
-
|
|
962
|
+
// For the client, read the exports and create a new module that only contains fetch functions with the correct metadata
|
|
965
963
|
|
|
966
|
-
|
|
967
|
-
|
|
964
|
+
/** @type {Map<string, RemoteInternals['type']>} */
|
|
965
|
+
const map = new Map();
|
|
968
966
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
967
|
+
// in dev, load the server module here (which will result in this hook
|
|
968
|
+
// being called again with `opts.ssr === true` if the module isn't
|
|
969
|
+
// already loaded) so we can determine what it exports
|
|
970
|
+
if (dev_server) {
|
|
971
|
+
const module = await get_runner(dev_server).import(id);
|
|
974
972
|
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
973
|
+
for (const [name, value] of Object.entries(module)) {
|
|
974
|
+
const type = value?.__?.type;
|
|
975
|
+
if (type) {
|
|
976
|
+
map.set(name, type);
|
|
977
|
+
}
|
|
979
978
|
}
|
|
980
979
|
}
|
|
981
|
-
}
|
|
982
980
|
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
981
|
+
// in prod, we already built and analysed the server code before
|
|
982
|
+
// building the client code, so `remotes` is populated
|
|
983
|
+
else if (build_metadata?.remotes) {
|
|
984
|
+
const exports = build_metadata?.remotes.get(remote.hash);
|
|
985
|
+
if (!exports) throw new Error('Expected to find metadata for remote file ' + id);
|
|
988
986
|
|
|
989
|
-
|
|
990
|
-
|
|
987
|
+
for (const [name, value] of exports) {
|
|
988
|
+
map.set(name, value.type);
|
|
989
|
+
}
|
|
991
990
|
}
|
|
992
|
-
}
|
|
993
991
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
992
|
+
const { namespace, declarations, reexports } = create_exported_declarations(
|
|
993
|
+
map.keys(),
|
|
994
|
+
(name, ns) => `${ns}.${map.get(name)}('${remote.hash}/${name}')`,
|
|
995
|
+
'__remote'
|
|
996
|
+
);
|
|
999
997
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
998
|
+
let result = `import * as ${namespace} from '__sveltekit/remote';\n\n${declarations.join('\n')}`;
|
|
999
|
+
if (reexports.length > 0) {
|
|
1000
|
+
result += `\nexport { ${reexports.join(', ')} };`;
|
|
1001
|
+
}
|
|
1002
|
+
result += '\n';
|
|
1005
1003
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1004
|
+
if (dev_server) {
|
|
1005
|
+
result += `\nimport.meta.hot?.accept();\n`;
|
|
1006
|
+
}
|
|
1009
1007
|
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1008
|
+
return {
|
|
1009
|
+
code: result,
|
|
1010
|
+
map: null
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
1013
|
}
|
|
1014
1014
|
};
|
|
1015
1015
|
|
|
@@ -1043,7 +1043,7 @@ function kit({ svelte_config }) {
|
|
|
1043
1043
|
/** @type {Set<string>} */
|
|
1044
1044
|
let build_files;
|
|
1045
1045
|
/** @type {string} */
|
|
1046
|
-
let
|
|
1046
|
+
let manifest_data_code;
|
|
1047
1047
|
|
|
1048
1048
|
/**
|
|
1049
1049
|
* Creates the service worker virtual modules
|
|
@@ -1054,7 +1054,6 @@ function kit({ svelte_config }) {
|
|
|
1054
1054
|
|
|
1055
1055
|
config(config) {
|
|
1056
1056
|
service_worker_entry_file = resolve_entry(kit.files.serviceWorker);
|
|
1057
|
-
parsed_service_worker = path.parse(kit.files.serviceWorker);
|
|
1058
1057
|
|
|
1059
1058
|
if (!service_worker_entry_file) return;
|
|
1060
1059
|
|
|
@@ -1109,46 +1108,23 @@ function kit({ svelte_config }) {
|
|
|
1109
1108
|
return environment.name === 'serviceWorker';
|
|
1110
1109
|
},
|
|
1111
1110
|
|
|
1112
|
-
resolveId
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
const parsed_importer = path.parse(importer);
|
|
1118
|
-
|
|
1119
|
-
const importer_is_service_worker =
|
|
1120
|
-
parsed_importer.dir === parsed_service_worker.dir &&
|
|
1121
|
-
parsed_importer.name === parsed_service_worker.name;
|
|
1122
|
-
|
|
1123
|
-
if (
|
|
1124
|
-
importer_is_service_worker &&
|
|
1125
|
-
id !== '$service-worker' &&
|
|
1126
|
-
id !== 'virtual:$app/env/public' &&
|
|
1127
|
-
id !== '__sveltekit/env/service-worker'
|
|
1128
|
-
) {
|
|
1129
|
-
throw new Error(
|
|
1130
|
-
`Cannot import ${normalize_id(
|
|
1131
|
-
id,
|
|
1132
|
-
normalized_aliases,
|
|
1133
|
-
normalized_cwd
|
|
1134
|
-
)} into service-worker code. Only the modules $service-worker and $app/env/public are available in service workers.`
|
|
1135
|
-
);
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
if (id.startsWith('$app/') || id === '$service-worker') {
|
|
1140
|
-
// ids with :$ don't work with reverse proxies like nginx
|
|
1141
|
-
return `\0virtual:${id.substring(1)}`;
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
|
-
if (id.startsWith('__sveltekit')) {
|
|
1111
|
+
resolveId: {
|
|
1112
|
+
filter: {
|
|
1113
|
+
id: [prefixRegex('__sveltekit/')]
|
|
1114
|
+
},
|
|
1115
|
+
handler(id) {
|
|
1145
1116
|
return `\0virtual:${id}`;
|
|
1146
1117
|
}
|
|
1147
1118
|
},
|
|
1148
1119
|
|
|
1149
1120
|
load: {
|
|
1150
1121
|
filter: {
|
|
1151
|
-
id: [
|
|
1122
|
+
id: [
|
|
1123
|
+
exactRegex('\0virtual:app/manifest'),
|
|
1124
|
+
exactRegex(sveltekit_manifest_data),
|
|
1125
|
+
exactRegex(sveltekit_env_service_worker),
|
|
1126
|
+
exactRegex(sveltekit_env_public_client)
|
|
1127
|
+
]
|
|
1152
1128
|
},
|
|
1153
1129
|
handler(id) {
|
|
1154
1130
|
if (!build_files) {
|
|
@@ -1171,36 +1147,33 @@ function kit({ svelte_config }) {
|
|
|
1171
1147
|
}
|
|
1172
1148
|
}
|
|
1173
1149
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
const base = "location.pathname.split('/').slice(0, -1).join('/')";
|
|
1177
|
-
|
|
1178
|
-
service_worker_code = dedent`
|
|
1179
|
-
export const base = /*@__PURE__*/ ${base};
|
|
1180
|
-
|
|
1181
|
-
export const build = [
|
|
1150
|
+
manifest_data_code = dedent`
|
|
1151
|
+
export const immutable = [
|
|
1182
1152
|
${Array.from(build_files)
|
|
1183
|
-
.map((file) =>
|
|
1153
|
+
.map((file) => s({ path: file }))
|
|
1184
1154
|
.join(',\n')}
|
|
1185
1155
|
];
|
|
1186
1156
|
|
|
1187
|
-
export const
|
|
1188
|
-
${manifest_data.assets
|
|
1189
|
-
.filter((asset) => kit.serviceWorker.files(asset.file))
|
|
1190
|
-
.map((asset) => `base + ${s(`/${asset.file}`)}`)
|
|
1191
|
-
.join(',\n')}
|
|
1157
|
+
export const assets = [
|
|
1158
|
+
${manifest_data.assets.map((asset) => s({ path: asset.file })).join(',\n')}
|
|
1192
1159
|
];
|
|
1193
1160
|
|
|
1194
1161
|
export const prerendered = [
|
|
1195
|
-
${prerendered.paths.map((path) =>
|
|
1162
|
+
${prerendered.paths.map((path) => s({ path: path.replace(kit.paths.base, '').slice(1) })).join(',\n')}
|
|
1196
1163
|
];
|
|
1197
1164
|
|
|
1198
|
-
export const
|
|
1165
|
+
export const routes = [
|
|
1166
|
+
${manifest_data.routes.map((route) => s({ id: route.id })).join(',\n')}
|
|
1167
|
+
];
|
|
1199
1168
|
`;
|
|
1200
1169
|
}
|
|
1201
1170
|
|
|
1202
|
-
if (id ===
|
|
1203
|
-
return
|
|
1171
|
+
if (id === '\0virtual:app/manifest') {
|
|
1172
|
+
return `export { immutable, assets, prerendered, routes } from '__sveltekit/manifest-data';`;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
if (id === sveltekit_manifest_data) {
|
|
1176
|
+
return manifest_data_code;
|
|
1204
1177
|
}
|
|
1205
1178
|
|
|
1206
1179
|
if (id === sveltekit_env_service_worker) {
|
|
@@ -1208,11 +1181,17 @@ function kit({ svelte_config }) {
|
|
|
1208
1181
|
? create_sveltekit_env_service_worker(
|
|
1209
1182
|
explicit_env_config,
|
|
1210
1183
|
env,
|
|
1184
|
+
kit.version.name,
|
|
1211
1185
|
kit_global,
|
|
1212
1186
|
kit.paths.base,
|
|
1213
1187
|
kit.appDir
|
|
1214
1188
|
)
|
|
1215
|
-
: create_sveltekit_env_service_worker_dev(
|
|
1189
|
+
: create_sveltekit_env_service_worker_dev(
|
|
1190
|
+
explicit_env_config,
|
|
1191
|
+
env,
|
|
1192
|
+
kit.version.name,
|
|
1193
|
+
kit_global
|
|
1194
|
+
);
|
|
1216
1195
|
}
|
|
1217
1196
|
|
|
1218
1197
|
if (id === sveltekit_env_public_client) {
|
|
@@ -1222,16 +1201,31 @@ function kit({ svelte_config }) {
|
|
|
1222
1201
|
`const env = ${kit_global}.env;`
|
|
1223
1202
|
);
|
|
1224
1203
|
}
|
|
1204
|
+
}
|
|
1205
|
+
},
|
|
1225
1206
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1207
|
+
generateBundle(_, bundle) {
|
|
1208
|
+
const invalid_modules = new Set();
|
|
1209
|
+
const modules = new Map([
|
|
1210
|
+
[`${runtime_directory}/app/forms.js`, '$app/forms'],
|
|
1211
|
+
[`${runtime_directory}/app/navigation.js`, '$app/navigation'],
|
|
1212
|
+
[`${runtime_directory}/app/state/index.js`, '$app/state']
|
|
1213
|
+
]);
|
|
1214
|
+
|
|
1215
|
+
for (const output of Object.values(bundle)) {
|
|
1216
|
+
if (output.type !== 'chunk') continue;
|
|
1217
|
+
|
|
1218
|
+
for (const id of output.moduleIds) {
|
|
1219
|
+
const module = modules.get(id);
|
|
1220
|
+
if (module) invalid_modules.add(module);
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
if (invalid_modules.size > 0) {
|
|
1233
1225
|
throw new Error(
|
|
1234
|
-
`Cannot import ${
|
|
1226
|
+
`Cannot import ${Array.from(modules.values())
|
|
1227
|
+
.filter((module) => invalid_modules.has(module))
|
|
1228
|
+
.join(', ')} into service-worker code.`
|
|
1235
1229
|
);
|
|
1236
1230
|
}
|
|
1237
1231
|
}
|
|
@@ -1243,17 +1237,19 @@ function kit({ svelte_config }) {
|
|
|
1243
1237
|
applyToEnvironment(environment) {
|
|
1244
1238
|
return !!service_worker_entry_file && environment.config.consumer === 'client';
|
|
1245
1239
|
},
|
|
1246
|
-
transform
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1240
|
+
transform: {
|
|
1241
|
+
handler(code, id) {
|
|
1242
|
+
if (id !== service_worker_entry_file) return;
|
|
1243
|
+
|
|
1244
|
+
// prepend the service worker with an import that configures
|
|
1245
|
+
// `env`, in case `$app/env/public` is imported. In production
|
|
1246
|
+
// this is required: dynamic public env vars aren't known at
|
|
1247
|
+
// build time, so `env.js` is loaded at runtime. In dev, the
|
|
1248
|
+
// imported module just inlines the current values instead.
|
|
1249
|
+
return {
|
|
1250
|
+
code: `import '__sveltekit/env/service-worker';\n${code}`
|
|
1251
|
+
};
|
|
1252
|
+
}
|
|
1257
1253
|
}
|
|
1258
1254
|
};
|
|
1259
1255
|
|
|
@@ -1437,9 +1433,26 @@ function kit({ svelte_config }) {
|
|
|
1437
1433
|
output: {
|
|
1438
1434
|
format: inline ? 'iife' : 'esm',
|
|
1439
1435
|
entryFileNames: `${app_immutable}/[name].[hash].js`,
|
|
1440
|
-
chunkFileNames:
|
|
1436
|
+
chunkFileNames: (/** @type {Rolldown.PreRenderedChunk} */ chunk_info) => {
|
|
1437
|
+
// The manifest data chunk gets a fixed (non-hashed) filename so
|
|
1438
|
+
// that importers' content hashes are stable regardless of the
|
|
1439
|
+
// manifest content — this breaks the content-hash feedback loop
|
|
1440
|
+
if (chunk_info.name === 'sveltekit-manifest') {
|
|
1441
|
+
return `${kit.appDir}/manifest.js`;
|
|
1442
|
+
}
|
|
1443
|
+
return `${app_immutable}/chunks/[hash].js`;
|
|
1444
|
+
},
|
|
1441
1445
|
codeSplitting:
|
|
1442
|
-
svelte_config.kit.output.bundleStrategy === 'split'
|
|
1446
|
+
svelte_config.kit.output.bundleStrategy === 'split'
|
|
1447
|
+
? {
|
|
1448
|
+
groups: [
|
|
1449
|
+
{
|
|
1450
|
+
name: 'sveltekit-manifest',
|
|
1451
|
+
test: sveltekit_manifest_data
|
|
1452
|
+
}
|
|
1453
|
+
]
|
|
1454
|
+
}
|
|
1455
|
+
: false
|
|
1443
1456
|
},
|
|
1444
1457
|
// This silences Rolldown warnings about not supporting `import.meta`
|
|
1445
1458
|
// for the `iife` output format. We don't care because it's
|
|
@@ -1518,7 +1531,18 @@ function kit({ svelte_config }) {
|
|
|
1518
1531
|
* @see https://vitejs.dev/guide/api-plugin.html#configureserver
|
|
1519
1532
|
*/
|
|
1520
1533
|
async configureServer(server) {
|
|
1521
|
-
return await dev(
|
|
1534
|
+
return await dev(
|
|
1535
|
+
server,
|
|
1536
|
+
vite_config,
|
|
1537
|
+
svelte_config,
|
|
1538
|
+
() => remotes,
|
|
1539
|
+
root,
|
|
1540
|
+
(data) => {
|
|
1541
|
+
manifest_data = data;
|
|
1542
|
+
// Invalidate the manifest data module so it reloads with new routes/files
|
|
1543
|
+
invalidate_module(server, sveltekit_manifest_data);
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1522
1546
|
},
|
|
1523
1547
|
|
|
1524
1548
|
/**
|
|
@@ -1574,6 +1598,15 @@ function kit({ svelte_config }) {
|
|
|
1574
1598
|
await builder.build(builder.environments.ssr)
|
|
1575
1599
|
);
|
|
1576
1600
|
|
|
1601
|
+
// Replace manifest placeholders in SSR output. `assets` and `routes`
|
|
1602
|
+
// are known from `manifest_data`. `immutable` and `prerendered` are not
|
|
1603
|
+
// known yet — they get sentinel strings that are replaced after
|
|
1604
|
+
// the client build and after prerendering respectively.
|
|
1605
|
+
replace_manifest_placeholder_variables(server_chunks, `${out}/server`, {
|
|
1606
|
+
assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
|
|
1607
|
+
routes: manifest_data.routes.map((route) => ({ id: route.id }))
|
|
1608
|
+
});
|
|
1609
|
+
|
|
1577
1610
|
const verbose = builder.config.logLevel === 'info';
|
|
1578
1611
|
const log = logger({ verbose });
|
|
1579
1612
|
|
|
@@ -1698,6 +1731,42 @@ function kit({ svelte_config }) {
|
|
|
1698
1731
|
read(`${out}/client/.vite/manifest.json`)
|
|
1699
1732
|
));
|
|
1700
1733
|
|
|
1734
|
+
// Replace manifest placeholders in client output. `immutable` is
|
|
1735
|
+
// computed from the Vite client manifest, `assets` and `routes`
|
|
1736
|
+
// from `manifest_data`. `prerendered` is left as a placeholder
|
|
1737
|
+
// for now — it's replaced after prerendering completes.
|
|
1738
|
+
/** @type {Set<string>} */
|
|
1739
|
+
const immutable = new Set();
|
|
1740
|
+
|
|
1741
|
+
/** @param {string} file */
|
|
1742
|
+
const add_immutable = (file) => {
|
|
1743
|
+
if (
|
|
1744
|
+
file.startsWith(`${kit.appDir}/immutable`) &&
|
|
1745
|
+
fs.existsSync(`${out}/client/${file}`)
|
|
1746
|
+
) {
|
|
1747
|
+
immutable.add(file);
|
|
1748
|
+
}
|
|
1749
|
+
};
|
|
1750
|
+
|
|
1751
|
+
for (const key in vite_manifest) {
|
|
1752
|
+
const { file, css = [], assets = [] } = vite_manifest[key];
|
|
1753
|
+
add_immutable(file);
|
|
1754
|
+
css.forEach(add_immutable);
|
|
1755
|
+
assets.forEach(add_immutable);
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
replace_manifest_placeholder_variables(client_chunks, `${out}/client`, {
|
|
1759
|
+
immutable: Array.from(immutable).map((file) => ({ path: file })),
|
|
1760
|
+
assets: manifest_data.assets.map((asset) => ({ path: asset.file })),
|
|
1761
|
+
routes: manifest_data.routes.map((route) => ({ id: route.id }))
|
|
1762
|
+
});
|
|
1763
|
+
|
|
1764
|
+
// Now that the client build is done, replace the `build` sentinel
|
|
1765
|
+
// in the SSR output with the real build files
|
|
1766
|
+
replace_manifest_placeholder_strings(`${out}/server`, {
|
|
1767
|
+
immutable: Array.from(immutable).map((file) => ({ path: file }))
|
|
1768
|
+
});
|
|
1769
|
+
|
|
1701
1770
|
/**
|
|
1702
1771
|
* @param {string} entry
|
|
1703
1772
|
* @param {boolean} [add_dynamic_css]
|
|
@@ -1844,17 +1913,51 @@ function kit({ svelte_config }) {
|
|
|
1844
1913
|
}
|
|
1845
1914
|
|
|
1846
1915
|
// ...and prerender
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1916
|
+
let prerender_results;
|
|
1917
|
+
try {
|
|
1918
|
+
prerender_results = await prerender({
|
|
1919
|
+
hash: kit.router.type === 'hash',
|
|
1920
|
+
out,
|
|
1921
|
+
manifest_path,
|
|
1922
|
+
metadata,
|
|
1923
|
+
verbose,
|
|
1924
|
+
env,
|
|
1925
|
+
vite_config_file: vite_config.configFile
|
|
1926
|
+
});
|
|
1927
|
+
|
|
1928
|
+
// this silly hack is necessary to ensure that stderr from prerender is flushed before we continue
|
|
1929
|
+
await new Promise((f) => setTimeout(f, 0));
|
|
1930
|
+
} catch (e) {
|
|
1931
|
+
if (e instanceof Error && e.message === '__handled__') {
|
|
1932
|
+
// error details are already logged inside `prerender`, don't duplicate them
|
|
1933
|
+
throw stackless('Prerendering failed');
|
|
1934
|
+
} else {
|
|
1935
|
+
// Unforeseen error, rethrow as-is
|
|
1936
|
+
throw e;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1856
1940
|
prerendered = prerender_results.prerendered;
|
|
1857
1941
|
|
|
1942
|
+
// Replace the `prerendered` sentinel in both SSR and client output
|
|
1943
|
+
// with the real prerendered paths. The other sentinels (`build`)
|
|
1944
|
+
// were already replaced after the client build.
|
|
1945
|
+
const prerendered_paths = prerendered.paths.map((p) => {
|
|
1946
|
+
return { path: p.replace(kit.paths.base, '').slice(1) };
|
|
1947
|
+
});
|
|
1948
|
+
|
|
1949
|
+
replace_manifest_placeholder_strings(`${out}/server`, { prerendered: prerendered_paths });
|
|
1950
|
+
replace_manifest_placeholder_strings(`${out}/client`, { prerendered: prerendered_paths });
|
|
1951
|
+
|
|
1952
|
+
// For `inline` strategy, the entry file was deleted and read into
|
|
1953
|
+
// `build_data.client.inline.script` — replace the sentinel there too
|
|
1954
|
+
if (build_data.client?.inline?.script) {
|
|
1955
|
+
build_data.client.inline.script = build_data.client.inline.script.replaceAll(
|
|
1956
|
+
'"__sveltekit_manifest_prerendered__"',
|
|
1957
|
+
JSON.stringify(prerendered_paths)
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1858
1961
|
await treeshake_prerendered_remotes(
|
|
1859
1962
|
vite,
|
|
1860
1963
|
out,
|
|
@@ -2015,21 +2118,143 @@ function find_overridden_config(config, resolved_config, enforced_config, path,
|
|
|
2015
2118
|
}
|
|
2016
2119
|
|
|
2017
2120
|
/**
|
|
2018
|
-
*
|
|
2121
|
+
* Creates the `$app/manifest` data module. During development, real values
|
|
2122
|
+
* are emitted for `assets` and `routes` (the only data known at that point).
|
|
2123
|
+
*
|
|
2124
|
+
* During build, bare identifier placeholders (fake globals) are emitted.
|
|
2125
|
+
* The bundler leaves these as unresolved global references in the output,
|
|
2126
|
+
* which are then replaced with real values by scanning the output chunks
|
|
2127
|
+
* after each build completes. This avoids the content-hash feedback loop:
|
|
2128
|
+
* the manifest data lives in its own chunk with a fixed filename, so
|
|
2129
|
+
* importers' hashes are stable regardless of the manifest content.
|
|
2130
|
+
*
|
|
2131
|
+
* @param {boolean} is_build
|
|
2132
|
+
* @param {ManifestData | undefined} manifest_data
|
|
2133
|
+
* @returns {string}
|
|
2019
2134
|
*/
|
|
2020
|
-
const
|
|
2021
|
-
if (
|
|
2022
|
-
|
|
2135
|
+
const create_manifest_data_module = (is_build, manifest_data) => {
|
|
2136
|
+
if (is_build) {
|
|
2137
|
+
// Bare identifiers (fake globals) — the bundler leaves these as
|
|
2138
|
+
// unresolved global references in the output. They are replaced
|
|
2139
|
+
// with real values by `replace_manifest_placeholder_variables`
|
|
2140
|
+
// after each build completes.
|
|
2141
|
+
return dedent`
|
|
2142
|
+
export const immutable = __SVELTEKIT_MANIFEST_IMMUTABLE__;
|
|
2143
|
+
export const assets = __SVELTEKIT_MANIFEST_ASSETS__;
|
|
2144
|
+
export const prerendered = __SVELTEKIT_MANIFEST_PRERENDERED__;
|
|
2145
|
+
export const routes = __SVELTEKIT_MANIFEST_ROUTES__;
|
|
2146
|
+
`;
|
|
2023
2147
|
}
|
|
2024
2148
|
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2149
|
+
// In dev, `manifest_data` may not be set yet on the very first load,
|
|
2150
|
+
// but `configureServer` (which calls `sync.create`) runs before any
|
|
2151
|
+
// module is served, so it will be set by the time this is called.
|
|
2152
|
+
const routes = manifest_data?.routes.map((route) => s({ id: route.id })).join(',\n') ?? '';
|
|
2153
|
+
const assets = manifest_data?.assets.map((asset) => s({ path: asset.file })).join(',\n') ?? '';
|
|
2154
|
+
|
|
2155
|
+
return dedent`
|
|
2156
|
+
// empty during dev
|
|
2157
|
+
export const immutable = [];
|
|
2158
|
+
export const prerendered = [];
|
|
2159
|
+
|
|
2160
|
+
export const assets = [
|
|
2161
|
+
${assets}
|
|
2162
|
+
];
|
|
2163
|
+
|
|
2164
|
+
export const routes = [
|
|
2165
|
+
${routes}
|
|
2166
|
+
];
|
|
2167
|
+
`;
|
|
2168
|
+
};
|
|
2169
|
+
|
|
2170
|
+
/**
|
|
2171
|
+
* Replaces manifest data placeholder identifiers in output chunks with real
|
|
2172
|
+
* values, or strings that are valid JS (so thecode doesn't crash during prerendering)
|
|
2173
|
+
* but findable on disk for later replacement by `replace_manifest_placeholder_strings`.
|
|
2174
|
+
*
|
|
2175
|
+
* @param {Rolldown.RolldownOutput['output']} chunks
|
|
2176
|
+
* @param {string} output_dir
|
|
2177
|
+
* @param {{
|
|
2178
|
+
* immutable?: Array<{ path: string }>;
|
|
2179
|
+
* assets?: Array<{ path: string }>;
|
|
2180
|
+
* prerendered?: Array<{ path: string }>;
|
|
2181
|
+
* routes?: Array<{ id: string }>;
|
|
2182
|
+
* }} values
|
|
2183
|
+
*/
|
|
2184
|
+
const replace_manifest_placeholder_variables = (chunks, output_dir, values) => {
|
|
2185
|
+
/** @type {Record<string, string>} */
|
|
2186
|
+
const replacements = {
|
|
2187
|
+
__SVELTEKIT_MANIFEST_IMMUTABLE__: JSON.stringify(
|
|
2188
|
+
values.immutable ?? '__sveltekit_manifest_build__'
|
|
2189
|
+
),
|
|
2190
|
+
__SVELTEKIT_MANIFEST_ASSETS__: JSON.stringify(values.assets ?? '__sveltekit_manifest_files__'),
|
|
2191
|
+
__SVELTEKIT_MANIFEST_PRERENDERED__: JSON.stringify(
|
|
2192
|
+
values.prerendered ?? '__sveltekit_manifest_prerendered__'
|
|
2193
|
+
),
|
|
2194
|
+
__SVELTEKIT_MANIFEST_ROUTES__: JSON.stringify(values.routes ?? '__sveltekit_manifest_routes__')
|
|
2195
|
+
};
|
|
2196
|
+
|
|
2197
|
+
for (const chunk of chunks) {
|
|
2198
|
+
if (chunk.type !== 'chunk') continue;
|
|
2199
|
+
if (!chunk.code.includes('__SVELTEKIT_MANIFEST_')) continue;
|
|
2200
|
+
|
|
2201
|
+
let code = chunk.code;
|
|
2202
|
+
|
|
2203
|
+
for (const [identifier, replacement] of Object.entries(replacements)) {
|
|
2204
|
+
code = code.replaceAll(identifier, replacement);
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
const file_path = `${output_dir}/${chunk.fileName}`;
|
|
2208
|
+
fs.writeFileSync(file_path, code);
|
|
2209
|
+
}
|
|
2210
|
+
};
|
|
2211
|
+
|
|
2212
|
+
/**
|
|
2213
|
+
* Replaces manifest sentinel strings in files on disk with real values.
|
|
2214
|
+
* This is used for values that weren't known when the first replacement
|
|
2215
|
+
* pass ran (e.g. `build` wasn't known until after the client build,
|
|
2216
|
+
* `prerendered` wasn't known until after prerendering).
|
|
2217
|
+
*
|
|
2218
|
+
* @param {string} dir Directory to scan for .js files
|
|
2219
|
+
* @param {{
|
|
2220
|
+
* immutable?: Array<{ path: string }>;
|
|
2221
|
+
* prerendered?: Array<{ path: string }>;
|
|
2222
|
+
* }} values
|
|
2223
|
+
*/
|
|
2224
|
+
const replace_manifest_placeholder_strings = (dir, values) => {
|
|
2225
|
+
/** @type {Record<string, string>} */
|
|
2226
|
+
const replacements = {};
|
|
2227
|
+
|
|
2228
|
+
if (values.immutable !== undefined) {
|
|
2229
|
+
replacements['__sveltekit_manifest_build__'] = JSON.stringify(values.immutable);
|
|
2230
|
+
}
|
|
2231
|
+
if (values.prerendered !== undefined) {
|
|
2232
|
+
replacements['__sveltekit_manifest_prerendered__'] = JSON.stringify(values.prerendered);
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
for (const file of fs.readdirSync(dir)) {
|
|
2236
|
+
const file_path = `${dir}/${file}`;
|
|
2237
|
+
const stat = fs.statSync(file_path);
|
|
2238
|
+
|
|
2239
|
+
if (stat.isDirectory()) {
|
|
2240
|
+
replace_manifest_placeholder_strings(file_path, values);
|
|
2241
|
+
continue;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
if (!file.endsWith('.js')) continue;
|
|
2245
|
+
|
|
2246
|
+
let code = read(file_path);
|
|
2247
|
+
let changed = false;
|
|
2248
|
+
|
|
2249
|
+
for (const [sentinel, replacement] of Object.entries(replacements)) {
|
|
2250
|
+
if (code.includes(sentinel)) {
|
|
2251
|
+
code = code.replaceAll(`"${sentinel}"`, replacement);
|
|
2252
|
+
changed = true;
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
if (changed) {
|
|
2257
|
+
fs.writeFileSync(file_path, code);
|
|
2258
|
+
}
|
|
2259
|
+
}
|
|
2260
|
+
};
|