@sveltejs/kit 2.38.1 → 2.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "2.38.1",
3
+ "version": "2.39.0",
4
4
  "description": "SvelteKit is the fastest way to build Svelte apps",
5
5
  "keywords": [
6
6
  "framework",
@@ -1,7 +1,7 @@
1
1
  /** @import { Builder } from '@sveltejs/kit' */
2
2
  /** @import { ResolvedConfig } from 'vite' */
3
3
  /** @import { RouteDefinition } from '@sveltejs/kit' */
4
- /** @import { RouteData, ValidatedConfig, BuildData, ServerMetadata, ServerMetadataRoute, Prerendered, PrerenderMap, Logger } from 'types' */
4
+ /** @import { RouteData, ValidatedConfig, BuildData, ServerMetadata, ServerMetadataRoute, Prerendered, PrerenderMap, Logger, RemoteChunk } from 'types' */
5
5
  import colors from 'kleur';
6
6
  import { createReadStream, createWriteStream, existsSync, statSync } from 'node:fs';
7
7
  import { extname, resolve, join, dirname, relative } from 'node:path';
@@ -32,6 +32,7 @@ const extensions = ['.html', '.js', '.mjs', '.json', '.css', '.svg', '.xml', '.w
32
32
  * prerender_map: PrerenderMap;
33
33
  * log: Logger;
34
34
  * vite_config: ResolvedConfig;
35
+ * remotes: RemoteChunk[]
35
36
  * }} opts
36
37
  * @returns {Builder}
37
38
  */
@@ -43,7 +44,8 @@ export function create_builder({
43
44
  prerendered,
44
45
  prerender_map,
45
46
  log,
46
- vite_config
47
+ vite_config,
48
+ remotes
47
49
  }) {
48
50
  /** @type {Map<RouteDefinition, RouteData>} */
49
51
  const lookup = new Map();
@@ -145,7 +147,8 @@ export function create_builder({
145
147
  build_data,
146
148
  prerendered: [],
147
149
  relative_path: relativePath,
148
- routes: Array.from(filtered)
150
+ routes: Array.from(filtered),
151
+ remotes
149
152
  })
150
153
  });
151
154
  }
@@ -195,7 +198,8 @@ export function create_builder({
195
198
  relative_path: relativePath,
196
199
  routes: subset
197
200
  ? subset.map((route) => /** @type {import('types').RouteData} */ (lookup.get(route)))
198
- : route_data.filter((route) => prerender_map.get(route.id) !== true)
201
+ : route_data.filter((route) => prerender_map.get(route.id) !== true),
202
+ remotes
199
203
  });
200
204
  },
201
205
 
@@ -8,6 +8,7 @@ import { create_builder } from './builder.js';
8
8
  * @param {import('types').Prerendered} prerendered
9
9
  * @param {import('types').PrerenderMap} prerender_map
10
10
  * @param {import('types').Logger} log
11
+ * @param {import('types').RemoteChunk[]} remotes
11
12
  * @param {import('vite').ResolvedConfig} vite_config
12
13
  */
13
14
  export async function adapt(
@@ -17,6 +18,7 @@ export async function adapt(
17
18
  prerendered,
18
19
  prerender_map,
19
20
  log,
21
+ remotes,
20
22
  vite_config
21
23
  ) {
22
24
  // This is only called when adapter is truthy, so the cast is safe
@@ -32,6 +34,7 @@ export async function adapt(
32
34
  prerendered,
33
35
  prerender_map,
34
36
  log,
37
+ remotes,
35
38
  vite_config
36
39
  });
37
40
 
@@ -1,3 +1,4 @@
1
+ /** @import { RemoteChunk } from 'types' */
1
2
  import fs from 'node:fs';
2
3
  import path from 'node:path';
3
4
  import * as mime from 'mrmime';
@@ -18,9 +19,10 @@ import { uneval } from 'devalue';
18
19
  * prerendered: string[];
19
20
  * relative_path: string;
20
21
  * routes: import('types').RouteData[];
22
+ * remotes: RemoteChunk[];
21
23
  * }} opts
22
24
  */
23
- export function generate_manifest({ build_data, prerendered, relative_path, routes }) {
25
+ export function generate_manifest({ build_data, prerendered, relative_path, routes, remotes }) {
24
26
  /**
25
27
  * @type {Map<any, number>} The new index of each node in the filtered nodes array
26
28
  */
@@ -101,7 +103,7 @@ export function generate_manifest({ build_data, prerendered, relative_path, rout
101
103
  ${(node_paths).map(loader).join(',\n')}
102
104
  ],
103
105
  remotes: {
104
- ${build_data.manifest_data.remotes.map((remote) => `'${remote.hash}': ${loader(join_relative(relative_path, resolve_symlinks(build_data.server_manifest, remote.file).chunk.file))}`).join(',\n')}
106
+ ${remotes.map((remote) => `'${remote.hash}': ${loader(join_relative(relative_path, `chunks/remote-${remote.hash}.js`))}`).join(',\n')}
105
107
  },
106
108
  routes: [
107
109
  ${routes.map(route => {
@@ -1,3 +1,4 @@
1
+ /** @import { RemoteChunk } from 'types' */
1
2
  import { join } from 'node:path';
2
3
  import { pathToFileURL } from 'node:url';
3
4
  import { validate_server_exports } from '../../utils/exports.js';
@@ -11,7 +12,6 @@ import { check_feature } from '../../utils/features.js';
11
12
  import { createReadableStream } from '@sveltejs/kit/node';
12
13
  import { PageNodes } from '../../utils/page_nodes.js';
13
14
  import { build_server_nodes } from '../../exports/vite/build/build_server.js';
14
- import { validate_remote_functions } from '@sveltejs/kit/internal';
15
15
 
16
16
  export default forked(import.meta.url, analyse);
17
17
 
@@ -25,6 +25,7 @@ export default forked(import.meta.url, analyse);
25
25
  * env: Record<string, string>;
26
26
  * out: string;
27
27
  * output_config: import('types').RecursiveRequired<import('types').ValidatedConfig['kit']['output']>;
28
+ * remotes: RemoteChunk[];
28
29
  * }} opts
29
30
  */
30
31
  async function analyse({
@@ -35,7 +36,8 @@ async function analyse({
35
36
  tracked_features,
36
37
  env,
37
38
  out,
38
- output_config
39
+ output_config,
40
+ remotes
39
41
  }) {
40
42
  /** @type {import('@sveltejs/kit').SSRManifest} */
41
43
  const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
@@ -166,16 +168,14 @@ async function analyse({
166
168
  }
167
169
 
168
170
  // analyse remotes
169
- for (const remote of manifest_data.remotes) {
171
+ for (const remote of remotes) {
170
172
  const loader = manifest._.remotes[remote.hash];
171
- const module = await loader();
172
-
173
- validate_remote_functions(module, remote.file);
173
+ const { default: functions } = await loader();
174
174
 
175
175
  const exports = new Map();
176
176
 
177
- for (const name in module) {
178
- const info = /** @type {import('types').RemoteInfo} */ (module[name].__);
177
+ for (const name in functions) {
178
+ const info = /** @type {import('types').RemoteInfo} */ (functions[name].__);
179
179
  const type = info.type;
180
180
 
181
181
  exports.set(name, {
@@ -495,7 +495,7 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env }) {
495
495
  for (const loader of Object.values(manifest._.remotes)) {
496
496
  const module = await loader();
497
497
 
498
- for (const fn of Object.values(module)) {
498
+ for (const fn of Object.values(module.default)) {
499
499
  if (fn?.__?.type === 'prerender') {
500
500
  prerender_functions.push(fn.__);
501
501
  should_prerender = true;
@@ -4,11 +4,10 @@ import process from 'node:process';
4
4
  import colors from 'kleur';
5
5
  import { lookup } from 'mrmime';
6
6
  import { list_files, runtime_directory } from '../../utils.js';
7
- import { posixify, resolve_entry, walk } from '../../../utils/filesystem.js';
7
+ import { posixify, resolve_entry } from '../../../utils/filesystem.js';
8
8
  import { parse_route_id } from '../../../utils/routing.js';
9
9
  import { sort_routes } from './sort.js';
10
10
  import { isSvelte5Plus } from '../utils.js';
11
- import { hash } from '../../../utils/hash.js';
12
11
 
13
12
  /**
14
13
  * Generates the manifest data used for the client-side manifest and types generation.
@@ -28,7 +27,6 @@ export default function create_manifest_data({
28
27
  const hooks = create_hooks(config, cwd);
29
28
  const matchers = create_matchers(config, cwd);
30
29
  const { nodes, routes } = create_routes_and_nodes(cwd, config, fallback);
31
- const remotes = create_remotes(config, cwd);
32
30
 
33
31
  for (const route of routes) {
34
32
  for (const param of route.params) {
@@ -43,7 +41,6 @@ export default function create_manifest_data({
43
41
  hooks,
44
42
  matchers,
45
43
  nodes,
46
- remotes,
47
44
  routes
48
45
  };
49
46
  }
@@ -468,33 +465,6 @@ function create_routes_and_nodes(cwd, config, fallback) {
468
465
  };
469
466
  }
470
467
 
471
- /**
472
- * @param {import('types').ValidatedConfig} config
473
- * @param {string} cwd
474
- */
475
- function create_remotes(config, cwd) {
476
- if (!config.kit.experimental.remoteFunctions) return [];
477
-
478
- const extensions = config.kit.moduleExtensions.map((ext) => `.remote${ext}`);
479
-
480
- /** @type {import('types').ManifestData['remotes']} */
481
- const remotes = [];
482
-
483
- // TODO could files live in other directories, including node_modules?
484
- for (const file of walk(config.kit.files.src)) {
485
- if (extensions.some((ext) => file.endsWith(ext))) {
486
- const posixified = posixify(path.relative(cwd, `${config.kit.files.src}/${file}`));
487
-
488
- remotes.push({
489
- hash: hash(posixified),
490
- file: posixified
491
- });
492
- }
493
- }
494
-
495
- return remotes;
496
- }
497
-
498
468
  /**
499
469
  * @param {string} project_relative
500
470
  * @param {string} file
@@ -62,4 +62,4 @@ export class ActionFailure {
62
62
  }
63
63
  }
64
64
 
65
- export { validate_remote_functions } from './remote-functions.js';
65
+ export { init_remote_functions } from './remote-functions.js';
@@ -1,27 +1,28 @@
1
+ /** @import { RemoteInfo } from 'types' */
2
+
3
+ /** @type {RemoteInfo['type'][]} */
4
+ const types = ['command', 'form', 'prerender', 'query', 'query_batch'];
5
+
1
6
  /**
2
7
  * @param {Record<string, any>} module
3
8
  * @param {string} file
9
+ * @param {string} hash
4
10
  */
5
- export function validate_remote_functions(module, file) {
11
+ export function init_remote_functions(module, file, hash) {
6
12
  if (module.default) {
7
13
  throw new Error(
8
14
  `Cannot export \`default\` from a remote module (${file}) — please use named exports instead`
9
15
  );
10
16
  }
11
17
 
12
- for (const name in module) {
13
- const type = /** @type {import('types').RemoteInfo['type']} */ (module[name]?.__?.type);
14
-
15
- if (
16
- type !== 'form' &&
17
- type !== 'command' &&
18
- type !== 'query' &&
19
- type !== 'query_batch' &&
20
- type !== 'prerender'
21
- ) {
18
+ for (const [name, fn] of Object.entries(module)) {
19
+ if (!types.includes(fn?.__?.type)) {
22
20
  throw new Error(
23
21
  `\`${name}\` exported from ${file} is invalid — all exports from this file must be remote functions`
24
22
  );
25
23
  }
24
+
25
+ fn.__.id = `${hash}/${name}`;
26
+ fn.__.name = name;
26
27
  }
27
28
  }
@@ -29,9 +29,10 @@ const vite_css_query_regex = /(?:\?|&)(?:raw|url|inline)(?:&|$)/;
29
29
  * @param {import('vite').ViteDevServer} vite
30
30
  * @param {import('vite').ResolvedConfig} vite_config
31
31
  * @param {import('types').ValidatedConfig} svelte_config
32
+ * @param {() => Array<{ hash: string, file: string }>} get_remotes
32
33
  * @return {Promise<Promise<() => void>>}
33
34
  */
34
- export async function dev(vite, vite_config, svelte_config) {
35
+ export async function dev(vite, vite_config, svelte_config, get_remotes) {
35
36
  installPolyfills();
36
37
 
37
38
  const async_local_storage = new AsyncLocalStorage();
@@ -266,12 +267,14 @@ export async function dev(vite, vite_config, svelte_config) {
266
267
  };
267
268
  }),
268
269
  prerendered_routes: new Set(),
269
- remotes: Object.fromEntries(
270
- manifest_data.remotes.map((remote) => [
271
- remote.hash,
272
- () => vite.ssrLoadModule(remote.file)
273
- ])
274
- ),
270
+ get remotes() {
271
+ return Object.fromEntries(
272
+ get_remotes().map((remote) => [
273
+ remote.hash,
274
+ () => vite.ssrLoadModule(remote.file).then((module) => ({ default: module }))
275
+ ])
276
+ );
277
+ },
275
278
  routes: compact(
276
279
  manifest_data.routes.map((route) => {
277
280
  if (!route.page && !route.endpoint) return null;
@@ -41,7 +41,6 @@ import {
41
41
  } from './module_ids.js';
42
42
  import { import_peer } from '../../utils/import.js';
43
43
  import { compact } from '../../utils/array.js';
44
- import { build_remotes, treeshake_prerendered_remotes } from './build/build_remote.js';
45
44
  import { should_ignore } from './static_analysis/utils.js';
46
45
 
47
46
  const cwd = process.cwd();
@@ -654,10 +653,66 @@ async function kit({ svelte_config }) {
654
653
  /** @type {import('vite').ViteDevServer} */
655
654
  let dev_server;
656
655
 
656
+ /** @type {Array<{ hash: string, file: string }>} */
657
+ const remotes = [];
658
+
657
659
  /** @type {import('vite').Plugin} */
658
660
  const plugin_remote = {
659
661
  name: 'vite-plugin-sveltekit-remote',
660
662
 
663
+ config(config) {
664
+ if (!config.build?.ssr) {
665
+ // only set manualChunks for the SSR build
666
+ return;
667
+ }
668
+
669
+ // Ensure build.rollupOptions.output exists
670
+ config.build ??= {};
671
+ config.build.rollupOptions ??= {};
672
+ config.build.rollupOptions.output ??= {};
673
+
674
+ if (Array.isArray(config.build.rollupOptions.output)) {
675
+ // TODO I have no idea how this could occur
676
+ throw new Error('rollupOptions.output cannot be an array');
677
+ }
678
+
679
+ // Set up manualChunks to isolate *.remote.ts files
680
+ const { manualChunks } = config.build.rollupOptions.output;
681
+
682
+ config.build.rollupOptions.output = {
683
+ ...config.build.rollupOptions.output,
684
+ manualChunks(id, meta) {
685
+ if (id === `${runtime_directory}/app/server/index.js`) {
686
+ return 'app-server';
687
+ }
688
+
689
+ // Check if this is a *.remote.ts file
690
+ if (svelte_config.kit.moduleExtensions.some((ext) => id.endsWith(`.remote${ext}`))) {
691
+ const relative = posixify(path.relative(cwd, id));
692
+
693
+ return `remote-${hash(relative)}`;
694
+ }
695
+
696
+ // If there was an existing manualChunks function, call it
697
+ if (typeof manualChunks === 'function') {
698
+ return manualChunks(id, meta);
699
+ }
700
+
701
+ // If manualChunks is an object, check if this module matches any patterns
702
+ if (manualChunks) {
703
+ for (const name in manualChunks) {
704
+ const patterns = manualChunks[name];
705
+
706
+ // TODO is `id.includes(pattern)` correct?
707
+ if (patterns.some((pattern) => id.includes(pattern))) {
708
+ return name;
709
+ }
710
+ }
711
+ }
712
+ }
713
+ };
714
+ },
715
+
661
716
  configureServer(_dev_server) {
662
717
  dev_server = _dev_server;
663
718
  },
@@ -668,36 +723,40 @@ async function kit({ svelte_config }) {
668
723
  }
669
724
 
670
725
  const file = posixify(path.relative(cwd, id));
671
- const hashed = hash(file);
726
+
727
+ const remote = {
728
+ hash: hash(file),
729
+ file
730
+ };
731
+
732
+ remotes.push(remote);
672
733
 
673
734
  if (opts?.ssr) {
674
- // in dev, add metadata to remote functions by self-importing
675
- if (dev_server) {
676
- return (
677
- code +
678
- dedent`
679
- import * as $$_self_$$ from './${path.basename(id)}';
680
- import { validate_remote_functions as $$_validate_$$ } from '@sveltejs/kit/internal';
681
-
682
- $$_validate_$$($$_self_$$, ${s(file)});
683
-
684
- for (const [name, fn] of Object.entries($$_self_$$)) {
685
- fn.__.id = ${s(hashed)} + '/' + name;
686
- fn.__.name = name;
687
- }
688
- `
689
- );
735
+ code += dedent`
736
+ import * as $$_self_$$ from './${path.basename(id)}';
737
+ import { init_remote_functions as $$_init_$$ } from '@sveltejs/kit/internal';
738
+
739
+ $$_init_$$($$_self_$$, ${s(file)}, ${s(remote.hash)});
740
+
741
+ for (const [name, fn] of Object.entries($$_self_$$)) {
742
+ fn.__.id = ${s(remote.hash)} + '/' + name;
743
+ fn.__.name = name;
744
+ }
745
+ `;
746
+
747
+ if (!dev_server) {
748
+ // in prod, prevent the functions from being treeshaken. This will
749
+ // be replaced with an `export default` in the `writeBundle` hook
750
+ code += `$$_export_$$($$_self_$$);`;
690
751
  }
691
752
 
692
- // in prod, return as-is, and augment the build result instead.
693
- // this allows us to treeshake non-dynamic `prerender` functions
694
- return;
753
+ return code;
695
754
  }
696
755
 
697
756
  // For the client, read the exports and create a new module that only contains fetch functions with the correct metadata
698
757
 
699
758
  /** @type {Map<string, import('types').RemoteInfo['type']>} */
700
- const remotes = new Map();
759
+ const map = new Map();
701
760
 
702
761
  // in dev, load the server module here (which will result in this hook
703
762
  // being called again with `opts.ssr === true` if the module isn't
@@ -708,7 +767,7 @@ async function kit({ svelte_config }) {
708
767
  for (const [name, value] of Object.entries(module)) {
709
768
  const type = value?.__?.type;
710
769
  if (type) {
711
- remotes.set(name, type);
770
+ map.set(name, type);
712
771
  }
713
772
  }
714
773
  }
@@ -716,25 +775,37 @@ async function kit({ svelte_config }) {
716
775
  // in prod, we already built and analysed the server code before
717
776
  // building the client code, so `remote_exports` is populated
718
777
  else if (remote_exports) {
719
- const exports = remote_exports.get(hashed);
778
+ const exports = remote_exports.get(remote.hash);
720
779
  if (!exports) throw new Error('Expected to find metadata for remote file ' + id);
721
780
 
722
781
  for (const [name, value] of exports) {
723
- remotes.set(name, value.type);
782
+ map.set(name, value.type);
724
783
  }
725
784
  }
726
785
 
727
786
  let namespace = '__remote';
728
787
  let uid = 1;
729
- while (remotes.has(namespace)) namespace = `__remote${uid++}`;
788
+ while (map.has(namespace)) namespace = `__remote${uid++}`;
730
789
 
731
- const exports = Array.from(remotes).map(([name, type]) => {
732
- return `export const ${name} = ${namespace}.${type}('${hashed}/${name}');`;
790
+ const exports = Array.from(map).map(([name, type]) => {
791
+ return `export const ${name} = ${namespace}.${type}('${remote.hash}/${name}');`;
733
792
  });
734
793
 
735
794
  return {
736
795
  code: `import * as ${namespace} from '__sveltekit/remote';\n\n${exports.join('\n')}\n`
737
796
  };
797
+ },
798
+
799
+ writeBundle() {
800
+ for (const remote of remotes) {
801
+ const file = `${out}/server/chunks/remote-${remote.hash}.js`;
802
+ const code = fs.readFileSync(file, 'utf-8');
803
+
804
+ fs.writeFileSync(
805
+ file,
806
+ code.replace('$$_export_$$($$_self_$$)', () => `export default $$_self_$$;`)
807
+ );
808
+ }
738
809
  }
739
810
  };
740
811
 
@@ -811,11 +882,6 @@ async function kit({ svelte_config }) {
811
882
  }
812
883
  input['instrumentation.server'] = server_instrumentation;
813
884
  }
814
-
815
- // ...and every .remote file
816
- for (const remote of manifest_data.remotes) {
817
- input[`remote/${remote.hash}`] = path.resolve(remote.file);
818
- }
819
885
  } else if (svelte_config.kit.output.bundleStrategy !== 'split') {
820
886
  input['bundle'] = `${runtime_directory}/client/bundle.js`;
821
887
  } else {
@@ -917,7 +983,7 @@ async function kit({ svelte_config }) {
917
983
  * @see https://vitejs.dev/guide/api-plugin.html#configureserver
918
984
  */
919
985
  async configureServer(vite) {
920
- return await dev(vite, vite_config, svelte_config);
986
+ return await dev(vite, vite_config, svelte_config, () => remotes);
921
987
  },
922
988
 
923
989
  /**
@@ -1000,7 +1066,8 @@ async function kit({ svelte_config }) {
1000
1066
  build_data,
1001
1067
  prerendered: [],
1002
1068
  relative_path: '.',
1003
- routes: manifest_data.routes
1069
+ routes: manifest_data.routes,
1070
+ remotes
1004
1071
  })};\n`
1005
1072
  );
1006
1073
 
@@ -1014,7 +1081,8 @@ async function kit({ svelte_config }) {
1014
1081
  tracked_features,
1015
1082
  env: { ...env.private, ...env.public },
1016
1083
  out,
1017
- output_config: svelte_config.output
1084
+ output_config: svelte_config.output,
1085
+ remotes
1018
1086
  });
1019
1087
 
1020
1088
  remote_exports = metadata.remotes;
@@ -1199,7 +1267,8 @@ async function kit({ svelte_config }) {
1199
1267
  build_data,
1200
1268
  prerendered: [],
1201
1269
  relative_path: '.',
1202
- routes: manifest_data.routes
1270
+ routes: manifest_data.routes,
1271
+ remotes
1203
1272
  })};\n`
1204
1273
  );
1205
1274
 
@@ -1216,9 +1285,6 @@ async function kit({ svelte_config }) {
1216
1285
  static_exports
1217
1286
  );
1218
1287
 
1219
- // ...make sure remote exports have their IDs assigned...
1220
- build_remotes(out, manifest_data);
1221
-
1222
1288
  // ...and prerender
1223
1289
  const { prerendered, prerender_map } = await prerender({
1224
1290
  hash: kit.router.type === 'hash',
@@ -1236,13 +1302,11 @@ async function kit({ svelte_config }) {
1236
1302
  build_data,
1237
1303
  prerendered: prerendered.paths,
1238
1304
  relative_path: '.',
1239
- routes: manifest_data.routes.filter((route) => prerender_map.get(route.id) !== true)
1305
+ routes: manifest_data.routes.filter((route) => prerender_map.get(route.id) !== true),
1306
+ remotes
1240
1307
  })};\n`
1241
1308
  );
1242
1309
 
1243
- // remove prerendered remote functions
1244
- await treeshake_prerendered_remotes(out, manifest_data, metadata);
1245
-
1246
1310
  if (service_worker_entry_file) {
1247
1311
  if (kit.paths.assets) {
1248
1312
  throw new Error('Cannot use service worker alongside config.kit.paths.assets');
@@ -1285,6 +1349,7 @@ async function kit({ svelte_config }) {
1285
1349
  prerendered,
1286
1350
  prerender_map,
1287
1351
  log,
1352
+ remotes,
1288
1353
  vite_config
1289
1354
  );
1290
1355
  } else {
@@ -18,61 +18,72 @@ import {
18
18
  */
19
19
  export function server_data_serializer(event, event_state, options) {
20
20
  let promise_id = 1;
21
+ let max_nodes = -1;
21
22
 
22
23
  const iterator = create_async_iterator();
23
24
  const global = get_global_name(options);
24
25
 
25
- /** @param {any} thing */
26
- function replacer(thing) {
27
- if (typeof thing?.then === 'function') {
28
- const id = promise_id++;
29
-
30
- const promise = thing
31
- .then(/** @param {any} data */ (data) => ({ data }))
32
- .catch(
33
- /** @param {any} error */ async (error) => ({
34
- error: await handle_error_and_jsonify(event, event_state, options, error)
35
- })
36
- )
37
- .then(
38
- /**
39
- * @param {{data: any; error: any}} result
40
- */
41
- async ({ data, error }) => {
42
- let str;
43
- try {
44
- str = devalue.uneval(error ? [, error] : [data], replacer);
45
- } catch {
46
- error = await handle_error_and_jsonify(
47
- event,
48
- event_state,
49
- options,
50
- new Error(`Failed to serialize promise while rendering ${event.route.id}`)
51
- );
52
- data = undefined;
53
- str = devalue.uneval([, error], replacer);
26
+ /** @param {number} index */
27
+ function get_replacer(index) {
28
+ /** @param {any} thing */
29
+ return function replacer(thing) {
30
+ if (typeof thing?.then === 'function') {
31
+ const id = promise_id++;
32
+
33
+ const promise = thing
34
+ .then(/** @param {any} data */ (data) => ({ data }))
35
+ .catch(
36
+ /** @param {any} error */ async (error) => ({
37
+ error: await handle_error_and_jsonify(event, event_state, options, error)
38
+ })
39
+ )
40
+ .then(
41
+ /**
42
+ * @param {{data: any; error: any}} result
43
+ */
44
+ async ({ data, error }) => {
45
+ let str;
46
+ try {
47
+ str = devalue.uneval(error ? [, error] : [data], replacer);
48
+ } catch {
49
+ error = await handle_error_and_jsonify(
50
+ event,
51
+ event_state,
52
+ options,
53
+ new Error(`Failed to serialize promise while rendering ${event.route.id}`)
54
+ );
55
+ data = undefined;
56
+ str = devalue.uneval([, error], replacer);
57
+ }
58
+
59
+ return {
60
+ index,
61
+ str: `${global}.resolve(${id}, ${str.includes('app.decode') ? `(app) => ${str}` : `() => ${str}`})`
62
+ };
54
63
  }
64
+ );
55
65
 
56
- return `${global}.resolve(${id}, ${str.includes('app.decode') ? `(app) => ${str}` : `() => ${str}`})`;
57
- }
58
- );
66
+ iterator.add(promise);
59
67
 
60
- iterator.add(promise);
61
-
62
- return `${global}.defer(${id})`;
63
- } else {
64
- for (const key in options.hooks.transport) {
65
- const encoded = options.hooks.transport[key].encode(thing);
66
- if (encoded) {
67
- return `app.decode('${key}', ${devalue.uneval(encoded, replacer)})`;
68
+ return `${global}.defer(${id})`;
69
+ } else {
70
+ for (const key in options.hooks.transport) {
71
+ const encoded = options.hooks.transport[key].encode(thing);
72
+ if (encoded) {
73
+ return `app.decode('${key}', ${devalue.uneval(encoded, replacer)})`;
74
+ }
68
75
  }
69
76
  }
70
- }
77
+ };
71
78
  }
72
79
 
73
80
  const strings = /** @type {string[]} */ ([]);
74
81
 
75
82
  return {
83
+ set_max_nodes(i) {
84
+ max_nodes = i;
85
+ },
86
+
76
87
  add_node(i, node) {
77
88
  try {
78
89
  if (!node) {
@@ -84,7 +95,7 @@ export function server_data_serializer(event, event_state, options) {
84
95
  const payload = { type: 'data', data: node.data, uses: serialize_uses(node) };
85
96
  if (node.slash) payload.slash = node.slash;
86
97
 
87
- strings[i] = devalue.uneval(payload, replacer);
98
+ strings[i] = devalue.uneval(payload, get_replacer(i));
88
99
  } catch (e) {
89
100
  // @ts-expect-error
90
101
  e.path = e.path.slice(1);
@@ -97,8 +108,17 @@ export function server_data_serializer(event, event_state, options) {
97
108
  const close = `</script>\n`;
98
109
 
99
110
  return {
100
- data: `[${compact(strings).join(',')}]`,
101
- chunks: promise_id > 1 ? iterator.iterate((str) => open + str + close) : null
111
+ data: `[${compact(max_nodes > -1 ? strings.slice(0, max_nodes) : strings).join(',')}]`,
112
+ chunks:
113
+ promise_id > 1
114
+ ? iterator.iterate(({ index, str }) => {
115
+ if (max_nodes > -1 && index >= max_nodes) {
116
+ return '';
117
+ }
118
+
119
+ return open + str + close;
120
+ })
121
+ : null
102
122
  };
103
123
  }
104
124
  };
@@ -281,6 +281,8 @@ export async function render_page(
281
281
  let j = i;
282
282
  while (!branch[j]) j -= 1;
283
283
 
284
+ data_serializer.set_max_nodes(j + 1);
285
+
284
286
  const layouts = compact(branch.slice(0, j + 1));
285
287
  const nodes = new PageNodes(layouts.map((layout) => layout.node));
286
288
 
@@ -303,7 +305,7 @@ export async function render_page(
303
305
  server_data: null
304
306
  }),
305
307
  fetched,
306
- data_serializer: server_data_serializer(event, event_state, options)
308
+ data_serializer
307
309
  });
308
310
  }
309
311
  }
@@ -45,6 +45,7 @@ export interface Cookie {
45
45
  export type ServerDataSerializer = {
46
46
  add_node(i: number, node: ServerDataNode | null): void;
47
47
  get_data(csp: Csp): { data: string; chunks: AsyncIterable<string> | null };
48
+ set_max_nodes(i: number): void;
48
49
  };
49
50
 
50
51
  export type ServerDataSerializerJson = {
@@ -43,7 +43,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
43
43
  if (!remotes[hash]) error(404);
44
44
 
45
45
  const module = await remotes[hash]();
46
- const fn = module[name];
46
+ const fn = module.default[name];
47
47
 
48
48
  if (!fn) error(404);
49
49
 
@@ -169,20 +169,28 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
169
169
  );
170
170
  } catch (error) {
171
171
  if (error instanceof Redirect) {
172
- return json({
173
- type: 'redirect',
174
- location: error.location,
175
- refreshes: await serialize_refreshes(form_client_refreshes ?? [])
176
- });
172
+ return json(
173
+ /** @type {RemoteFunctionResponse} */ ({
174
+ type: 'redirect',
175
+ location: error.location,
176
+ refreshes: await serialize_refreshes(form_client_refreshes ?? [])
177
+ })
178
+ );
177
179
  }
178
180
 
181
+ const status =
182
+ error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500;
183
+
179
184
  return json(
180
185
  /** @type {RemoteFunctionResponse} */ ({
181
186
  type: 'error',
182
187
  error: await handle_error_and_jsonify(event, state, options, error),
183
- status: error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500
188
+ status
184
189
  }),
185
190
  {
191
+ // By setting a non-200 during prerendering we fail the prerender process (unless handleHttpError handles it).
192
+ // Errors at runtime will be passed to the client and are handled there
193
+ status: state.prerendering ? status : undefined,
186
194
  headers: {
187
195
  'cache-control': 'private, no-store'
188
196
  }
@@ -202,7 +210,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id)
202
210
  const [hash, name, payload] = key.split('/');
203
211
 
204
212
  const loader = manifest._.remotes[hash];
205
- const fn = (await loader?.())?.[name];
213
+ const fn = (await loader?.())?.default?.[name];
206
214
 
207
215
  if (!fn) error(400, 'Bad Request');
208
216
 
@@ -254,7 +262,7 @@ async function handle_remote_form_post_internal(event, state, manifest, id) {
254
262
  const remotes = manifest._.remotes;
255
263
  const module = await remotes[hash]?.();
256
264
 
257
- let form = /** @type {RemoteForm<any>} */ (module?.[name]);
265
+ let form = /** @type {RemoteForm<any>} */ (module?.default[name]);
258
266
 
259
267
  if (!form) {
260
268
  event.setHeaders({
@@ -505,11 +505,12 @@ export async function internal_respond(request, options, manifest, state) {
505
505
  return response;
506
506
  } catch (e) {
507
507
  if (e instanceof Redirect) {
508
- const response = is_data_request
509
- ? redirect_json_response(e)
510
- : route?.page && is_action_json_request(event)
511
- ? action_json_redirect(e)
512
- : redirect_response(e.status, e.location);
508
+ const response =
509
+ is_data_request || remote_id
510
+ ? redirect_json_response(e)
511
+ : route?.page && is_action_json_request(event)
512
+ ? action_json_redirect(e)
513
+ : redirect_response(e.status, e.location);
513
514
  add_cookies_to_headers(response.headers, new_cookies.values());
514
515
  return response;
515
516
  }
@@ -192,14 +192,15 @@ export interface ManifestData {
192
192
  universal: string | null;
193
193
  };
194
194
  nodes: PageNode[];
195
- remotes: Array<{
196
- file: string;
197
- hash: string;
198
- }>;
199
195
  routes: RouteData[];
200
196
  matchers: Record<string, string>;
201
197
  }
202
198
 
199
+ export interface RemoteChunk {
200
+ hash: string;
201
+ file: string;
202
+ }
203
+
203
204
  export interface PageNode {
204
205
  depth: number;
205
206
  /** The `+page/layout.svelte`. */
package/src/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  // generated during release, do not modify
2
2
 
3
3
  /** @type {string} */
4
- export const VERSION = '2.38.1';
4
+ export const VERSION = '2.39.0';
package/types/index.d.ts CHANGED
@@ -2123,10 +2123,6 @@ declare module '@sveltejs/kit' {
2123
2123
  universal: string | null;
2124
2124
  };
2125
2125
  nodes: PageNode[];
2126
- remotes: Array<{
2127
- file: string;
2128
- hash: string;
2129
- }>;
2130
2126
  routes: RouteData[];
2131
2127
  matchers: Record<string, string>;
2132
2128
  }
@@ -187,6 +187,6 @@
187
187
  null,
188
188
  null
189
189
  ],
190
- "mappings": ";;;;;;;;;;;kBAkCiBA,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAiCZC,cAAcA;;;;;;aAMdC,cAAcA;;;;;;;;MAQrBC,aAAaA;;;;;OAKJC,YAAYA;;kBAETC,aAAaA;;;;;;MAMzBC,qBAAqBA;;;;;;;;;;;kBAWTC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA8IPC,MAAMA;;;;;;;;;;;kBAWNC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4DPC,QAAQA;;;;;;;;kBAQRC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAqkBdC,MAAMA;;;;;;;;;;;aAWNC,iBAAiBA;;;;;;;;;;;;aAYjBC,qBAAqBA;;;;;;;;;aASrBC,iBAAiBA;;;;;;;;;;aAUjBC,WAAWA;;;;;;;;;;aAUXC,UAAUA;;;;;;aAMVC,UAAUA;;;;;;aAMVC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;aA0BPC,SAASA;;;;;kBAKJC,WAAWA;;;;;;;;;;;;aAYhBC,IAAIA;;;;;;;;;;;;kBAYCC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAyHTC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0BfC,gBAAgBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAgCrBC,cAAcA;;kBAETC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAoCVC,cAAcA;;;;;;;;;;kBAUdC,UAAUA;;;;;;;;;;;;;;;;;;kBAkBVC,aAAaA;;;;;;;;;;;;;;;;;;;kBAmBbC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA8CTC,YAAYA;;kBAEPC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA+GjBC,cAAcA;;;;;kBAKTC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;kBAuBdC,eAAeA;;;;;;;;;;;;;;;cAenBC,MAAMA;;;;;;kBAMFC,iBAAiBA;;;;;;;kBAOjBC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;aAyBhBC,UAAUA;;;;;;;kBAOLC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAkFpBC,MAAMA;;;;;;;;;;aAUNC,OAAOA;;;;;;;;;;;;;;;;aAgBPC,YAAYA;;;;;;;;;;;;kBC7mDXC,SAASA;;;;;;;;;;kBAqBTC,QAAQA;;;;;;;aDqnDTC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6BTC,QAAQA;;;;;;;;aAQbC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAoEVC,aAAaA;;;;;;;;aAQbC,cAAcA;;;;;;;;;;;;;;;;;;aAkBdC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAqCNC,mBAAmBA;;;;;;;;aAQxBC,uBAAuBA;;;;;aAKvBC,mBAAmBA;WEzzDdC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAkDZC,GAAGA;;;;;;;;;;;;;;;;;;;;;WAqBHC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAmElBC,UAAUA;;WAELC,MAAMA;;;;;;;;;MASXC,YAAYA;;WAEPC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmCXC,yBAAyBA;;;;;;;;;;WAUzBC,yBAAyBA;;;;WAIzBC,sCAAsCA;;;;WAItCC,4BAA4BA;;;;MAIjCC,8BAA8BA;MAC9BC,8BAA8BA;MAC9BC,iCAAiCA;;;;;MAKjCC,2CAA2CA;;;;;;aAM3CC,eAAeA;;WAIVC,cAAcA;;;;;WAKdC,YAAYA;;;;;;MAMjBC,aAAaA;WC/LRC,KAAKA;;;;;;WAeLC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAuHTC,YAAYA;;;;;;;;;;;;;;;;;WAiBZC,QAAQA;;;;;;;;;;;;;;MAgCbC,iBAAiBA;;;;;;;;;WAWZC,UAAUA;;;;;;;;;;;;;WAaVC,SAASA;;;;;;;;;;;;;;;;;;;;;;;WAsHTC,YAAYA;;;;;;;;;;;;;;;;MAgBjBC,kBAAkBA;;WAEbC,aAAaA;;;;;;;;;;WAUbC,UAAUA;;;;;;;;;;;WAWVC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;MAuBZC,aAAaA;;WA6BRC,eAAeA;;;;;;MAMpBC,uBAAuBA;;MAGvBC,WAAWA;;;;;;;;WAQNC,QAAQA;;;;;;;;;WASRC,cAAcA;;;;;;;;;MA+CnBC,eAAeA;;;;;MAKfC,kBAAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC1cdC,WAAWA;;;;;;;;;;;;;;;;;;;iBAsBXC,QAAQA;;;;;iBAiBRC,UAAUA;;;;;;iBASVC,IAAIA;;;;;;iBA4BJC,IAAIA;;;;;;;;;;;;;;;;iBAkDJC,eAAeA;;;;;;;;;;;;;;iBAmBfC,YAAYA;;;;;;;cCrOfC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBC4EJC,QAAQA;;;;;;iBC4BFC,UAAUA;;;;;;iBAkCVC,WAAWA;;;;;iBAgFjBC,oBAAoBA;;;;;;;;;;;iBC3MpBC,gBAAgBA;;;;;;;;;iBCuHVC,SAASA;;;;;;;;;cCtIlBC,OAAOA;;;;;cAKPC,GAAGA;;;;;cAKHC,QAAQA;;;;;cAKRC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;iBCYJC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;iBAgDXC,OAAOA;;;;;;;iBCsmEDC,WAAWA;;;;;;;;;;;iBA9UjBC,aAAaA;;;;;;;;;;;;iBAiBbC,cAAcA;;;;;;;;;;iBAedC,UAAUA;;;;;iBASVC,qBAAqBA;;;;;;;;;;iBA8BrBC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;iBAsCJC,UAAUA;;;;iBA0BVC,aAAaA;;;;;iBAebC,UAAUA;;;;;;;;;;;;;;iBAqBJC,WAAWA;;;;;;;;;;;;;;;;;;iBAoCXC,WAAWA;;;;;iBAsCjBC,SAASA;;;;;iBA+CTC,YAAYA;MV/+DhBlE,YAAYA;;;;;;;;;;;;;;YWlJbmE,IAAIA;;;;;;;;;YASJC,MAAMA;;MAEZC,WAAWA;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBAC,OAAOA;;;;;;;;;;;;;;;;;iBAiBPC,KAAKA;;;;;iBAKLC,YAAYA;;;;;;;;;;;;;;;;;;;;;;iBChDZC,IAAIA;;;;;;;;iBCOJC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCTfC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MbycRC,8BAA8BA;MD/T9B5E,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ce1GX6E,IAAIA;;;;;cAQJC,UAAUA;;;;;;;;;;;cAMVC,OAAOA;;;;;;;;;iBCrDPC,SAASA;;;;;;;;;;;;;;;cAyBTH,IAAIA;;;;;;;;;;cAiBJC,UAAUA;;;;;;;;cAeVC,OAAOA",
190
+ "mappings": "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",
191
191
  "ignoreList": []
192
192
  }
@@ -1,129 +0,0 @@
1
- /** @import { ManifestData, ServerMetadata } from 'types' */
2
- import fs from 'node:fs';
3
- import path from 'node:path';
4
- import { posixify } from '../../../utils/filesystem.js';
5
- import { dedent } from '../../../core/sync/utils.js';
6
- import { import_peer } from '../../../utils/import.js';
7
-
8
- /**
9
- * Moves the remote files to a sibling file and rewrites the original remote file to import from that sibling file,
10
- * enhancing the remote functions with their hashed ID.
11
- * This is not done through a self-import like during DEV because we want to treeshake prerendered remote functions
12
- * later, which wouldn't work if we do a self-import and iterate over all exports (since we're reading them then).
13
- * @param {string} out
14
- * @param {ManifestData} manifest_data
15
- */
16
- export function build_remotes(out, manifest_data) {
17
- const dir = `${out}/server/remote`;
18
-
19
- for (const remote of manifest_data.remotes) {
20
- const entry = `${dir}/${remote.hash}.js`;
21
- const tmp = `${remote.hash}.tmp.js`;
22
-
23
- fs.renameSync(entry, `${dir}/${tmp}`);
24
- fs.writeFileSync(
25
- entry,
26
- dedent`
27
- import * as $$_self_$$ from './${tmp}';
28
-
29
- for (const [name, fn] of Object.entries($$_self_$$)) {
30
- fn.__.id = '${remote.hash}/' + name;
31
- fn.__.name = name;
32
- }
33
-
34
- export * from './${tmp}';
35
- `
36
- );
37
- }
38
- }
39
-
40
-
41
- /**
42
- * For each remote module, checks if there are treeshakeable prerendered remote functions,
43
- * then accomplishes the treeshaking by rewriting the remote files to only include the non-prerendered imports,
44
- * replacing the prerendered remote functions with a dummy function that should never be called,
45
- * and doing a Vite build. This will not treeshake perfectly yet as everything except the remote files are treated as external,
46
- * so it will not go into those files to check what can be treeshaken inside them.
47
- * @param {string} out
48
- * @param {ManifestData} manifest_data
49
- * @param {ServerMetadata} metadata
50
- */
51
- export async function treeshake_prerendered_remotes(out, manifest_data, metadata) {
52
- if (manifest_data.remotes.length === 0) {
53
- return;
54
- }
55
-
56
- const dir = posixify(`${out}/server/remote`);
57
-
58
- const vite = /** @type {typeof import('vite')} */ (await import_peer('vite'));
59
- const remote_entry = posixify(`${out}/server/remote-entry.js`);
60
-
61
- const prefix = 'optimized/';
62
-
63
- const input = {
64
- // include this file in the bundle, so that Rollup understands
65
- // that functions like `prerender` are side-effect free
66
- [path.basename(remote_entry.slice(0, -3))]: remote_entry
67
- };
68
-
69
- for (const remote of manifest_data.remotes) {
70
- const exports = metadata.remotes.get(remote.hash);
71
- if (!exports) throw new Error('An impossible situation occurred');
72
-
73
- /** @type {string[]} */
74
- const dynamic = [];
75
-
76
- /** @type {string[]} */
77
- const prerendered = [];
78
-
79
- for (const [name, value] of exports) {
80
- (value.dynamic ? dynamic : prerendered).push(name);
81
- }
82
-
83
- const remote_file = posixify(`${dir}/${remote.hash}.js`);
84
-
85
- fs.writeFileSync(
86
- remote_file,
87
- dedent`
88
- import { ${dynamic.join(', ')} } from './${remote.hash}.tmp.js';
89
- import { prerender } from '../${path.basename(remote_entry)}';
90
-
91
- ${prerendered.map((name) => `export const ${name} = prerender('unchecked', () => { throw new Error('Unexpectedly called prerender function. Did you forget to set { dynamic: true } ?') });`).join('\n')}
92
-
93
- for (const [name, fn] of Object.entries({ ${Array.from(exports.keys()).join(', ')} })) {
94
- fn.__.id = '${remote.hash}/' + name;
95
- fn.__.name = name;
96
- }
97
-
98
- export { ${dynamic.join(', ')} };
99
- `
100
- );
101
-
102
- input[prefix + remote.hash] = remote_file;
103
- }
104
-
105
- const bundle = /** @type {import('vite').Rollup.RollupOutput} */ (await vite.build({
106
- configFile: false,
107
- build: {
108
- write: false,
109
- ssr: true,
110
- rollupOptions: {
111
- external: (id) => {
112
- if (id[0] === '.') return;
113
- return !id.startsWith(dir);
114
- },
115
- input
116
- }
117
- }
118
- }));
119
-
120
- for (const chunk of bundle.output) {
121
- if (chunk.type === 'chunk' && chunk.name.startsWith(prefix)) {
122
- fs.writeFileSync(`${dir}/${chunk.fileName.slice(prefix.length)}`, chunk.code);
123
- }
124
- }
125
-
126
- for (const remote of manifest_data.remotes) {
127
- fs.unlinkSync(`${dir}/${remote.hash}.tmp.js`);
128
- }
129
- }