sveltejs / kit

web development, streamlined
https://kit.svelte.dev
MIT License
18.61k stars 1.92k forks source link

adapter-static: Allow root index.html to be served for dynamic paths #12769

Open powellnorma opened 1 week ago

powellnorma commented 1 week ago

Describe the problem

Let's say I have item/[id]/+page.svelte, which just contains:

<script lang="ts">
  import { page } from '$app/stores';

  $: itemId = $page.params.id;
</script>

<svelte:head>
  <title>Item {itemId}</title>
</svelte:head>

<h1>Item {itemId}</h1>
<p>This is the details page for item {itemId}.</p>

<a href="/">Back to Home</a>

Now I don't know all the itemIds in advance (and it also could be millions of different ones).

What works: Klicking on a link like <a href="./item/{Math.floor(Math.random() * 100) + 1}">Random Item</a> from the root page.

What doesn't work: Navigating to /item/123 directly - As there isn't a prerendered .html for this.

I tried serving index.html in that case, but it fails, since

  1. Relative paths are used:
    Promise.all([
    import("./_app/immutable/entry/start.DsajyGCw.js"),
    import("./_app/immutable/entry/app.CUpY7-FC.js")
    ]).then(([kit, app]) => {
    kit.start(app, element);
    });
  2. Even after fixing that path on the backend (to /_app/..), it now just gives a 404 page, the console says:
    Error: Not found: /ui/item/6

In Routify this works without problems, it doesn't prerender individual pages, but expects you to always just serve the root index.html

Describe the proposed solution

Adjust the generated index.html file such that it can be served for any path.

Alternatives considered

On the backend, I currently rewrite the URL to /?jump-to-path=<somePath>, and in +layout.svelte I do:

onMount(() => {
  const jumpToPath = $page.url.searchParams.get('jump-to-path');
  if (jumpToPath) {
    // Remove the 'jump-to-path' parameter from the URL
    const newUrl = new URL($page.url);
    newUrl.searchParams.delete('jump-to-path');
    history.replaceState(null, '', newUrl);

    // Navigate to the specified path
    goto(jumpToPath, { replaceState: true });
  }
});

This works, but it flickers and requires extra code.

Importance

would make my life easier

Additional Information

In a real app, item/[id]/+page.svelte might fetch data dynamically via XHR. Implementing the proposed feature would make it easier to use svelte-kit without Node (e.g. when the backend is written in golang).

eltigerchino commented 5 days ago

If you want a dynamic route using the static adapter, you'll have to opt into SPA-mode (fetching the data when the page is mounted). You can do this by turning off prerendering for the dynamic route and specifying a fallback page option. https://kit.svelte.dev/docs/single-page-apps#usage

Does that fit your use case?