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 routes are broken #24

Open
meticoeus opened this issue Feb 2, 2023 · 3 comments
Open

Dynamic routes are broken #24

meticoeus opened this issue Feb 2, 2023 · 3 comments

Comments

@meticoeus
Copy link

The generated asset links on dynamic pages are relative to the current directory instead of the root, resulting in prefixing the current URL to the asset requests which do not exist.

Navigating to pages with the client side router works correctly. The only problem is when you open the page to a page that isn't prerendered or refresh the page on a page that isn't prerendered that you encounter the problem.

I've tested the normal example produced with npm create svelte@latest my-app and it correctly generates relative links to the assets.

Issue reproduction: https://github.com/meticoeus/sveltekit. See the modified example

$ cd ./examples/sveltekit-ts
$ npm i
$ npm run build
$ npm run preview
# navigate to http://localhost:4173/about/foo
# you may need to refresh the page to ensure you are loading the file from the server/service worker cache instead of the client side router.

I've made minimum modifications to the example to switch to the new auto adapter and add a dynamic route page that imports a component to show the problem.

Example generated html for route /about/[id] in .svelte-kit/output/:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" href="./favicon.svg"  type="image/svg+xml" />
		<link rel="alternate icon" href="./favicon.ico" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		<link rel="icon" href="/favicon.svg" type="image/svg+xml">
		<link rel="apple-touch-icon" href="/pwa-192x192.png">
		<link rel="mask-icon" href="/favicon.svg" color="#FFFFFF">
		<meta name="msapplication-TileColor" content="#FFFFFF">
		<meta name="theme-color" content="#ffffff">
		<meta http-equiv="content-security-policy" content="">

                <!--        ↓ Notice the './' here instead of '../'-->
		<link href="./_app/immutable/assets/_layout-7c064e52.css" rel="stylesheet">
		<link href="./_app/immutable/assets/ReloadPrompt-1dacdefd.css" rel="stylesheet">
		<link href="./_app/immutable/assets/_page-fefd3e3e.css" rel="stylesheet">
		<link href="./_app/immutable/assets/Counter-28c380d8.css" rel="stylesheet">
		<link rel="modulepreload" href="./_app/immutable/start-50acbb5f.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/index-606a435a.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/singletons-006c2a7a.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/index-6d6f5695.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/preload-helper-f8376bb0.js">
		<link rel="modulepreload" href="./_app/immutable/components/pages/_layout.svelte-607721bf.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/stores-83e7464f.js">
		<link rel="modulepreload" href="./_app/immutable/modules/pages/_layout.ts-fa3c4266.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/_layout-9a8b0c19.js">
		<link rel="modulepreload" href="./_app/immutable/components/pages/_page.svelte-6e5f7367.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/Counter-1b9396a8.js">
		<link rel="modulepreload" href="./_app/immutable/modules/pages/_page.ts-ed610ca4.js">
		<link rel="modulepreload" href="./_app/immutable/chunks/_page-de0ef88a.js"><title>Home</title><!-- HEAD_svelte-hnr6zt_START --><!-- HTML_TAG_START --><link rel="manifest" href="/manifest.webmanifest"><!-- HTML_TAG_END --><!-- HEAD_svelte-hnr6zt_END --><!-- HEAD_svelte-t32ptj_START --><meta name="description" content="Svelte demo app"><!-- HEAD_svelte-t32ptj_END -->
	</head>
	<body>
		<div>

<header class="svelte-1wxubj"><div class="corner svelte-1wxubj"><a href="https://kit.svelte.dev" class="svelte-1wxubj"><img src="/_app/immutable/assets/svelte-logo-87df40b8.svg" alt="SvelteKit" class="svelte-1wxubj"></a></div>

	<nav data-sveltekit-prefetch class="svelte-1wxubj"><svg viewBox="0 0 2 3" aria-hidden="true" class="svelte-1wxubj"><path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" class="svelte-1wxubj"></path></svg>
		<ul class="svelte-1wxubj"><li class="svelte-1wxubj active"><a href="/" class="svelte-1wxubj">Home</a></li>
			<li class="svelte-1wxubj"><a href="/about" class="svelte-1wxubj">About</a></li></ul>
		<svg viewBox="0 0 2 3" aria-hidden="true" class="svelte-1wxubj"><path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" class="svelte-1wxubj"></path></svg></nav>

	<div class="corner svelte-1wxubj">2023-02-01T23:45:27.577Z</div>
</header>

<main class="svelte-1izrdc8">

<section class="svelte-1egtvge"><h1 class="svelte-1egtvge"><span class="welcome svelte-1egtvge"><picture><source srcset="svelte-welcome.webp" type="image/webp">
				<img src="svelte-welcome.png" alt="Welcome" class="svelte-1egtvge"></picture></span>

		to your new<br>SvelteKit app
	</h1>

	<h2>try editing <strong>src/routes/+page.svelte</strong></h2>

	<div class="counter svelte-sx9eo4"><button aria-label="Decrease the counter by one" class="svelte-sx9eo4"><svg aria-hidden="true" viewBox="0 0 1 1" class="svelte-sx9eo4"><path d="M0,0.5 L1,0.5" class="svelte-sx9eo4"></path></svg></button>

	<div class="counter-viewport svelte-sx9eo4"><div class="counter-digits svelte-sx9eo4" style="transform: translate(0, 0%)"><strong class="hidden svelte-sx9eo4" aria-hidden="true">1</strong>
			<strong class="svelte-sx9eo4">0</strong></div></div>

	<button aria-label="Increase the counter by one" class="svelte-sx9eo4"><svg aria-hidden="true" viewBox="0 0 1 1" class="svelte-sx9eo4"><path d="M0,0.5 L1,0.5 M0.5,0 L0.5,1" class="svelte-sx9eo4"></path></svg></button>
</div>
</section></main>

<footer class="svelte-1izrdc8"><p>visit <a href="https://kit.svelte.dev" class="svelte-1izrdc8">kit.svelte.dev</a> to learn SvelteKit</p></footer>

		<script type="module" data-sveltekit-hydrate="kstxm9">
			import { start } from "./_app/immutable/start-50acbb5f.js";

			start({
				env: {},
				paths: {"assets":"","base":""},
				target: document.querySelector('[data-sveltekit-hydrate="kstxm9"]').parentNode,
				version: "1675295127372",
				hydrate: {
					node_ids: [0, 2],
					data: [null,null],
					form: null,
					error: null
				}
			});
		</script>
	</div>
	</body>
</html>
@meticoeus
Copy link
Author

For anyone looking for a temporary if very hacky workaround, I've added a fetch event handler in my service worker to work around this:

// service-worker.ts
// add this before workbox registerRoute(...)
self.addEventListener('fetch', (event: FetchEvent) => {
  const url = new URL(event.request.url)

  if (url.pathname.includes('/_app/') && !url.pathname.startsWith('/_app/')) {
    url.pathname = replaceBeforeSubstring(url.pathname, '/_app/')

    return event.respondWith(caches.match(url))
  }
})

@austerj
Copy link

austerj commented Sep 21, 2023

I am struggling with this exact same issue using generateSW. I tried adding the above snippet (thanks @meticoeus) to the generated service worker, but didn't seem to fix it for me unfortunately. Maybe it's necessary to switch to injectManifest?

I'm prerendering and precaching the root page and setting navigateFallback to '/' as listed in the precache manifest. Still, any redirects, manual page refreshes or errors thrown in page load functions leads to the service worker looking for ./_app/... in the current route instead of the root. For me this happens not only with dynamic routes, but ALL non-prerendered routes that are not at the root.

I tried to add dynamic routes to navigateFallbackDenylist, which at least leads to page refreshes and SvelteKit error pages working like normal when online, but still does not work offline (and leads to a server request that shouldn't be necessary, as all it does is return an HTML shell with the corrected path to _app).

Did anyone find a stable solution to this? Or is the better bet to just prerender and handle everything dynamic in regular Svelte components?

@austerj
Copy link

austerj commented Sep 22, 2023

Found the answer! The issue seems entirely related to the SvelteKit build process and not the service worker / PWA plugin.

Setting this

const config = {
    kit: {
        ...
        paths: {
            relative: false,
        },
        ...
    },
}

in svelte.config.js has completely resolved it for me and now the service worker behavior matches the regular SvelteKit behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants