Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dynamic base #9150

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rude-cameras-compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': minor
---

feat: use relative `base` path in client
2 changes: 1 addition & 1 deletion packages/adapter-static/test/test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import fs from 'fs';
import fs from 'node:fs';
import * as assert from 'uvu/assert';
import { run } from './utils.js';

Expand Down
7 changes: 5 additions & 2 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,12 @@ function kit({ svelte_config }) {
case '\0__sveltekit/paths':
const { assets, base } = svelte_config.kit.paths;

// use the values defined in `global`, but fall back to hard-coded values
// for the sake of things like Vitest which may import this module
// outside the context of a page
if (browser) {
return `export const base = ${s(base)};
export const assets = ${global}.assets;`;
return `export const base = ${global}?.base ?? ${s(base)};
export const assets = ${global}?.assets ?? ${assets ? s(assets) : 'base'};`;
}

return `export const base = ${s(base)};
Expand Down
2 changes: 1 addition & 1 deletion packages/kit/src/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ declare module '__sveltekit/environment' {

/** Internal version of $app/paths */
declare module '__sveltekit/paths' {
export const base: `/${string}`;
export const base: string;
export let assets: `https://${string}` | `http://${string}`;
export function set_assets(path: string): void;
}
56 changes: 27 additions & 29 deletions packages/kit/src/runtime/server/page/render.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as devalue from 'devalue';
import { readable, writable } from 'svelte/store';
import { DEV } from 'esm-env';
import { assets, base } from '__sveltekit/paths';
import * as paths from '__sveltekit/paths';
import { hash } from '../../hash.js';
import { serialize_data } from './serialize_data.js';
import { s } from '../../../utils/misc.js';
Expand Down Expand Up @@ -156,34 +156,31 @@ export async function render_response({
rendered = { head: '', html: '', css: { code: '', map: null } };
}

const segments = event.url.pathname.slice(paths.base.length).split('/').slice(2);
const base = segments.map(() => '..').join('/') || '.';

/**
* The prefix to use for static assets. Replaces `%sveltekit.assets%` in the template
* @type {string}
* An expression that will evaluate in the client to determine the resolved base path.
* We use a relative path when possible to support IPFS, the internet archive, etc.
*/
let resolved_assets;
const base_expression =
state.prerendering?.fallback || paths.base !== ''
? s(paths.base)
: `new URL(${s(base)}, location.href).pathname.slice(0,-1)`;

/**
* An expression that will evaluate in the client to determine the resolved asset path
* An expression that will evaluate in the client to determine the resolved asset path.
* If `undefined`, falls back to `base`
*/
let asset_expression;

if (assets) {
// if an asset path is specified, use it
resolved_assets = assets;
asset_expression = s(assets);
} else if (state.prerendering?.fallback) {
// if we're creating a fallback page, asset paths need to be root-relative
resolved_assets = base;
asset_expression = s(base);
} else {
// otherwise we want asset paths to be relative to the page, so that they
// will work in odd contexts like IPFS, the internet archive, and so on
const segments = event.url.pathname.slice(base.length).split('/').slice(2);
resolved_assets = segments.length > 0 ? segments.map(() => '..').join('/') : '.';
asset_expression = `new URL(${s(
resolved_assets
)}, location.href).pathname.replace(/^\\\/$/, '')`;
}
const asset_expression = paths.assets ? s(paths.assets) : undefined;

/**
* The prefix to use for static assets. Replaces `%sveltekit.assets%` in the template.
* If an asset path is specified, use it. If we're creating a fallback page, asset paths
* need to be root-relative. Otherwise, use the base path relative to the current page.
* @type {string}
*/
const assets = paths.assets || (state.prerendering?.fallback ? paths.base : base);

let head = '';
let body = rendered.html;
Expand All @@ -198,9 +195,9 @@ export async function render_response({
// Vite makes the start script available through the base path and without it.
// We load it via the base path in order to support remote IDE environments which proxy
// all URLs under the base path during development.
return base + path;
return paths.base + path;
}
return `${resolved_assets}/${path}`;
return `${assets}/${path}`;
};

if (inline_styles.size > 0) {
Expand Down Expand Up @@ -285,9 +282,10 @@ export async function render_response({

const properties = [
`env: ${s(public_env)}`,
`assets: ${asset_expression}`,
asset_expression && `assets: ${asset_expression}`,
`base: ${base_expression}`,
`element: document.currentScript.parentElement`
];
].filter(Boolean);

if (chunks) {
blocks.push(`const deferred = new Map();`);
Expand Down Expand Up @@ -418,7 +416,7 @@ export async function render_response({
const html = options.templates.app({
head,
body,
assets: resolved_assets,
assets,
nonce: /** @type {string} */ (csp.nonce),
env: public_env
});
Expand Down