@sveltejs/kit 3.0.0-next.2 → 3.0.0-next.4

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 (33) 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/exports/public.d.ts +1 -1
  5. package/src/exports/vite/build/build_server.js +43 -58
  6. package/src/exports/vite/build/remote.js +18 -11
  7. package/src/exports/vite/build/utils.js +0 -8
  8. package/src/exports/vite/index.js +220 -216
  9. package/src/runtime/app/server/remote/command.js +0 -3
  10. package/src/runtime/app/server/remote/form.js +18 -13
  11. package/src/runtime/app/server/remote/prerender.js +28 -34
  12. package/src/runtime/app/server/remote/query.js +105 -94
  13. package/src/runtime/app/server/remote/requested.js +14 -10
  14. package/src/runtime/app/server/remote/shared.js +25 -19
  15. package/src/runtime/client/client.js +25 -15
  16. package/src/runtime/client/remote-functions/command.svelte.js +5 -30
  17. package/src/runtime/client/remote-functions/form.svelte.js +62 -82
  18. package/src/runtime/client/remote-functions/prerender.svelte.js +14 -6
  19. package/src/runtime/client/remote-functions/query/index.js +6 -14
  20. package/src/runtime/client/remote-functions/query/instance.svelte.js +37 -8
  21. package/src/runtime/client/remote-functions/query/proxy.js +3 -3
  22. package/src/runtime/client/remote-functions/query-batch.svelte.js +59 -68
  23. package/src/runtime/client/remote-functions/query-live/instance.svelte.js +21 -6
  24. package/src/runtime/client/remote-functions/shared.svelte.js +76 -59
  25. package/src/runtime/server/page/render.js +20 -80
  26. package/src/runtime/server/page/server_routing.js +20 -15
  27. package/src/runtime/server/remote.js +296 -204
  28. package/src/runtime/server/respond.js +4 -2
  29. package/src/types/global-private.d.ts +3 -3
  30. package/src/types/internal.d.ts +53 -34
  31. package/src/version.js +1 -1
  32. package/types/index.d.ts +6 -5
  33. package/types/index.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "3.0.0-next.2",
3
+ "version": "3.0.0-next.4",
4
4
  "description": "SvelteKit is the fastest way to build Svelte apps",
5
5
  "keywords": [
6
6
  "framework",
@@ -37,7 +37,7 @@
37
37
  "dts-buddy": "^0.8.0",
38
38
  "jsdom": "^29.1.1",
39
39
  "rolldown": "^1.0.0-rc.6",
40
- "svelte": "^5.55.7",
40
+ "svelte": "^5.56.3",
41
41
  "svelte-preprocess": "^6.0.5",
42
42
  "typescript": "~6.0.0",
43
43
  "vite": "^8.0.10",
@@ -10,7 +10,6 @@ import { has_server_load, resolve_route } from '../../utils/routing.js';
10
10
  import { check_feature } from '../../utils/features.js';
11
11
  import { createReadableStream } from '@sveltejs/kit/node';
12
12
  import { PageNodes } from '../../utils/page_nodes.js';
13
- import { build_server_nodes } from '../../exports/vite/build/build_server.js';
14
13
 
15
14
  export default forked(import.meta.url, analyse);
16
15
 
@@ -22,9 +21,7 @@ export default forked(import.meta.url, analyse);
22
21
  * server_manifest: import('vite').Manifest;
23
22
  * tracked_features: Record<string, string[]>;
24
23
  * env: Record<string, string>;
25
- * out: string;
26
24
  * remotes: RemoteChunk[];
27
- * root: string;
28
25
  * vite_config_file: string | undefined;
29
26
  * }} opts
30
27
  */
@@ -35,9 +32,7 @@ async function analyse({
35
32
  server_manifest,
36
33
  tracked_features,
37
34
  env,
38
- out,
39
35
  remotes,
40
- root,
41
36
  vite_config_file
42
37
  }) {
43
38
  /** @type {import('@sveltejs/kit').SSRManifest} */
@@ -67,9 +62,6 @@ async function analyse({
67
62
  internal.set_manifest(manifest);
68
63
  internal.set_read_implementation((file) => createReadableStream(`${server_root}/server/${file}`));
69
64
 
70
- // first, build server nodes without the client manifest so we can analyse it
71
- build_server_nodes(out, config, manifest_data, server_manifest, null, null, null, root);
72
-
73
65
  /** @type {import('types').ServerMetadata} */
74
66
  const metadata = {
75
67
  nodes: [],
@@ -210,6 +210,8 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env, vit
210
210
 
211
211
  const seen = new Set();
212
212
  const written = new Set();
213
+
214
+ /** @type {Map<string, Promise<any>>} */
213
215
  const remote_responses = new Map();
214
216
 
215
217
  /** @type {Map<string, Set<string>>} */
@@ -1655,7 +1655,7 @@ export interface SSRManifest {
1655
1655
 
1656
1656
  /** private fields */
1657
1657
  _: {
1658
- client: NonNullable<BuildData['client']>;
1658
+ client: BuildData['client'];
1659
1659
  nodes: SSRNodeLoader[];
1660
1660
  /** hashed filename -> import to that file */
1661
1661
  remotes: Record<string, () => Promise<any>>;
@@ -16,39 +16,16 @@ import { fix_css_urls } from '../../../utils/css.js';
16
16
  import { escape_for_interpolation } from '../../../utils/escape.js';
17
17
 
18
18
  /**
19
- * @overload Build without the client manifest so we can analyse the nodes.
20
19
  * @param {string} out
21
20
  * @param {ValidatedKitConfig} kit
22
21
  * @param {ManifestData} manifest_data
23
22
  * @param {Manifest} server_manifest
24
- * @param {null} client_manifest
25
- * @param {null} assets_path
26
- * @param {null} client_chunks
27
- * @param {string} root
28
- * @returns {void}
29
- */
30
- /**
31
- * @overload Or build with the client manifest
32
- * @param {string} out
33
- * @param {ValidatedKitConfig} kit
34
- * @param {ManifestData} manifest_data
35
- * @param {Manifest} server_manifest
36
- * @param {Manifest} client_manifest
23
+ * @param {Manifest | null} client_manifest
37
24
  * @param {string} assets_path
38
- * @param {Rolldown.RolldownOutput['output']} client_chunks
25
+ * @param {(Rolldown.OutputAsset | Rolldown.OutputChunk)[]} chunks
39
26
  * @param {string} root
40
27
  * @returns {void}
41
28
  */
42
- /**
43
- * @param {string} out
44
- * @param {ValidatedKitConfig} kit
45
- * @param {ManifestData} manifest_data
46
- * @param {Manifest} server_manifest
47
- * @param {Manifest | null} client_manifest
48
- * @param {string | null} assets_path
49
- * @param {Rolldown.RolldownOutput['output'] | null} client_chunks
50
- * @param {string} root
51
- */
52
29
  export function build_server_nodes(
53
30
  out,
54
31
  kit,
@@ -56,7 +33,7 @@ export function build_server_nodes(
56
33
  server_manifest,
57
34
  client_manifest,
58
35
  assets_path,
59
- client_chunks,
36
+ chunks,
60
37
  root
61
38
  ) {
62
39
  mkdirp(`${out}/server/nodes`);
@@ -75,8 +52,8 @@ export function build_server_nodes(
75
52
  */
76
53
  let prepare_css_for_inlining = (css) => s(css);
77
54
 
78
- if (client_chunks && kit.inlineStyleThreshold > 0 && kit.output.bundleStrategy === 'split') {
79
- for (const chunk of client_chunks) {
55
+ if (chunks && kit.inlineStyleThreshold > 0 && kit.output.bundleStrategy === 'split') {
56
+ for (const chunk of chunks) {
80
57
  if (chunk.type !== 'asset' || !chunk.fileName.endsWith('.css')) {
81
58
  continue;
82
59
  }
@@ -132,6 +109,9 @@ export function build_server_nodes(
132
109
  }
133
110
  }
134
111
 
112
+ /** path to the `.svelte-kit` directory */
113
+ const out_dir = normalizePath(kit.outDir);
114
+
135
115
  for (let i = 0; i < manifest_data.nodes.length; i++) {
136
116
  const node = manifest_data.nodes[i];
137
117
 
@@ -159,7 +139,7 @@ export function build_server_nodes(
159
139
  ? node.child_pages.some((child) => child.page_options?.ssr !== false)
160
140
  : node.page_options?.ssr !== false;
161
141
 
162
- if (node.component && client_manifest && uses_server_component) {
142
+ if (node.component && uses_server_component) {
163
143
  exports.push(
164
144
  'let component_cache;',
165
145
  `export const component = async () => component_cache ??= (await import('../${
@@ -189,18 +169,7 @@ export function build_server_nodes(
189
169
  exports.push(`export const server_id = ${s(node.server)};`);
190
170
  }
191
171
 
192
- if (
193
- client_manifest &&
194
- (node.universal || node.component) &&
195
- kit.output.bundleStrategy === 'split'
196
- ) {
197
- const entry_path = `${normalizePath(kit.outDir)}/generated/client-optimized/nodes/${i}.js`;
198
- const entry = find_deps(client_manifest, entry_path, true, root);
199
-
200
- // Eagerly load client stylesheets and fonts imported by the SSR-ed page to avoid FOUC.
201
- // However, if it is not used during SSR (not present in the server manifest),
202
- // then it can be lazily loaded in the browser.
203
-
172
+ if ((node.universal || node.component) && kit.output.bundleStrategy === 'split') {
204
173
  /** @type {AssetDependencies | undefined} */
205
174
  let component;
206
175
  if (node.component) {
@@ -213,25 +182,41 @@ export function build_server_nodes(
213
182
  universal = find_deps(server_manifest, node.universal, true, root);
214
183
  }
215
184
 
216
- /** @type {Set<string>} */
217
- const eager_css = new Set();
185
+ if (client_manifest) {
186
+ const entry_path = `${out_dir}/generated/client-optimized/nodes/${i}.js`;
187
+ const entry = find_deps(client_manifest, entry_path, true, root);
218
188
 
219
- entry.stylesheet_map.forEach((value, filepath) => {
220
- // pages and layouts are renamed to node indexes when optimised for the client
221
- // so we use the original filename instead to check against the server manifest
222
- if (filepath === entry_path) {
223
- filepath = node.component ?? filepath;
224
- }
189
+ // Eagerly load client stylesheets and fonts imported by the SSR-ed page to avoid FOUC.
190
+ // However, if it is not used during SSR (not present in the server manifest),
191
+ // then it can be lazily loaded in the browser.
225
192
 
226
- if (component?.stylesheet_map.has(filepath) || universal?.stylesheet_map.has(filepath)) {
227
- value.css.forEach((file) => eager_css.add(file));
228
- value.assets.forEach((file) => eager_assets.add(file));
229
- }
230
- });
193
+ /** @type {Set<string>} */
194
+ const eager_css = new Set();
195
+
196
+ entry.stylesheet_map.forEach((value, filepath) => {
197
+ // pages and layouts are renamed to node indexes when optimised for the client
198
+ // so we use the original filename instead to check against the server manifest
199
+ if (filepath === entry_path) {
200
+ filepath = node.component ?? filepath;
201
+ }
202
+
203
+ if (component?.stylesheet_map.has(filepath) || universal?.stylesheet_map.has(filepath)) {
204
+ value.css.forEach((file) => eager_css.add(file));
205
+ value.assets.forEach((file) => eager_assets.add(file));
206
+ }
207
+ });
231
208
 
232
- imported = entry.imports;
233
- stylesheets = Array.from(eager_css);
234
- fonts = filter_fonts(Array.from(eager_assets));
209
+ imported = entry.imports;
210
+ stylesheets = Array.from(eager_css);
211
+ fonts = filter_fonts(Array.from(eager_assets));
212
+ } else {
213
+ for (const entry of [component, universal]) {
214
+ if (!entry) continue;
215
+ imported.push(...entry.imports);
216
+ stylesheets.push(...entry.stylesheets);
217
+ fonts.push(...entry.fonts);
218
+ }
219
+ }
235
220
  }
236
221
 
237
222
  exports.push(
@@ -248,7 +233,7 @@ export function build_server_nodes(
248
233
 
249
234
  // Keep track of Vite asset filenames so that we avoid touching unrelated ones
250
235
  // when adjusting the inlined CSS
251
- if (stylesheets_to_inline.size && assets_path && eager_assets.size) {
236
+ if (stylesheets_to_inline.size && eager_assets.size) {
252
237
  vite_assets = new Set(
253
238
  Array.from(eager_assets).map((asset) => {
254
239
  return decodeURIComponent(asset.replace(`${assets_path}/`, ''));
@@ -13,7 +13,7 @@ import { posixify } from '../../../utils/os.js';
13
13
  * @param {Array<{ hash: string, file: string }>} remotes
14
14
  * @param {ServerMetadata} metadata
15
15
  * @param {string} cwd
16
- * @param {Rolldown.RolldownOutput} server_bundle
16
+ * @param {(Rolldown.OutputAsset | Rolldown.OutputChunk)[]} server_chunks
17
17
  * @param {NonNullable<import('vitest/config').ViteUserConfig['build']>['sourcemap']} sourcemap
18
18
  */
19
19
  export async function treeshake_prerendered_remotes(
@@ -22,11 +22,14 @@ export async function treeshake_prerendered_remotes(
22
22
  remotes,
23
23
  metadata,
24
24
  cwd,
25
- server_bundle,
25
+ server_chunks,
26
26
  sourcemap
27
27
  ) {
28
28
  if (remotes.length === 0) return;
29
29
 
30
+ /** @type {string[]} */
31
+ const chunk_paths = [];
32
+
30
33
  for (const remote of remotes) {
31
34
  const exports_map = metadata.remotes.get(remote.hash);
32
35
  if (!exports_map) continue;
@@ -45,7 +48,7 @@ export async function treeshake_prerendered_remotes(
45
48
  // remove file extension
46
49
  const remote_filename = path.basename(remote.file).split('.').slice(0, -1).join('.');
47
50
 
48
- const remote_chunk = Object.values(server_bundle).find((chunk) => {
51
+ const remote_chunk = server_chunks.find((chunk) => {
49
52
  return chunk.name === remote_filename;
50
53
  });
51
54
 
@@ -88,8 +91,13 @@ export async function treeshake_prerendered_remotes(
88
91
 
89
92
  const stubbed = modified_code.toString();
90
93
  fs.writeFileSync(chunk_path, stubbed);
94
+ chunk_paths.push(chunk_path);
95
+ }
96
+
97
+ if (!chunk_paths.length) return;
91
98
 
92
- const bundle = /** @type {import('vite').Rolldown.RolldownOutput} */ (
99
+ for (const chunk_path of chunk_paths) {
100
+ const bundle = /** @type {Rolldown.RolldownOutput} */ (
93
101
  await vite.build({
94
102
  configFile: false,
95
103
  build: {
@@ -97,7 +105,7 @@ export async function treeshake_prerendered_remotes(
97
105
  ssr: true,
98
106
  target: 'esnext',
99
107
  sourcemap,
100
- rollupOptions: {
108
+ rolldownOptions: {
101
109
  // avoid resolving imports
102
110
  external: (id) => !id.endsWith(chunk_path),
103
111
  input: {
@@ -108,14 +116,13 @@ export async function treeshake_prerendered_remotes(
108
116
  })
109
117
  );
110
118
 
111
- const chunk = bundle.output.find(
112
- (output) => output.type === 'chunk' && output.name === 'treeshaken'
113
- );
114
- if (chunk && chunk.type === 'chunk') {
115
- fs.writeFileSync(chunk_path, chunk.code);
119
+ for (const output of bundle.output) {
120
+ if (output.type !== 'chunk' || output.name !== 'treeshaken') return;
121
+
122
+ fs.writeFileSync(chunk_path, output.code);
116
123
 
117
124
  const chunk_sourcemap = bundle.output.find(
118
- (output) => output.type === 'asset' && output.fileName === chunk.fileName + '.map'
125
+ (o) => o.type === 'asset' && o.fileName === output.fileName + '.map'
119
126
  );
120
127
  if (chunk_sourcemap && chunk_sourcemap.type === 'asset') {
121
128
  fs.writeFileSync(chunk_path + '.map', chunk_sourcemap.source);
@@ -124,14 +124,6 @@ export function filter_fonts(assets) {
124
124
  return assets.filter((asset) => /\.(woff2?|ttf|otf)$/.test(asset));
125
125
  }
126
126
 
127
- /**
128
- * @param {import('types').ValidatedKitConfig} config
129
- * @returns {string}
130
- */
131
- export function assets_base(config) {
132
- return (config.paths.assets || config.paths.base || '.') + '/';
133
- }
134
-
135
127
  /**
136
128
  * Writes a function with arguments used by a template literal.
137
129
  * This helps us store strings in a module and inject values at runtime.