@sveltejs/kit 1.8.8 → 1.9.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": "1.8.8",
3
+ "version": "1.9.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sveltejs/kit",
@@ -171,6 +171,13 @@ const options = object(
171
171
  }
172
172
  }
173
173
 
174
+ return input;
175
+ }),
176
+ relative: validate(undefined, (input, keypath) => {
177
+ if (typeof input !== 'boolean') {
178
+ throw new Error(`${keypath} option must be a boolean or undefined`);
179
+ }
180
+
174
181
  return input;
175
182
  })
176
183
  }),
@@ -27,7 +27,8 @@ const server_template = ({
27
27
  }) => `
28
28
  import root from '../root.svelte';
29
29
  import { set_building } from '__sveltekit/environment';
30
- import { set_assets, set_private_env, set_public_env } from '${runtime_directory}/shared-server.js';
30
+ import { set_assets } from '__sveltekit/paths';
31
+ import { set_private_env, set_public_env } from '${runtime_directory}/shared-server.js';
31
32
 
32
33
  export const options = {
33
34
  app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
@@ -451,15 +451,14 @@ export async function dev(vite, vite_config, svelte_config) {
451
451
  await vite.ssrLoadModule(`${runtime_base}/server/index.js`)
452
452
  );
453
453
 
454
- const { set_assets, set_fix_stack_trace } =
455
- /** @type {import('types').ServerInternalModule} */ (
456
- await vite.ssrLoadModule(`${runtime_base}/shared-server.js`)
457
- );
454
+ const { set_fix_stack_trace } = await vite.ssrLoadModule(
455
+ `${runtime_base}/shared-server.js`
456
+ );
457
+ set_fix_stack_trace(fix_stack_trace);
458
458
 
459
+ const { set_assets } = await vite.ssrLoadModule('__sveltekit/paths');
459
460
  set_assets(assets);
460
461
 
461
- set_fix_stack_trace(fix_stack_trace);
462
-
463
462
  const server = new Server(manifest);
464
463
 
465
464
  await server.init({ env });
@@ -379,17 +379,34 @@ function kit({ svelte_config }) {
379
379
  case '\0__sveltekit/paths':
380
380
  const { assets, base } = svelte_config.kit.paths;
381
381
 
382
+ // use the values defined in `global`, but fall back to hard-coded values
383
+ // for the sake of things like Vitest which may import this module
384
+ // outside the context of a page
382
385
  if (browser) {
383
- return `export const base = ${s(base)};
384
- export const assets = ${global}.assets;`;
386
+ return `export const base = ${global}?.base ?? ${s(base)};
387
+ export const assets = ${global}?.assets ?? ${assets ? s(assets) : 'base'};`;
385
388
  }
386
389
 
387
- return `export const base = ${s(base)};
390
+ return `export let base = ${s(base)};
388
391
  export let assets = ${assets ? s(assets) : 'base'};
389
392
 
393
+ export const relative = ${svelte_config.kit.paths.relative};
394
+
395
+ const initial = { base, assets };
396
+
397
+ export function override(paths) {
398
+ base = paths.base;
399
+ assets = paths.assets;
400
+ }
401
+
402
+ export function reset() {
403
+ base = initial.base;
404
+ assets = initial.assets;
405
+ }
406
+
390
407
  /** @param {string} path */
391
408
  export function set_assets(path) {
392
- assets = path;
409
+ assets = initial.assets = path;
393
410
  }`;
394
411
 
395
412
  case '\0__sveltekit/environment':
package/src/internal.d.ts CHANGED
@@ -7,7 +7,10 @@ declare module '__sveltekit/environment' {
7
7
 
8
8
  /** Internal version of $app/paths */
9
9
  declare module '__sveltekit/paths' {
10
- export const base: `/${string}`;
11
- export let assets: `https://${string}` | `http://${string}`;
10
+ export let base: '' | `/${string}`;
11
+ export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets';
12
+ export let relative: boolean | undefined; // TODO in 2.0, make this a `boolean` that defaults to `true`
13
+ export function reset(): void;
14
+ export function override(paths: { base: string; assets: string }): void;
12
15
  export function set_assets(path: string): void;
13
16
  }
@@ -66,7 +66,8 @@ function get_store(name) {
66
66
  return getStores()[name];
67
67
  } catch (e) {
68
68
  throw new Error(
69
- `Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.`
69
+ `Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.` +
70
+ 'For more information, see https://kit.svelte.dev/docs/state-management#avoid-shared-state-on-the-server'
70
71
  );
71
72
  }
72
73
  }
@@ -1,7 +1,7 @@
1
1
  import * as devalue from 'devalue';
2
2
  import { readable, writable } from 'svelte/store';
3
3
  import { DEV } from 'esm-env';
4
- import { assets, base } from '__sveltekit/paths';
4
+ import * as paths from '__sveltekit/paths';
5
5
  import { hash } from '../../hash.js';
6
6
  import { serialize_data } from './serialize_data.js';
7
7
  import { s } from '../../../utils/misc.js';
@@ -11,6 +11,7 @@ import { clarify_devalue_error, stringify_uses, handle_error_and_jsonify } from
11
11
  import { public_env } from '../../shared-server.js';
12
12
  import { text } from '../../../exports/index.js';
13
13
  import { create_async_iterator } from '../../../utils/streaming.js';
14
+ import { SVELTE_KIT_ASSETS } from '../../../constants.js';
14
15
 
15
16
  // TODO rename this function/module
16
17
 
@@ -80,6 +81,43 @@ export async function render_response({
80
81
  ? action_result.data ?? null
81
82
  : null;
82
83
 
84
+ /** @type {string} */
85
+ let base = paths.base;
86
+
87
+ /** @type {string} */
88
+ let assets = paths.assets;
89
+
90
+ /**
91
+ * An expression that will evaluate in the client to determine the resolved base path.
92
+ * We use a relative path when possible to support IPFS, the internet archive, etc.
93
+ */
94
+ let base_expression = s(paths.base);
95
+
96
+ // if appropriate, use relative paths for greater portability
97
+ if (paths.relative !== false && !state.prerendering?.fallback) {
98
+ const segments = event.url.pathname.slice(paths.base.length).split('/');
99
+
100
+ if (segments.length === 1 && paths.base !== '') {
101
+ // if we're on `/my-base-path`, relative links need to start `./my-base-path` rather than `.`
102
+ base = `./${paths.base.split('/').at(-1)}`;
103
+
104
+ base_expression = `new URL(${s(base)}, location).pathname`;
105
+ } else {
106
+ base =
107
+ segments
108
+ .slice(2)
109
+ .map(() => '..')
110
+ .join('/') || '.';
111
+
112
+ // resolve e.g. '../..' against current location, then remove trailing slash
113
+ base_expression = `new URL(${s(base)}, location).pathname.slice(0, -1)`;
114
+ }
115
+
116
+ if (!paths.assets || (paths.assets[0] === '/' && paths.assets !== SVELTE_KIT_ASSETS)) {
117
+ assets = base;
118
+ }
119
+ }
120
+
83
121
  if (page_config.ssr) {
84
122
  if (__SVELTEKIT_DEV__ && !branch.at(-1)?.node.component) {
85
123
  // Can only be the leaf, layouts have a fallback component generated
@@ -116,6 +154,10 @@ export async function render_response({
116
154
  form: form_value
117
155
  };
118
156
 
157
+ // use relative paths during rendering, so that the resulting HTML is as
158
+ // portable as possible, but reset afterwards
159
+ if (paths.relative) paths.override({ base, assets });
160
+
119
161
  if (__SVELTEKIT_DEV__) {
120
162
  const fetch = globalThis.fetch;
121
163
  let warned = false;
@@ -138,9 +180,14 @@ export async function render_response({
138
180
  rendered = options.root.render(props);
139
181
  } finally {
140
182
  globalThis.fetch = fetch;
183
+ paths.reset();
141
184
  }
142
185
  } else {
143
- rendered = options.root.render(props);
186
+ try {
187
+ rendered = options.root.render(props);
188
+ } finally {
189
+ paths.reset();
190
+ }
144
191
  }
145
192
 
146
193
  for (const { node } of branch) {
@@ -156,35 +203,6 @@ export async function render_response({
156
203
  rendered = { head: '', html: '', css: { code: '', map: null } };
157
204
  }
158
205
 
159
- /**
160
- * The prefix to use for static assets. Replaces `%sveltekit.assets%` in the template
161
- * @type {string}
162
- */
163
- let resolved_assets;
164
-
165
- /**
166
- * An expression that will evaluate in the client to determine the resolved asset path
167
- */
168
- let asset_expression;
169
-
170
- if (assets) {
171
- // if an asset path is specified, use it
172
- resolved_assets = assets;
173
- asset_expression = s(assets);
174
- } else if (state.prerendering?.fallback) {
175
- // if we're creating a fallback page, asset paths need to be root-relative
176
- resolved_assets = base;
177
- asset_expression = s(base);
178
- } else {
179
- // otherwise we want asset paths to be relative to the page, so that they
180
- // will work in odd contexts like IPFS, the internet archive, and so on
181
- const segments = event.url.pathname.slice(base.length).split('/').slice(2);
182
- resolved_assets = segments.length > 0 ? segments.map(() => '..').join('/') : '.';
183
- asset_expression = `new URL(${s(
184
- resolved_assets
185
- )}, location.href).pathname.replace(/^\\\/$/, '')`;
186
- }
187
-
188
206
  let head = '';
189
207
  let body = rendered.html;
190
208
 
@@ -198,9 +216,9 @@ export async function render_response({
198
216
  // Vite makes the start script available through the base path and without it.
199
217
  // We load it via the base path in order to support remote IDE environments which proxy
200
218
  // all URLs under the base path during development.
201
- return base + path;
219
+ return paths.base + path;
202
220
  }
203
- return `${resolved_assets}/${path}`;
221
+ return `${assets}/${path}`;
204
222
  };
205
223
 
206
224
  if (inline_styles.size > 0) {
@@ -286,9 +304,10 @@ export async function render_response({
286
304
 
287
305
  const properties = [
288
306
  `env: ${s(public_env)}`,
289
- `assets: ${asset_expression}`,
307
+ paths.assets && `assets: ${s(paths.assets)}`,
308
+ `base: ${base_expression}`,
290
309
  `element: document.currentScript.parentElement`
291
- ];
310
+ ].filter(Boolean);
292
311
 
293
312
  if (chunks) {
294
313
  blocks.push(`const deferred = new Map();`);
@@ -419,7 +438,7 @@ export async function render_response({
419
438
  const html = options.templates.app({
420
439
  head,
421
440
  body,
422
- assets: resolved_assets,
441
+ assets,
423
442
  nonce: /** @type {string} */ (csp.nonce),
424
443
  env: public_env
425
444
  });
@@ -1,5 +1,3 @@
1
- export { set_assets } from '__sveltekit/paths';
2
-
3
1
  /** @type {Record<string, string>} */
4
2
  export let private_env = {};
5
3
 
@@ -195,7 +195,7 @@ declare module '$app/navigation' {
195
195
  */
196
196
  state?: any;
197
197
  /**
198
- * If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#invalidation for more info on invalidation.
198
+ * If `true`, all `load` functions of the page will be rerun. See https://kit.svelte.dev/docs/load#rerunning-load-functions for more info on invalidation.
199
199
  */
200
200
  invalidateAll?: boolean;
201
201
  }
package/types/index.d.ts CHANGED
@@ -441,12 +441,20 @@ export interface KitConfig {
441
441
  * An absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kind.
442
442
  * @default ""
443
443
  */
444
- assets?: string;
444
+ assets?: '' | `http://${string}` | `https://${string}`;
445
445
  /**
446
446
  * A root-relative path that must start, but not end with `/` (e.g. `/base-path`), unless it is the empty string. This specifies where your app is served from and allows the app to live on a non-root path. Note that you need to prepend all your root-relative links with the base value or they will point to the root of your domain, not your `base` (this is how the browser works). You can use [`base` from `$app/paths`](/docs/modules#$app-paths-base) for that: `<a href="{base}/your-page">Link</a>`. If you find yourself writing this often, it may make sense to extract this into a reusable component.
447
447
  * @default ""
448
448
  */
449
- base?: string;
449
+ base?: '' | `/${string}`;
450
+ /**
451
+ * Whether to use relative asset paths. By default, if `paths.assets` is not external, SvelteKit will replace `%sveltekit.assets%` with a relative path and use relative paths to reference build artifacts, but `base` and `assets` imported from `$app/paths` will be as specified in your config.
452
+ *
453
+ * If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in portable HTML.
454
+ * If `false`, `%sveltekit.assets%` and references to build artifacts will always be root-relative paths, unless `paths.assets` is an external URL
455
+ * @default undefined
456
+ */
457
+ relative?: boolean | undefined;
450
458
  };
451
459
  /**
452
460
  * See [Prerendering](https://kit.svelte.dev/docs/page-options#prerender).