Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/easy-weeks-tan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': major
---

breaking: remove `base`, `assets`, and `resolveRoute` from `$app/paths`
3 changes: 3 additions & 0 deletions documentation/docs/98-reference/20-$app-paths.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ title: $app/paths
---

> MODULE: $app/paths

> [!LEGACY]
> `base`, `assets`, and `resolveRoute` were removed in 3.0
2 changes: 1 addition & 1 deletion packages/kit/src/core/postbuild/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ async function prerender({ hash, out, manifest_path, metadata, verbose, env, roo
({ status, path, referrer, referenceType }) => {
const message =
status === 404 && !path.startsWith(config.paths.base)
? `${path} does not begin with \`base\`, which is configured in \`paths.base\` and can be imported from \`$app/paths\` - see https://svelte.dev/docs/kit/configuration#paths for more info`
? `${path} does not begin with \`base\`. You can fix this by using \`resolve('${path}')\` from \`$app/paths\`. The base path is configurable from \`paths.base\` - see https://svelte.dev/docs/kit/configuration#paths for more info`
: path;

return `${status} ${message}${referrer ? ` (${referenceType} from ${referrer})` : ''}`;
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/src/exports/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -671,14 +671,14 @@ export interface KitConfig {
*/
assets?: '' | `http://${string}` | `https://${string}`;
/**
* 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`](https://svelte.dev/docs/kit/$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.
* 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 [`resolve(...)` from `$app/paths`](https://svelte.dev/docs/kit/$app-paths#resolve) for that: `<a href="{resolve('/your-page')}">Link</a>`. If you find yourself writing this often, it may make sense to extract this into a reusable component.
* @default ""
*/
base?: '' | `/${string}`;
/**
* Whether to use relative asset paths.
*
* If `true`, `base` and `assets` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in more portable HTML.
* If `true`, paths created with `resolve()` and `asset()` imported from `$app/paths` will be replaced with relative asset paths during server-side rendering, resulting in more portable HTML.
* If `false`, `%sveltekit.assets%` and references to build artifacts will always be root-relative paths, unless `paths.assets` is an external URL
*
* [Single-page app](https://svelte.dev/docs/kit/single-page-apps) fallback pages will always use absolute paths, regardless of this setting.
Expand Down
2 changes: 0 additions & 2 deletions packages/kit/src/runtime/app/paths/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,3 @@ export async function match(url) {

return null;
}

export { base, assets, resolve as resolveRoute };
28 changes: 0 additions & 28 deletions packages/kit/src/runtime/app/paths/public.d.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1 @@
import { RouteIdWithSearchOrHash, PathnameWithSearchOrHash, ResolvedPathname } from '$app/types';
import { ResolveArgs } from './types.js';

export { resolve, asset, match } from './client.js';

/**
* A string that matches [`config.kit.paths.base`](https://svelte.dev/docs/kit/configuration#paths).
*
* Example usage: `<a href="{base}/your-page">Link</a>`
*
* @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead
*/
export let base: '' | `/${string}`;

/**
* An absolute path that matches [`config.kit.paths.assets`](https://svelte.dev/docs/kit/configuration#paths).
*
* > [!NOTE] If a value for `config.kit.paths.assets` is specified, it will be replaced with `'/_svelte_kit_assets'` during `vite dev` or `vite preview`, since the assets don't yet live at their eventual URL.
*
* @deprecated Use [`asset(...)`](https://svelte.dev/docs/kit/$app-paths#asset) instead
*/
export let assets: '' | `https://${string}` | `http://${string}` | '/_svelte_kit_assets';

/**
* @deprecated Use [`resolve(...)`](https://svelte.dev/docs/kit/$app-paths#resolve) instead
*/
export function resolveRoute<T extends RouteIdWithSearchOrHash | PathnameWithSearchOrHash>(
...args: ResolveArgs<T>
): ResolvedPathname;
2 changes: 0 additions & 2 deletions packages/kit/src/runtime/app/paths/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,3 @@ export async function match(url) {

return null;
}

export { base, assets, resolve as resolveRoute };
2 changes: 1 addition & 1 deletion packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
create_updated_store,
load_css
} from './utils.js';
import { base } from '$app/paths';
import { base } from '$app/paths/internal/client';
import * as devalue from 'devalue';
import {
HISTORY_INDEX,
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/runtime/client/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BROWSER, DEV } from 'esm-env';
import { writable } from 'svelte/store';
import { assets } from '$app/paths';
import { assets } from '$app/paths/internal/client';
import { version } from '__sveltekit/environment';
import { PRELOAD_PRIORITIES } from './constants.js';

Expand Down
5 changes: 0 additions & 5 deletions packages/kit/test/apps/basics/src/routes/paths/+page.svelte

This file was deleted.

This file was deleted.

20 changes: 0 additions & 20 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -730,33 +730,13 @@
});

test.describe('$app/paths', () => {
test('includes paths', async ({ page, javaScriptEnabled }) => {
test.skip(
process.env.SVELTE_ASYNC === 'true',
'does not work with async, should use new functions instead'
);
await page.goto('/paths');

let base = javaScriptEnabled ? '' : '.';
expect(await page.innerHTML('pre')).toBe(JSON.stringify({ base, assets: base }));

await page.goto('/paths/deeply/nested');

base = javaScriptEnabled ? '' : '../..';
expect(await page.innerHTML('pre')).toBe(JSON.stringify({ base, assets: base }));
});

// some browsers will re-request assets after a `pushState`
// https://github.com/sveltejs/kit/issues/3748#issuecomment-1125980897
test('replaces %sveltekit.assets% in template with relative path, and makes it absolute in the client', async ({
baseURL,
page,
javaScriptEnabled
}) => {
test.skip(
process.env.SVELTE_ASYNC === 'true',
'does not work with async, should use new functions instead'
);
const absolute = `${baseURL}/favicon.png`;

await page.goto('/');
Expand Down Expand Up @@ -1119,7 +1099,7 @@
});

test.describe('Actions', () => {
test("invalidateAll = false doesn't invalidate all", async ({ page, javaScriptEnabled }) => {

Check warning on line 1102 in packages/kit/test/apps/basics/test/test.js

View workflow job for this annotation

GitHub Actions / test-kit (22, ubuntu-latest, chromium, current)

flaky test: invalidateAll = false doesn't invalidate all

retries: 2
await page.goto('/actions/invalidate-all?invalidate_all=false');
const preSubmitContent = await page.locator('pre').textContent();
await page.click('button');
Expand Down Expand Up @@ -1256,7 +1236,7 @@
}
});

test('applyAction errors', async ({ page, javaScriptEnabled }) => {

Check warning on line 1239 in packages/kit/test/apps/basics/test/test.js

View workflow job for this annotation

GitHub Actions / test-kit (22, ubuntu-latest, chromium, current)

flaky test: applyAction errors

retries: 2
await page.goto('/actions/update-form');
expect(await page.textContent('pre')).toBe(JSON.stringify(null));

Expand Down Expand Up @@ -1424,7 +1404,7 @@
expect(page.url()).toContain('/actions/enhance');
});

test('redirect in handle', async ({ page, javaScriptEnabled }) => {

Check warning on line 1407 in packages/kit/test/apps/basics/test/test.js

View workflow job for this annotation

GitHub Actions / test-kit (22, ubuntu-latest, chromium, current)

flaky test: redirect in handle

retries: 2
await page.goto('/actions/redirect-in-handle');

page.click('button');
Expand Down
8 changes: 4 additions & 4 deletions packages/kit/test/apps/options-2/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script>
import { base, assets } from '$app/paths';
import { asset, resolve } from '$app/paths';
</script>

<h1>Hello</h1>

<p data-testid="base">base: {base}</p>
<p data-testid="assets">assets: {assets}</p>
<p data-testid="base">base: {resolve('/')}</p>
<p data-testid="assets">assets: {asset('')}</p>

<a href="{base}/hello" data-testid="link">Go to /hello</a>
<a href={resolve('/hello')} data-testid="link">Go to /hello</a>

<style>
a {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<script>
import { base, assets } from '$app/paths';
import { resolve, asset } from '$app/paths';
</script>

<h1>Hello</h1>

<p data-testid="base">base: {base}</p>
<p data-testid="assets">assets: {assets}</p>
<p data-testid="base">base: {resolve('/')}</p>
<p data-testid="assets">assets: {asset('')}</p>

<style>
p {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<script>
import { base } from '$app/paths';
import { resolve } from '$app/paths';
</script>

<a href="{base}/trailing-slash-server/prerender">{base}/trailing-slash-server/prerender</a>
<a href={resolve('/trailing-slash-server/prerender')}
>{resolve('/trailing-slash-server/prerender')}</a
>
10 changes: 6 additions & 4 deletions packages/kit/test/apps/options-2/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ test.describe('paths', () => {
test('uses relative paths during SSR', async ({ page, javaScriptEnabled }) => {
await page.goto('/basepath');

let base = javaScriptEnabled ? '/basepath' : '.';
let base = javaScriptEnabled ? '/basepath/' : './';
let assets = javaScriptEnabled ? '/basepath' : '.';
expect(await page.textContent('[data-testid="base"]')).toBe(`base: ${base}`);
expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${base}`);
expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${assets}`);

await page.goto('/basepath/deeply/nested/page');

base = javaScriptEnabled ? '/basepath' : '../..';
base = javaScriptEnabled ? '/basepath/' : '../../';
assets = javaScriptEnabled ? '/basepath' : '../..';
expect(await page.textContent('[data-testid="base"]')).toBe(`base: ${base}`);
expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${base}`);
expect(await page.textContent('[data-testid="assets"]')).toBe(`assets: ${assets}`);
});

test('serves /basepath with trailing slash always', async ({ page }) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/kit/test/apps/options/source/pages/base/+page.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { base, assets } from '$app/paths';
import { resolve, asset } from '$app/paths';

/** @type {import('@sveltejs/kit').Load} */
export async function load() {
return {
paths: {
base,
assets
base: resolve('/'),
assets: asset('')
}
};
}
7 changes: 4 additions & 3 deletions packages/kit/test/apps/options/source/pages/match/+server.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { json } from '@sveltejs/kit';
import { match } from '$app/paths';

/** @satisfies {import('$app/types').ResolvedPathname[]} */
const test_paths = [
'/path-base/resolve-route',
'/path-base/resolve-route/resolved',
'/path-base/not-a-real-route-that-exists'
'/path-base/base/',
'/path-base/base/resolved/',
'/path-base/not-a-real-route-that-exists/'
];

export async function GET() {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script>
import { base } from '$app/paths';
import { resolve } from '$app/paths';
import { page } from '$app/state';
</script>

<h2>{page.url.pathname}</h2>

<a data-testid="child" href="{base}/slash/child">/slash/child</a>
<a data-testid="child" href={resolve('/slash/child')}>/slash/child</a>
13 changes: 4 additions & 9 deletions packages/kit/test/apps/options/test/paths-assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@ test.describe('base path', () => {
expect(await response.text()).toBe('hello there world\n');
});

test('paths available on server side', async ({ page }) => {
test('paths available on server side', async ({ page, javaScriptEnabled }) => {
await page.goto('/path-base/base/');
expect(await page.textContent('[data-source="base"]')).toBe('/path-base');
expect(await page.textContent('[data-source="base"]')).toBe(
javaScriptEnabled ? '/path-base/' : '../'
);
expect(await page.textContent('[data-source="assets"]')).toBe('/_svelte_kit_assets');
});

Expand Down Expand Up @@ -72,13 +74,6 @@ test.describe('base path', () => {
expect(await page.textContent('h2')).toBe('two');
});

test('resolveRoute accounts for base path', async ({ baseURL, page, clicknav }) => {
await page.goto('/path-base/resolve-route');
await clicknav('[data-id=target]');
expect(page.url()).toBe(`${baseURL}/path-base/resolve-route/resolved/`);
expect(await page.textContent('h2')).toBe('resolved');
});

test('server load fetch without base path does not invoke the server', async ({
page,
baseURL
Expand Down
27 changes: 15 additions & 12 deletions packages/kit/test/apps/options/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ test.describe('trailingSlash', () => {
page,
javaScriptEnabled
}) => {
if (!javaScriptEnabled) return;
test.skip(!javaScriptEnabled, 'data-sveltekit-* only works with JavaScript');

await page.goto('/path-base/preloading');

Expand Down Expand Up @@ -238,17 +238,20 @@ test.describe('$app/paths', () => {
test('match() works with base paths', async ({ request }) => {
const response = await request.get('/path-base/match');

expect(await response.json()).toEqual([
{
path: '/path-base/resolve-route',
result: { id: '/resolve-route', params: {} }
},
{
path: '/path-base/resolve-route/resolved',
result: { id: '/resolve-route/[foo]', params: { foo: 'resolved' } }
},
{ path: '/path-base/not-a-real-route-that-exists', result: null }
]);
expect(await response.json()).toEqual(
/** @satisfies {({ path: import('$app/types').ResolvedPathname ; result: { id: import('$app/types').RouteId; params: Record<string, string> }})[]} */
([
{
path: '/path-base/base/',
result: { id: '/base', params: {} }
},
{
path: '/path-base/base/resolved/',
result: { id: '/base/[slug]', params: { slug: 'resolved' } }
},
{ path: '/path-base/not-a-real-route-that-exists/', result: null }
])
);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { redirect } from '@sveltejs/kit';
import { base } from '$app/paths';
import { resolve } from '$app/paths';

export function load() {
redirect(301, `${base}/dynamic/foo`);
redirect(301, resolve('/dynamic/foo'));
}
Loading
Loading