@sveltejs/kit 1.0.0-next.385 → 1.0.0-next.388

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.
@@ -1672,6 +1672,13 @@ function create_client({ target, session, base, trailing_slash }) {
1672
1672
  }
1673
1673
  });
1674
1674
 
1675
+ // fix link[rel=icon], because browsers will occasionally try to load relative
1676
+ // URLs after a pushState/replaceState, resulting in a 404 — see
1677
+ // https://github.com/sveltejs/kit/issues/3748#issuecomment-1125980897
1678
+ for (const link of document.querySelectorAll('link')) {
1679
+ if (link.rel === 'icon') link.href = link.href;
1680
+ }
1681
+
1675
1682
  addEventListener('pageshow', (event) => {
1676
1683
  // If the user navigates to another site and then uses the back button and
1677
1684
  // bfcache hits, we need to set navigating to null, the site doesn't know
@@ -1375,7 +1375,9 @@ async function render_response({
1375
1375
  /** @type {import('types').NormalizedLoadOutputCache | undefined} */
1376
1376
  let cache;
1377
1377
 
1378
- if (error) {
1378
+ const stack = error?.stack;
1379
+
1380
+ if (options.dev && error) {
1379
1381
  error.stack = options.get_stack(error);
1380
1382
  }
1381
1383
 
@@ -1410,20 +1412,15 @@ async function render_response({
1410
1412
  }
1411
1413
 
1412
1414
  const session = writable($session);
1415
+ // Even if $session isn't accessed, it still ends up serialized in the rendered HTML
1416
+ is_private = is_private || (cache?.private ?? (!!$session && Object.keys($session).length > 0));
1413
1417
 
1414
1418
  /** @type {Record<string, any>} */
1415
1419
  const props = {
1416
1420
  stores: {
1417
1421
  page: writable(null),
1418
1422
  navigating: writable(null),
1419
- /** @type {import('svelte/store').Writable<App.Session>} */
1420
- session: {
1421
- ...session,
1422
- subscribe: (fn) => {
1423
- is_private = cache?.private ?? true;
1424
- return session.subscribe(fn);
1425
- }
1426
- },
1423
+ session,
1427
1424
  updated
1428
1425
  },
1429
1426
  /** @type {import('types').Page} */
@@ -1623,6 +1620,11 @@ async function render_response({
1623
1620
  }
1624
1621
  }
1625
1622
 
1623
+ if (options.dev && error) {
1624
+ // reset stack, otherwise it may be 'fixed' a second time
1625
+ error.stack = stack;
1626
+ }
1627
+
1626
1628
  return new Response(html, {
1627
1629
  status,
1628
1630
  headers
@@ -54,7 +54,7 @@ function create_builder({ config, build_data, prerendered, log }) {
54
54
  // TODO routes should come pre-filtered
55
55
  function not_prerendered(route) {
56
56
  if (route.type === 'page' && route.path) {
57
- return !prerendered_paths.has(route.path);
57
+ return !prerendered_paths.has(route.path) && !prerendered_paths.has(route.path + '/');
58
58
  }
59
59
 
60
60
  return true;
@@ -157,10 +157,7 @@ function create_builder({ config, build_data, prerendered, log }) {
157
157
  },
158
158
 
159
159
  writeClient(dest) {
160
- return [
161
- ...copy(`${config.kit.outDir}/output/client`, dest),
162
- ...copy(config.kit.files.assets, dest)
163
- ];
160
+ return [...copy(`${config.kit.outDir}/output/client`, dest)];
164
161
  },
165
162
 
166
163
  writePrerendered(dest, { fallback } = {}) {
package/dist/cli.js CHANGED
@@ -18,7 +18,7 @@ function handle_error(e) {
18
18
  process.exit(1);
19
19
  }
20
20
 
21
- const prog = sade('svelte-kit').version('1.0.0-next.385');
21
+ const prog = sade('svelte-kit').version('1.0.0-next.388');
22
22
 
23
23
  prog
24
24
  .command('package')
package/dist/node.js CHANGED
@@ -312,42 +312,36 @@ async function setResponse(res, response) {
312
312
  return;
313
313
  }
314
314
 
315
- let cancelled = false;
315
+ const cancel = (/** @type {Error|undefined} */ error) => {
316
+ res.off('close', cancel);
317
+ res.off('error', cancel);
316
318
 
317
- res.on('close', () => {
318
- if (cancelled) return;
319
- cancelled = true;
320
- reader.cancel();
321
- res.emit('drain');
322
- });
319
+ // If the reader has already been interrupted with an error earlier,
320
+ // then it will appear here, it is useless, but it needs to be catch.
321
+ reader.cancel(error).catch(() => {});
322
+ if (error) res.destroy(error);
323
+ };
323
324
 
324
- res.on('error', (error) => {
325
- if (cancelled) return;
326
- cancelled = true;
327
- reader.cancel(error);
328
- res.emit('drain');
329
- });
325
+ res.on('close', cancel);
326
+ res.on('error', cancel);
330
327
 
331
- try {
332
- for (;;) {
333
- const { done, value } = await reader.read();
328
+ next();
329
+ async function next() {
330
+ try {
331
+ for (;;) {
332
+ const { done, value } = await reader.read();
334
333
 
335
- if (cancelled) return;
334
+ if (done) break;
336
335
 
337
- if (done) {
338
- res.end();
339
- return;
340
- }
341
-
342
- const ok = res.write(value);
343
-
344
- if (!ok) {
345
- await new Promise((fulfil) => res.once('drain', fulfil));
336
+ if (!res.write(value)) {
337
+ res.once('drain', next);
338
+ return;
339
+ }
346
340
  }
341
+ res.end();
342
+ } catch (error) {
343
+ cancel(error instanceof Error ? error : new Error(String(error)));
347
344
  }
348
- } catch (error) {
349
- cancelled = true;
350
- res.destroy(error instanceof Error ? error : undefined);
351
345
  }
352
346
  }
353
347
 
package/dist/vite.js CHANGED
@@ -284,9 +284,7 @@ const get_default_config = function ({ config, input, ssr, outDir }) {
284
284
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: JSON.stringify(config.kit.version.pollInterval),
285
285
  __SVELTEKIT_DEV__: 'false'
286
286
  },
287
- // prevent Vite copying the contents of `config.kit.files.assets`,
288
- // if it happens to be 'public' instead of 'static'
289
- publicDir: false,
287
+ publicDir: ssr ? false : config.kit.files.assets,
290
288
  resolve: {
291
289
  alias: get_aliases(config.kit)
292
290
  },
@@ -610,61 +608,6 @@ function get_methods(cwd, output, manifest_data) {
610
608
  return methods;
611
609
  }
612
610
 
613
- const absolute = /^([a-z]+:)?\/?\//;
614
- const scheme = /^[a-z]+:/;
615
-
616
- /**
617
- * @param {string} base
618
- * @param {string} path
619
- */
620
- function resolve(base, path) {
621
- if (scheme.test(path)) return path;
622
-
623
- const base_match = absolute.exec(base);
624
- const path_match = absolute.exec(path);
625
-
626
- if (!base_match) {
627
- throw new Error(`bad base path: "${base}"`);
628
- }
629
-
630
- const baseparts = path_match ? [] : base.slice(base_match[0].length).split('/');
631
- const pathparts = path_match ? path.slice(path_match[0].length).split('/') : path.split('/');
632
-
633
- baseparts.pop();
634
-
635
- for (let i = 0; i < pathparts.length; i += 1) {
636
- const part = pathparts[i];
637
- if (part === '.') continue;
638
- else if (part === '..') baseparts.pop();
639
- else baseparts.push(part);
640
- }
641
-
642
- const prefix = (path_match && path_match[0]) || (base_match && base_match[0]) || '';
643
-
644
- return `${prefix}${baseparts.join('/')}`;
645
- }
646
-
647
- /** @param {string} path */
648
- function is_root_relative(path) {
649
- return path[0] === '/' && path[1] !== '/';
650
- }
651
-
652
- /**
653
- * @param {string} path
654
- * @param {import('types').TrailingSlash} trailing_slash
655
- */
656
- function normalize_path(path, trailing_slash) {
657
- if (path === '/' || trailing_slash === 'ignore') return path;
658
-
659
- if (trailing_slash === 'never') {
660
- return path.endsWith('/') ? path.slice(0, -1) : path;
661
- } else if (trailing_slash === 'always' && !path.endsWith('/')) {
662
- return path + '/';
663
- }
664
-
665
- return path;
666
- }
667
-
668
611
  /**
669
612
  * @param {{
670
613
  * config: import('types').ValidatedConfig;
@@ -715,9 +658,7 @@ async function build_service_worker(
715
658
  ];
716
659
 
717
660
  export const prerendered = [
718
- ${prerendered.paths
719
- .map((path) => s(normalize_path(path, config.kit.trailingSlash)))
720
- .join(',\n\t\t\t\t')}
661
+ ${prerendered.paths.map((path) => s(path)).join(',\n\t\t\t\t')}
721
662
  ];
722
663
 
723
664
  export const version = ${s(config.kit.version.name)};
@@ -758,6 +699,45 @@ async function build_service_worker(
758
699
  await vite.build(merged_config);
759
700
  }
760
701
 
702
+ const absolute = /^([a-z]+:)?\/?\//;
703
+ const scheme = /^[a-z]+:/;
704
+
705
+ /**
706
+ * @param {string} base
707
+ * @param {string} path
708
+ */
709
+ function resolve(base, path) {
710
+ if (scheme.test(path)) return path;
711
+
712
+ const base_match = absolute.exec(base);
713
+ const path_match = absolute.exec(path);
714
+
715
+ if (!base_match) {
716
+ throw new Error(`bad base path: "${base}"`);
717
+ }
718
+
719
+ const baseparts = path_match ? [] : base.slice(base_match[0].length).split('/');
720
+ const pathparts = path_match ? path.slice(path_match[0].length).split('/') : path.split('/');
721
+
722
+ baseparts.pop();
723
+
724
+ for (let i = 0; i < pathparts.length; i += 1) {
725
+ const part = pathparts[i];
726
+ if (part === '.') continue;
727
+ else if (part === '..') baseparts.pop();
728
+ else baseparts.push(part);
729
+ }
730
+
731
+ const prefix = (path_match && path_match[0]) || (base_match && base_match[0]) || '';
732
+
733
+ return `${prefix}${baseparts.join('/')}`;
734
+ }
735
+
736
+ /** @param {string} path */
737
+ function is_root_relative(path) {
738
+ return path[0] === '/' && path[1] !== '/';
739
+ }
740
+
761
741
  /**
762
742
  * @typedef {{
763
743
  * fn: () => Promise<any>,
@@ -1230,7 +1210,9 @@ async function prerender({ config, entries, files, log }) {
1230
1210
 
1231
1211
  /** @type {import('types').ServerModule} */
1232
1212
  const { Server, override } = await import(pathToFileURL(`${server_root}/server/index.js`).href);
1233
- const { manifest } = await import(pathToFileURL(`${server_root}/server/manifest.js`).href);
1213
+
1214
+ /** @type {import('types').SSRManifest} */
1215
+ const manifest = (await import(pathToFileURL(`${server_root}/server/manifest.js`).href)).manifest;
1234
1216
 
1235
1217
  override({
1236
1218
  paths: config.paths,
@@ -1249,11 +1231,7 @@ async function prerender({ config, entries, files, log }) {
1249
1231
  * @param {boolean} is_html
1250
1232
  */
1251
1233
  function output_filename(path, is_html) {
1252
- const file = path.slice(config.paths.base.length + 1);
1253
-
1254
- if (file === '') {
1255
- return 'index.html';
1256
- }
1234
+ const file = path.slice(config.paths.base.length + 1) || 'index.html';
1257
1235
 
1258
1236
  if (is_html && !file.endsWith('.html')) {
1259
1237
  return file + (file.endsWith('/') ? 'index.html' : '.html');
@@ -1383,7 +1361,7 @@ async function prerender({ config, entries, files, log }) {
1383
1361
  location: resolved
1384
1362
  });
1385
1363
 
1386
- prerendered.paths.push(normalize_path(decoded, 'never'));
1364
+ prerendered.paths.push(decoded);
1387
1365
  }
1388
1366
  }
1389
1367
  } else {
@@ -1410,7 +1388,7 @@ async function prerender({ config, entries, files, log }) {
1410
1388
  });
1411
1389
  }
1412
1390
 
1413
- prerendered.paths.push(normalize_path(decoded, 'never'));
1391
+ prerendered.paths.push(decoded);
1414
1392
  } else if (response_type !== OK) {
1415
1393
  error({ status: response.status, path: decoded, referrer, referenceType });
1416
1394
  }
@@ -2278,7 +2256,7 @@ async function dev(vite, vite_config, svelte_config) {
2278
2256
  /** @type {function} */ (middleware.handle).name === 'viteServeStaticMiddleware'
2279
2257
  );
2280
2258
 
2281
- remove_html_middlewares(vite.middlewares);
2259
+ remove_static_middlewares(vite.middlewares);
2282
2260
 
2283
2261
  vite.middlewares.use(async (req, res) => {
2284
2262
  try {
@@ -2394,9 +2372,7 @@ async function dev(vite, vite_config, svelte_config) {
2394
2372
  {
2395
2373
  csp: svelte_config.kit.csp,
2396
2374
  dev: true,
2397
- get_stack: (error) => {
2398
- return fix_stack_trace(error);
2399
- },
2375
+ get_stack: (error) => fix_stack_trace(error),
2400
2376
  handle_error: (error, event) => {
2401
2377
  hooks.handleError({
2402
2378
  error: new Proxy(error, {
@@ -2467,9 +2443,8 @@ async function dev(vite, vite_config, svelte_config) {
2467
2443
  }
2468
2444
  } catch (e) {
2469
2445
  const error = coalesce_to_error(e);
2470
- vite.ssrFixStacktrace(error);
2471
2446
  res.statusCode = 500;
2472
- res.end(error.stack);
2447
+ res.end(fix_stack_trace(error));
2473
2448
  }
2474
2449
  });
2475
2450
  };
@@ -2484,11 +2459,15 @@ function not_found(res, message = 'Not found') {
2484
2459
  /**
2485
2460
  * @param {import('connect').Server} server
2486
2461
  */
2487
- function remove_html_middlewares(server) {
2488
- const html_middlewares = ['viteServeStaticMiddleware'];
2462
+ function remove_static_middlewares(server) {
2463
+ // We don't use viteServePublicMiddleware because of the following issues:
2464
+ // https://github.com/vitejs/vite/issues/9260
2465
+ // https://github.com/vitejs/vite/issues/9236
2466
+ // https://github.com/vitejs/vite/issues/9234
2467
+ const static_middlewares = ['viteServePublicMiddleware', 'viteServeStaticMiddleware'];
2489
2468
  for (let i = server.stack.length - 1; i > 0; i--) {
2490
- // @ts-expect-error using internals until https://github.com/vitejs/vite/pull/4640 is merged
2491
- if (html_middlewares.includes(server.stack[i].handle.name)) {
2469
+ // @ts-expect-error using internals
2470
+ if (static_middlewares.includes(server.stack[i].handle.name)) {
2492
2471
  server.stack.splice(i, 1);
2493
2472
  }
2494
2473
  }
@@ -2712,16 +2691,13 @@ async function preview(vite, config, protocol) {
2712
2691
  const server = new Server(manifest);
2713
2692
 
2714
2693
  return () => {
2715
- // files in `static`
2716
- vite.middlewares.use(scoped(assets, mutable(config.kit.files.assets)));
2717
-
2718
- // immutable generated client assets
2694
+ // generated client assets and the contents of `static`
2719
2695
  vite.middlewares.use(
2720
2696
  scoped(
2721
2697
  assets,
2722
2698
  sirv(join(config.kit.outDir, 'output/client'), {
2723
2699
  setHeaders: (res, pathname) => {
2724
- // only apply to build directory, not e.g. version.json
2700
+ // only apply to immutable directory, not e.g. version.json
2725
2701
  if (pathname.startsWith(`/${config.kit.appDir}/immutable`)) {
2726
2702
  res.setHeader('cache-control', 'public,max-age=31536000,immutable');
2727
2703
  }
@@ -3043,6 +3019,7 @@ function kit() {
3043
3019
  __SVELTEKIT_DEV__: 'true',
3044
3020
  __SVELTEKIT_APP_VERSION_POLL_INTERVAL__: '0'
3045
3021
  },
3022
+ publicDir: svelte_config.kit.files.assets,
3046
3023
  resolve: {
3047
3024
  alias: get_aliases(svelte_config.kit)
3048
3025
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sveltejs/kit",
3
- "version": "1.0.0-next.385",
3
+ "version": "1.0.0-next.388",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",