@sveltejs/kit 3.0.0-next.1 → 3.0.0-next.3

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.
Files changed (45) hide show
  1. package/package.json +2 -2
  2. package/src/core/postbuild/analyse.js +0 -8
  3. package/src/core/postbuild/prerender.js +2 -0
  4. package/src/core/sync/create_manifest_data/index.js +24 -1
  5. package/src/core/sync/write_env.js +2 -1
  6. package/src/exports/internal/env.js +1 -1
  7. package/src/exports/public.d.ts +1 -1
  8. package/src/exports/vite/build/build_server.js +47 -58
  9. package/src/exports/vite/build/remote.js +18 -11
  10. package/src/exports/vite/build/utils.js +0 -8
  11. package/src/exports/vite/index.js +221 -217
  12. package/src/exports/vite/static_analysis/index.js +2 -4
  13. package/src/exports/vite/static_analysis/types.d.ts +14 -0
  14. package/src/exports/vite/utils.js +1 -12
  15. package/src/runtime/app/server/remote/command.js +0 -3
  16. package/src/runtime/app/server/remote/form.js +18 -13
  17. package/src/runtime/app/server/remote/prerender.js +28 -34
  18. package/src/runtime/app/server/remote/query.js +105 -94
  19. package/src/runtime/app/server/remote/requested.js +14 -10
  20. package/src/runtime/app/server/remote/shared.js +25 -19
  21. package/src/runtime/client/client.js +19 -13
  22. package/src/runtime/client/ndjson.js +6 -33
  23. package/src/runtime/client/remote-functions/command.svelte.js +7 -32
  24. package/src/runtime/client/remote-functions/form.svelte.js +62 -82
  25. package/src/runtime/client/remote-functions/prerender.svelte.js +14 -6
  26. package/src/runtime/client/remote-functions/query/index.js +6 -14
  27. package/src/runtime/client/remote-functions/query/instance.svelte.js +20 -0
  28. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  29. package/src/runtime/client/remote-functions/query-batch.svelte.js +59 -68
  30. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +21 -6
  31. package/src/runtime/client/remote-functions/query-live/iterator.js +36 -55
  32. package/src/runtime/client/remote-functions/shared.svelte.js +76 -59
  33. package/src/runtime/client/sse.js +32 -0
  34. package/src/runtime/client/stream.js +38 -0
  35. package/src/runtime/server/page/render.js +23 -80
  36. package/src/runtime/server/page/server_routing.js +20 -15
  37. package/src/runtime/server/remote.js +296 -204
  38. package/src/runtime/server/respond.js +4 -2
  39. package/src/runtime/shared.js +83 -13
  40. package/src/types/global-private.d.ts +3 -3
  41. package/src/types/internal.d.ts +54 -35
  42. package/src/utils/error.js +12 -0
  43. package/src/version.js +1 -1
  44. package/types/index.d.ts +17 -7
  45. package/types/index.d.ts.map +5 -3
@@ -1,7 +1,7 @@
1
- /** @import { EnvVarConfig } from '@sveltejs/kit' */
1
+ /** @import { Adapter, EnvVarConfig, KitConfig } from '@sveltejs/kit' */
2
2
  /** @import { Options, SvelteConfig } from '@sveltejs/vite-plugin-svelte' */
3
3
  /** @import { PreprocessorGroup } from 'svelte/compiler' */
4
- /** @import { Plugin, ResolvedConfig, UserConfig, ViteDevServer } from 'vite' */
4
+ /** @import { Plugin, Manifest, ResolvedConfig, UserConfig, ViteDevServer, Rolldown, EnvironmentOptions } from 'vite' */
5
5
  import fs from 'node:fs';
6
6
  import path from 'node:path';
7
7
  import process from 'node:process';
@@ -23,16 +23,16 @@ import { create_assets } from '../../core/sync/create_manifest_data/index.js';
23
23
  import { runtime_directory, logger } from '../../core/utils.js';
24
24
  import { generate_manifest } from '../../core/generate_manifest/index.js';
25
25
  import { build_server_nodes } from './build/build_server.js';
26
- import { assets_base, find_deps, resolve_symlinks } from './build/utils.js';
26
+ import { find_deps, resolve_symlinks } from './build/utils.js';
27
27
  import { dev } from './dev/index.js';
28
28
  import { preview } from './preview/index.js';
29
29
  import {
30
30
  error_for_missing_config,
31
31
  get_config_aliases,
32
32
  normalize_id,
33
- stackless,
34
33
  strip_virtual_prefix
35
34
  } from './utils.js';
35
+ import { stackless } from '../../utils/error.js';
36
36
  import { write_client_manifest } from '../../core/sync/write_client_manifest.js';
37
37
  import prerender from '../../core/postbuild/prerender.js';
38
38
  import analyse from '../../core/postbuild/analyse.js';
@@ -147,7 +147,7 @@ let vite_plugin_svelte;
147
147
  /**
148
148
  * Returns the SvelteKit Vite plugins.
149
149
  * Since version 2.62.0 you can pass [configuration](configuration) directly, in which case `svelte.config.js` is ignored.
150
- * @param {import('@sveltejs/kit').KitConfig & Omit<SvelteConfig, 'onwarn'>} [config]
150
+ * @param {KitConfig & Omit<SvelteConfig, 'onwarn'>} [config]
151
151
  * @returns {Promise<Plugin[]>}
152
152
  */
153
153
  export async function sveltekit(config) {
@@ -190,7 +190,7 @@ export async function sveltekit(config) {
190
190
  ];
191
191
  }
192
192
 
193
- /** @param {import('vite').UserConfig | import('vite').ResolvedConfig} vite_config */
193
+ /** @param {UserConfig | ResolvedConfig} vite_config */
194
194
  function resolve_root(vite_config) {
195
195
  return posixify(vite_config.root ? path.resolve(vite_config.root) : process.cwd());
196
196
  }
@@ -199,10 +199,10 @@ function resolve_root(vite_config) {
199
199
  * Resolves the Svelte config using the `vite.config.root` setting before any
200
200
  * of our other plugins try to access the config objects
201
201
  * @param {{
202
- * vite_plugin_svelte_options: import('@sveltejs/vite-plugin-svelte').Options;
202
+ * vite_plugin_svelte_options: Options;
203
203
  * svelte_config: import('types').ValidatedConfig;
204
204
  * }} options
205
- * @return {import('vite').Plugin}
205
+ * @return {Plugin}
206
206
  */
207
207
  function plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }) {
208
208
  return {
@@ -214,7 +214,7 @@ function plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }) {
214
214
  handler(config) {
215
215
  root = resolve_root(config);
216
216
 
217
- /** @type {import('@sveltejs/vite-plugin-svelte').Options['preprocess']} */
217
+ /** @type {Options['preprocess']} */
218
218
  let preprocess = svelte_config.preprocess;
219
219
  if (Array.isArray(preprocess)) {
220
220
  preprocess = [...preprocess, warning_preprocessor];
@@ -253,8 +253,8 @@ function plugin_svelte_config({ vite_plugin_svelte_options, svelte_config }) {
253
253
  *
254
254
  * @param {object} opts
255
255
  * @param {import('types').ValidatedConfig} opts.svelte_config options are only resolved after the Vite `config` hook runs
256
- * @param {import('@sveltejs/kit').Adapter | undefined} opts.adapter
257
- * @return {import('vite').Plugin[]}
256
+ * @param {Adapter | undefined} opts.adapter
257
+ * @return {Plugin[]}
258
258
  */
259
259
  function kit({ svelte_config, adapter }) {
260
260
  /** @type {typeof import('vite')} */
@@ -478,9 +478,7 @@ function kit({ svelte_config, adapter }) {
478
478
 
479
479
  // These Kit dependencies are packaged as CommonJS, which means they must always be externalized.
480
480
  // Without this, the tests will still pass but `pnpm dev` will fail in projects that link `@sveltejs/kit`.
481
- /** @type {NonNullable<import('vite').UserConfig['ssr']>} */ (new_config.ssr).external = [
482
- 'cookie'
483
- ];
481
+ /** @type {NonNullable<UserConfig['ssr']>} */ (new_config.ssr).external = ['cookie'];
484
482
  }
485
483
 
486
484
  warn_overridden_config(config, new_config);
@@ -959,8 +957,10 @@ function kit({ svelte_config, adapter }) {
959
957
  }
960
958
  };
961
959
 
962
- /** @type {import('vite').Manifest} */
963
- let client_manifest;
960
+ /** @type {Manifest} */
961
+ let vite_server_manifest;
962
+ /** @type {Manifest | null} */
963
+ let vite_client_manifest = null;
964
964
  /** @type {import('types').Prerendered} */
965
965
  let prerendered;
966
966
 
@@ -971,7 +971,7 @@ function kit({ svelte_config, adapter }) {
971
971
 
972
972
  /**
973
973
  * Creates the service worker virtual modules
974
- * @type {import('vite').Plugin}
974
+ * @type {Plugin}
975
975
  */
976
976
  const plugin_service_worker = {
977
977
  name: 'vite-plugin-sveltekit-service-worker',
@@ -996,8 +996,9 @@ function kit({ svelte_config, adapter }) {
996
996
  load(id) {
997
997
  if (!build) {
998
998
  build = new Set();
999
- for (const key in client_manifest) {
1000
- const { file, css = [], assets = [] } = client_manifest[key];
999
+ const manifest = vite_client_manifest ?? vite_server_manifest;
1000
+ for (const key in manifest) {
1001
+ const { file, css = [], assets = [] } = manifest[key];
1001
1002
  build.add(file);
1002
1003
  css.forEach((file) => build.add(file));
1003
1004
  assets.forEach((file) => build.add(file));
@@ -1185,10 +1186,8 @@ function kit({ svelte_config, adapter }) {
1185
1186
 
1186
1187
  const inline = svelte_config.kit.output.bundleStrategy === 'inline';
1187
1188
 
1188
- const config_base = assets_base(kit);
1189
-
1190
1189
  /** @type {string} */
1191
- const base = kit.paths.assets || kit.paths.base || '/';
1190
+ const base = (kit.paths.assets || kit.paths.base) + '/';
1192
1191
  const root_to_assets = prefix + '/assets/';
1193
1192
  const assets_to_root =
1194
1193
  prefix
@@ -1198,7 +1197,7 @@ function kit({ svelte_config, adapter }) {
1198
1197
 
1199
1198
  new_config = {
1200
1199
  appType: 'custom',
1201
- base: config_base,
1200
+ base: './',
1202
1201
  build: {
1203
1202
  cssCodeSplit: !inline,
1204
1203
  cssMinify:
@@ -1282,43 +1281,36 @@ function kit({ svelte_config, adapter }) {
1282
1281
  }
1283
1282
  },
1284
1283
  experimental: {
1285
- // we can't change the base path per environment so we're setting the
1286
- // base prefix for files here ourselves
1287
- renderBuiltUrl:
1288
- // if the Vite base is relative, we need to ensure paths used during SSR are absolute
1289
- config_base === './'
1290
- ? (filename, { ssr }) => {
1291
- if (ssr) return base + filename;
1292
- }
1293
- : // but if the Vite base is absolute, we just need to ensure
1294
- // client paths are relative rather than absolute
1295
- (filename, { ssr, hostType }) => {
1296
- if (ssr) return;
1297
-
1298
- if (hostType === 'js') {
1299
- // We could always use a relative asset base path here, but it's better for performance not to.
1300
- // E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'.
1301
- // That's larger and takes longer to run and also causes an HTML diff between SSR and client
1302
- // causing us to do a more expensive hydration check.
1303
- return {
1304
- relative: kit.paths.relative !== false || !!kit.paths.assets
1305
- };
1306
- }
1307
-
1308
- // _app/immutable/assets files
1309
- if (filename.startsWith(root_to_assets)) {
1310
- return `./${filename.slice(root_to_assets.length)}`;
1311
- }
1312
-
1313
- // static dir files
1314
- return assets_to_root + filename;
1315
- }
1284
+ // Allows us to use relative paths in as many places as we can
1285
+ renderBuiltUrl(filename, { ssr, hostType }) {
1286
+ if (hostType === 'js') {
1287
+ // SSR builds should use an absolute path in JS modules to
1288
+ // match the default Vite behaviour
1289
+ if (ssr) return base + filename;
1290
+
1291
+ // We could always use a relative asset base path here, but it's better for performance not to.
1292
+ // E.g. Vite generates `new URL('/asset.png', import.meta).href` for a relative path vs just '/asset.png'.
1293
+ // That's larger and takes longer to run and also causes an HTML diff between SSR and client
1294
+ // causing us to do a more expensive hydration check.
1295
+ return {
1296
+ relative: kit.paths.relative !== false || !!kit.paths.assets
1297
+ };
1298
+ }
1299
+
1300
+ // _app/immutable/assets files
1301
+ if (filename.startsWith(root_to_assets)) {
1302
+ return `./${filename.slice(root_to_assets.length)}`;
1303
+ }
1304
+
1305
+ // static dir files
1306
+ return assets_to_root + filename;
1307
+ }
1316
1308
  },
1317
1309
  publicDir: kit.files.assets
1318
1310
  };
1319
1311
 
1320
1312
  if (service_worker_entry_file) {
1321
- /** @type {Record<string, import('vite').EnvironmentOptions>} */ (
1313
+ /** @type {Record<string, EnvironmentOptions>} */ (
1322
1314
  new_config.environments
1323
1315
  ).serviceWorker = {
1324
1316
  build: {
@@ -1409,15 +1401,15 @@ function kit({ svelte_config, adapter }) {
1409
1401
  }
1410
1402
  mkdirp(out);
1411
1403
 
1412
- const server_bundle = /** @type {import('vite').Rolldown.RolldownOutput} */ (
1404
+ const { output: server_chunks } = /** @type {Rolldown.RolldownOutput} */ (
1413
1405
  await builder.build(builder.environments.ssr)
1414
1406
  );
1415
1407
 
1416
1408
  const verbose = vite_config.logLevel === 'info';
1417
1409
  const log = logger({ verbose });
1418
1410
 
1419
- /** @type {import('vite').Manifest} */
1420
- const server_manifest = JSON.parse(read(`${out}/server/.vite/manifest.json`));
1411
+ /** @type {Manifest} */
1412
+ vite_server_manifest = JSON.parse(read(`${out}/server/.vite/manifest.json`));
1421
1413
 
1422
1414
  /** @type {import('types').BuildData} */
1423
1415
  const build_data = {
@@ -1427,7 +1419,7 @@ function kit({ svelte_config, adapter }) {
1427
1419
  out_dir: out,
1428
1420
  service_worker: service_worker_entry_file ? 'service-worker.js' : null, // TODO make file configurable?
1429
1421
  client: null,
1430
- server_manifest
1422
+ server_manifest: vite_server_manifest
1431
1423
  };
1432
1424
 
1433
1425
  const manifest_path = `${out}/server/manifest-full.js`;
@@ -1443,18 +1435,30 @@ function kit({ svelte_config, adapter }) {
1443
1435
  })};\n`
1444
1436
  );
1445
1437
 
1438
+ const assets_path = `${kit.appDir}/immutable/assets`;
1439
+
1440
+ // first, build server nodes without the client manifest so we can analyse it
1441
+ build_server_nodes(
1442
+ out,
1443
+ kit,
1444
+ manifest_data,
1445
+ vite_server_manifest,
1446
+ null,
1447
+ assets_path,
1448
+ server_chunks,
1449
+ root
1450
+ );
1451
+
1446
1452
  log.info('Analysing routes');
1447
1453
 
1448
1454
  const { metadata } = await analyse({
1449
1455
  hash: kit.router.type === 'hash',
1450
1456
  manifest_path,
1451
1457
  manifest_data,
1452
- server_manifest,
1458
+ server_manifest: vite_server_manifest,
1453
1459
  tracked_features,
1454
1460
  env,
1455
- out,
1456
1461
  remotes,
1457
- root,
1458
1462
  vite_config_file: vite_config.configFile
1459
1463
  });
1460
1464
 
@@ -1470,178 +1474,178 @@ function kit({ svelte_config, adapter }) {
1470
1474
  metadata.nodes
1471
1475
  );
1472
1476
 
1473
- const nodes = Object.values(
1474
- /** @type {import('types').ServerMetadata} */ (build_metadata).nodes
1475
- );
1476
-
1477
- // Through the finished analysis we can now check if any node has server or universal load functions
1478
- const has_server_load = nodes.some((node) => node.has_server_load);
1479
- const has_universal_load = nodes.some((node) => node.has_universal_load);
1480
-
1481
- if (builder.environments.client.config.define) {
1482
- builder.environments.client.config.define.__SVELTEKIT_HAS_SERVER_LOAD__ =
1483
- s(has_server_load);
1484
- builder.environments.client.config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ =
1485
- s(has_universal_load);
1486
- }
1487
-
1488
- const { output: client_chunks } = /** @type {import('vite').Rolldown.RolldownOutput} */ (
1489
- await builder.build(builder.environments.client)
1490
- );
1491
-
1492
- // We use `build.ssrEmitAssets` so that asset URLs created from
1493
- // imports in server-only modules correspond to files in the build,
1494
- // but we don't want to copy over CSS imports as these are already
1495
- // accounted for in the client bundle. In most cases it would be
1496
- // a no-op, but for SSR builds `url(...)` paths are handled
1497
- // differently (relative for client, absolute for server)
1498
- // resulting in different hashes, and thus duplication
1499
- const ssr_stylesheets = new Set(
1500
- Object.values(server_manifest)
1501
- .map((chunk) => chunk.css ?? [])
1502
- .flat()
1503
- );
1504
-
1505
- const assets_path = `${kit.appDir}/immutable/assets`;
1506
1477
  const server_assets = `${out}/server/${assets_path}`;
1507
1478
  const client_assets = `${out}/client/${assets_path}`;
1508
1479
 
1509
- if (fs.existsSync(server_assets)) {
1510
- for (const file of fs.readdirSync(server_assets)) {
1511
- const src = `${server_assets}/${file}`;
1512
- const dest = `${client_assets}/${file}`;
1513
-
1514
- if (fs.existsSync(dest) || ssr_stylesheets.has(`${assets_path}/${file}`)) {
1515
- continue;
1516
- }
1480
+ const skip_client_build = manifest_data.nodes.every(
1481
+ (node) => node.page_options?.csr === false
1482
+ );
1517
1483
 
1518
- if (file.endsWith('.css')) {
1519
- // make absolute paths in CSS relative, for portability
1520
- const content = fs
1521
- .readFileSync(src, 'utf-8')
1522
- .replaceAll(`${kit.paths.base}/${assets_path}`, '.');
1484
+ if (!skip_client_build) {
1485
+ const nodes = Object.values(build_metadata.nodes);
1523
1486
 
1524
- fs.writeFileSync(src, content);
1525
- }
1487
+ // Through the finished analysis we can now check if any node has server or universal load functions
1488
+ const has_server_load = nodes.some((node) => node.has_server_load);
1489
+ const has_universal_load = nodes.some((node) => node.has_universal_load);
1526
1490
 
1527
- copy(src, dest);
1491
+ if (builder.environments.client.config.define) {
1492
+ builder.environments.client.config.define.__SVELTEKIT_HAS_SERVER_LOAD__ =
1493
+ s(has_server_load);
1494
+ builder.environments.client.config.define.__SVELTEKIT_HAS_UNIVERSAL_LOAD__ =
1495
+ s(has_universal_load);
1528
1496
  }
1529
- }
1530
1497
 
1531
- /** @type {import('vite').Manifest} */
1532
- client_manifest = JSON.parse(read(`${out}/client/.vite/manifest.json`));
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
- };
1498
+ const { output: client_chunks } = /** @type {Rolldown.RolldownOutput} */ (
1499
+ await builder.build(builder.environments.client)
1500
+ );
1555
1501
 
1556
- // In case of server-side route resolution, we create a purpose-built route manifest that is
1557
- // similar to that on the client, with as much information computed upfront so that we
1558
- // don't need to include any code of the actual routes in the server bundle.
1559
- if (svelte_config.kit.router.resolution === 'server') {
1560
- const nodes = manifest_data.nodes.map((node, i) => {
1561
- if (node.component || node.universal) {
1562
- const entry = `${out_dir}/generated/client-optimized/nodes/${i}.js`;
1563
- const deps = deps_of(entry, true);
1564
- const file = resolve_symlinks(
1565
- client_manifest,
1566
- `${out_dir}/generated/client-optimized/nodes/${i}.js`,
1567
- root
1568
- ).chunk.file;
1569
-
1570
- return { file, css: deps.stylesheets };
1502
+ // We use `build.ssrEmitAssets` so that asset URLs created from
1503
+ // imports in server-only modules correspond to files in the build,
1504
+ // but we don't want to copy over CSS imports as these are already
1505
+ // accounted for in the client bundle. In most cases it would be
1506
+ // a no-op, but for SSR builds `url(...)` paths are handled
1507
+ // differently (relative for client, absolute for server)
1508
+ // resulting in different hashes, and thus duplication
1509
+ const ssr_stylesheets = new Set(
1510
+ Object.values(vite_server_manifest)
1511
+ .map((chunk) => chunk.css ?? [])
1512
+ .flat()
1513
+ );
1514
+
1515
+ if (fs.existsSync(server_assets)) {
1516
+ for (const file of fs.readdirSync(server_assets)) {
1517
+ const src = `${server_assets}/${file}`;
1518
+ const dest = `${client_assets}/${file}`;
1519
+
1520
+ if (fs.existsSync(dest) || ssr_stylesheets.has(`${assets_path}/${file}`)) {
1521
+ continue;
1571
1522
  }
1572
- });
1573
- build_data.client.nodes = nodes.map((node) => node?.file);
1574
- build_data.client.css = nodes.map((node) => node?.css);
1575
-
1576
- build_data.client.routes = compact(
1577
- manifest_data.routes.map((route) => {
1578
- if (!route.page) return;
1579
-
1580
- return {
1581
- id: route.id,
1582
- pattern: route.pattern,
1583
- params: route.params,
1584
- layouts: route.page.layouts.map((l) =>
1585
- l !== undefined ? [metadata.nodes[l].has_server_load, l] : undefined
1586
- ),
1587
- errors: route.page.errors,
1588
- leaf: [metadata.nodes[route.page.leaf].has_server_load, route.page.leaf]
1589
- };
1590
- })
1591
- );
1523
+
1524
+ copy(src, dest);
1525
+ }
1592
1526
  }
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
1527
 
1606
- if (svelte_config.kit.output.bundleStrategy === 'inline') {
1607
- const style = /** @type {import('vite').Rolldown.OutputAsset} */ (
1608
- client_chunks.find(
1609
- (chunk) =>
1610
- chunk.type === 'asset' && chunk.names.length === 1 && chunk.names[0] === 'style.css'
1528
+ const vite_manifest = (vite_client_manifest = JSON.parse(
1529
+ read(`${out}/client/.vite/manifest.json`)
1530
+ ));
1531
+
1532
+ /**
1533
+ * @param {string} entry
1534
+ * @param {boolean} [add_dynamic_css]
1535
+ */
1536
+ const deps_of = (entry, add_dynamic_css = false) =>
1537
+ find_deps(vite_manifest, posixify(path.relative(root, entry)), add_dynamic_css, root);
1538
+
1539
+ if (svelte_config.kit.output.bundleStrategy === 'split') {
1540
+ const start = deps_of(`${runtime_directory}/client/entry.js`);
1541
+ const app = deps_of(`${out_dir}/generated/client-optimized/app.js`);
1542
+
1543
+ build_data.client = {
1544
+ start: start.file,
1545
+ app: app.file,
1546
+ imports: [...start.imports, ...app.imports],
1547
+ stylesheets: [...start.stylesheets, ...app.stylesheets],
1548
+ fonts: [...start.fonts, ...app.fonts],
1549
+ uses_env_dynamic_public: client_chunks.some(
1550
+ (chunk) => chunk.type === 'chunk' && chunk.modules[sveltekit_env_public_client]
1611
1551
  )
1612
- );
1552
+ };
1613
1553
 
1614
- build_data.client.inline = {
1615
- script: read(`${out}/client/${start.file}`),
1616
- style: /** @type {string | undefined} */ (style?.source)
1554
+ // In case of server-side route resolution, we create a purpose-built route manifest that is
1555
+ // similar to that on the client, with as much information computed upfront so that we
1556
+ // don't need to include any code of the actual routes in the server bundle.
1557
+ if (svelte_config.kit.router.resolution === 'server') {
1558
+ const nodes = manifest_data.nodes.map((node, i) => {
1559
+ if (node.component || node.universal) {
1560
+ const entry = `${out_dir}/generated/client-optimized/nodes/${i}.js`;
1561
+ const deps = deps_of(entry, true);
1562
+ const file = resolve_symlinks(
1563
+ vite_manifest,
1564
+ `${out_dir}/generated/client-optimized/nodes/${i}.js`,
1565
+ root
1566
+ ).chunk.file;
1567
+
1568
+ return { file, css: deps.stylesheets };
1569
+ }
1570
+ });
1571
+ build_data.client.nodes = nodes.map((node) => node?.file);
1572
+ build_data.client.css = nodes.map((node) => node?.css);
1573
+
1574
+ build_data.client.routes = compact(
1575
+ manifest_data.routes.map((route) => {
1576
+ if (!route.page) return;
1577
+
1578
+ return {
1579
+ id: route.id,
1580
+ pattern: route.pattern,
1581
+ params: route.params,
1582
+ layouts: route.page.layouts.map((l) =>
1583
+ l !== undefined ? [metadata.nodes[l].has_server_load, l] : undefined
1584
+ ),
1585
+ errors: route.page.errors,
1586
+ leaf: [metadata.nodes[route.page.leaf].has_server_load, route.page.leaf]
1587
+ };
1588
+ })
1589
+ );
1590
+ }
1591
+ } else {
1592
+ const start = deps_of(`${runtime_directory}/client/bundle.js`);
1593
+
1594
+ build_data.client = {
1595
+ start: start.file,
1596
+ imports: start.imports,
1597
+ stylesheets: start.stylesheets,
1598
+ fonts: start.fonts,
1599
+ uses_env_dynamic_public: client_chunks.some(
1600
+ (chunk) => chunk.type === 'chunk' && chunk.modules[sveltekit_env_public_client]
1601
+ )
1617
1602
  };
1603
+
1604
+ if (svelte_config.kit.output.bundleStrategy === 'inline') {
1605
+ const style = /** @type {Rolldown.OutputAsset} */ (
1606
+ client_chunks.find(
1607
+ (chunk) =>
1608
+ chunk.type === 'asset' &&
1609
+ chunk.names.length === 1 &&
1610
+ chunk.names[0] === 'style.css'
1611
+ )
1612
+ );
1613
+
1614
+ build_data.client.inline = {
1615
+ script: read(`${out}/client/${start.file}`),
1616
+ style: /** @type {string | undefined} */ (style?.source)
1617
+ };
1618
+ }
1618
1619
  }
1619
- }
1620
1620
 
1621
- // regenerate manifest now that we have client entry...
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
- );
1621
+ // regenerate manifest now that we have client entry...
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
+ );
1633
1633
 
1634
- // regenerate nodes with the client manifest...
1635
- build_server_nodes(
1636
- out,
1637
- kit,
1638
- manifest_data,
1639
- server_manifest,
1640
- client_manifest,
1641
- assets_path,
1642
- client_chunks,
1643
- root
1644
- );
1634
+ // regenerate nodes with the client manifest...
1635
+ build_server_nodes(
1636
+ out,
1637
+ kit,
1638
+ manifest_data,
1639
+ vite_server_manifest,
1640
+ vite_manifest,
1641
+ assets_path,
1642
+ client_chunks,
1643
+ root
1644
+ );
1645
+ } else {
1646
+ copy(server_assets, client_assets);
1647
+ copy(kit.files.assets, `${out}/client`);
1648
+ }
1645
1649
 
1646
1650
  // ...and prerender
1647
1651
  const prerender_results = await prerender({
@@ -1661,7 +1665,7 @@ function kit({ svelte_config, adapter }) {
1661
1665
  remotes,
1662
1666
  metadata,
1663
1667
  process.cwd(),
1664
- server_bundle,
1668
+ server_chunks,
1665
1669
  vite_config.build.sourcemap
1666
1670
  );
1667
1671
 
@@ -1,9 +1,10 @@
1
+ /** @import { PageOptions } from './types.js' */
1
2
  import path from 'node:path';
2
3
  import { tsPlugin } from '@sveltejs/acorn-typescript';
3
4
  import { Parser } from 'acorn';
4
5
  import { read } from '../../../utils/filesystem.js';
5
6
 
6
- const valid_page_options_array = /** @type {const} */ ([
7
+ export const valid_page_options_array = /** @type {const} */ ([
7
8
  'ssr',
8
9
  'prerender',
9
10
  'csr',
@@ -16,9 +17,6 @@ const valid_page_options_array = /** @type {const} */ ([
16
17
  /** @type {Set<string>} */
17
18
  const valid_page_options = new Set(valid_page_options_array);
18
19
 
19
- /** @typedef {typeof valid_page_options_array[number]} ValidPageOption */
20
- /** @typedef {Partial<Record<ValidPageOption, any>>} PageOptions */
21
-
22
20
  const skip_parsing_regex = new RegExp(
23
21
  `${Array.from(valid_page_options).join('|')}|(?:export[\\s\\n]+\\*[\\s\\n]+from)`
24
22
  );
@@ -0,0 +1,14 @@
1
+ import type { PrerenderOption, TrailingSlash } from 'types';
2
+ import type { valid_page_options_array } from './index.js';
3
+
4
+ type ValidPageOption = (typeof valid_page_options_array)[number];
5
+
6
+ export type PageOptions = Partial<{
7
+ [K in ValidPageOption]: K extends 'ssr' | 'csr'
8
+ ? boolean
9
+ : K extends 'prerender'
10
+ ? PrerenderOption
11
+ : K extends 'trailingSlash'
12
+ ? TrailingSlash
13
+ : any;
14
+ }>;