Repository: sveltejs/kit (js)

Issue:
Service worker reference is absolute, should be relative
### Describe the bug

The service worker reference in `build/index.html` is `/service-worker.js`, i.e. still absolute, while the other references are (finally :partying_face:) relative.

### Reproduction

https://github.com/bassjoe/pwa3
- created sveltekit app
- changed from `auto` adapter to `static` adapter, creating `src/routes/+layout.js`
- created `src/service-worker.js`

To reproduce:
- run `npm install` and `npm run build`
- see `build/index.html`
 
The resulting `index.html` looks like this: https://github.com/bassjoe/pwa3/blob/gh-pages/index.html
And the service worker obviously can't be loaded: https://bassjoe.github.io/pwa3/

### Logs

_No response_

### System Info

```shell
System:
    OS: Linux 5.19 Fedora Linux 36 (Workstation Edition)
    CPU: (4) x64 Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz
    Memory: 11.72 GB / 15.51 GB
    Container: Yes
    Shell: 3.5.0 - /usr/bin/fish
  Binaries:
    Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node
    npm: 8.15.0 - ~/.nvm/versions/node/v16.17.0/bin/npm
  Browsers:
    Firefox: 104.0.1
  npmPackages:
    @sveltejs/adapter-static: next => 1.0.0-next.41 
    @sveltejs/kit: next => 1.0.0-next.468 
    svelte: ^3.44.0 => 3.50.0 
    vite: ^3.1.0-beta.1 => 3.1.0-beta.2
```


### Severity

serious, but I can work around it

### Additional Information

This is similar to https://github.com/sveltejs/kit/issues/3290

Pull request description:
register service worker with relative URL
fixes #6561. While I was at it I tidied some stuff up — only creating scripts if they're needed, for example, and making the indentation less wacky in the rendered HTML

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [x] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/cuddly-dragons-punch.md b/.changeset/cuddly-dragons-punch.md
new file mode 100644
index 000000000..1491e81fb
--- /dev/null
+++ b/.changeset/cuddly-dragons-punch.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Fix fetch type
diff --git a/.changeset/orange-cups-itch.md b/.changeset/orange-cups-itch.md
new file mode 100644
index 000000000..7a0b57312
--- /dev/null
+++ b/.changeset/orange-cups-itch.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Register service worker with relative URL
diff --git a/.changeset/pre.json b/.changeset/pre.json
index 7a028dc0f..e547b7ca1 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -764,6 +764,7 @@
     "olive-socks-thank",
     "olive-vans-talk",
     "orange-boats-love",
+    "orange-rocks-return",
     "orange-ties-tell",
     "orange-wolves-fly",
     "perfect-cycles-smell",
diff --git a/packages/adapter-auto/CHANGELOG.md b/packages/adapter-auto/CHANGELOG.md
index 4e266dc97..ca546206b 100644
--- a/packages/adapter-auto/CHANGELOG.md
+++ b/packages/adapter-auto/CHANGELOG.md
@@ -1,5 +1,12 @@
 # @sveltejs/adapter-auto
 
+## 1.0.0-next.80
+
+### Patch Changes
+
+- Updated dependencies [[`d0e63d44`](https://github.com/sveltejs/kit/commit/d0e63d445e19e2df7a5e7d35f42b2ba1ae5e5745)]:
+  - @sveltejs/adapter-cloudflare@1.0.0-next.38
+
 ## 1.0.0-next.79
 
 ### Patch Changes
diff --git a/packages/adapter-auto/package.json b/packages/adapter-auto/package.json
index a6ac51e9e..859537000 100644
--- a/packages/adapter-auto/package.json
+++ b/packages/adapter-auto/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/adapter-auto",
-	"version": "1.0.0-next.79",
+	"version": "1.0.0-next.80",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/adapter-cloudflare/CHANGELOG.md b/packages/adapter-cloudflare/CHANGELOG.md
index b00a3702d..fc1d02e4c 100644
--- a/packages/adapter-cloudflare/CHANGELOG.md
+++ b/packages/adapter-cloudflare/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/adapter-cloudflare
 
+## 1.0.0-next.38
+
+### Patch Changes
+
+- Ensure all excluded paths in `_routes.json` start with / ([#6952](https://github.com/sveltejs/kit/pull/6952))
+
 ## 1.0.0-next.37
 
 ### Patch Changes
diff --git a/packages/adapter-cloudflare/package.json b/packages/adapter-cloudflare/package.json
index e06358d5b..5c180ae58 100644
--- a/packages/adapter-cloudflare/package.json
+++ b/packages/adapter-cloudflare/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/adapter-cloudflare",
-	"version": "1.0.0-next.37",
+	"version": "1.0.0-next.38",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/kit/src/exports/vite/build/build_server.js b/packages/kit/src/exports/vite/build/build_server.js
index 9b116d423..0f1120e5f 100644
--- a/packages/kit/src/exports/vite/build/build_server.js
+++ b/packages/kit/src/exports/vite/build/build_server.js
@@ -82,7 +82,7 @@ export class Server {
 			public_env: {},
 			read,
 			root,
-			service_worker: ${has_service_worker ? "base + '/service-worker.js'" : 'null'},
+			service_worker: ${has_service_worker},
 			app_template,
 			app_template_contains_nonce: ${template.includes('%sveltekit.nonce%')},
 			error_template,
diff --git a/packages/kit/src/exports/vite/dev/index.js b/packages/kit/src/exports/vite/dev/index.js
index 36e2fa0f2..3c971ce19 100644
--- a/packages/kit/src/exports/vite/dev/index.js
+++ b/packages/kit/src/exports/vite/dev/index.js
@@ -460,6 +460,7 @@ export async function dev(vite, vite_config, svelte_config) {
 								.replace(/%sveltekit\.status%/g, String(status))
 								.replace(/%sveltekit\.error\.message%/g, message);
 						},
+						service_worker: false,
 						trailing_slash: svelte_config.kit.trailingSlash
 					},
 					{
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index 195eab6ca..071423a6f 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -537,9 +537,7 @@ export function create_client({ target, base, trailing_slash }) {
 				async fetch(resource, init) {
 					let requested;
 
-					if (typeof resource === 'string') {
-						requested = resource;
-					} else {
+					if (resource instanceof Request) {
 						requested = resource.url;
 
 						// we're not allowed to modify the received `Request` object, so in order
@@ -564,6 +562,8 @@ export function create_client({ target, base, trailing_slash }) {
 							signal: resource.signal,
 							...init
 						};
+					} else {
+						requested = resource;
 					}
 
 					// we must fixup relative urls so they are resolved from the target page
diff --git a/packages/kit/src/runtime/client/fetcher.js b/packages/kit/src/runtime/client/fetcher.js
index 1552656fa..e355ee2db 100644
--- a/packages/kit/src/runtime/client/fetcher.js
+++ b/packages/kit/src/runtime/client/fetcher.js
@@ -62,12 +62,12 @@ const cache = new Map();
 /**
  * Should be called on the initial run of load functions that hydrate the page.
  * Saves any requests with cache-control max-age to the cache.
- * @param {RequestInfo} resource
+ * @param {RequestInfo | URL} resource
  * @param {string} resolved
  * @param {RequestInit} [opts]
  */
 export function initial_fetch(resource, resolved, opts) {
-	const url = JSON.stringify(typeof resource === 'string' ? resource : resource.url);
+	const url = JSON.stringify(resource instanceof Request ? resource.url : resource);
 
 	let selector = `script[data-sveltekit-fetched][data-url=${url}]`;
 
diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js
index 308d02e0c..2bb13b92d 100644
--- a/packages/kit/src/runtime/server/page/render.js
+++ b/packages/kit/src/runtime/server/page/render.js
@@ -187,37 +187,6 @@ export async function render_response({
 		serialized.form = devalue(form_value);
 	}
 
-	// prettier-ignore
-	const init_app = `
-		import { start } from ${s(prefixed(entry.file))};
-
-		start({
-			env: ${s(options.public_env)},
-			hydrate: ${page_config.ssr ? `{
-				status: ${status},
-				error: ${s(error)},
-				node_ids: [${branch.map(({ node }) => node.index).join(', ')}],
-				params: ${devalue(event.params)},
-				routeId: ${s(event.routeId)},
-				data: ${serialized.data},
-				form: ${serialized.form}
-			}` : 'null'},
-			paths: ${s(options.paths)},
-			target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode,
-			trailing_slash: ${s(options.trailing_slash)}
-		});
-	`;
-
-	// we use an anonymous function instead of an arrow function to support
-	// older browsers (https://github.com/sveltejs/kit/pull/5417)
-	const init_service_worker = `
-		if ('serviceWorker' in navigator) {
-			addEventListener('load', function () {
-				navigator.serviceWorker.register('${options.service_worker}');
-			});
-		}
-	`;
-
 	if (inline_styles.size > 0) {
 		const content = Array.from(inline_styles.values()).join('\n');
 
@@ -248,15 +217,36 @@ export async function render_response({
 		}
 
 		attributes.unshift('rel="stylesheet"');
-		head += `\n\t<link href="${path}" ${attributes.join(' ')}>`;
+		head += `\n\t\t<link href="${path}" ${attributes.join(' ')}>`;
 	}
 
 	if (page_config.csr) {
+		// prettier-ignore
+		const init_app = `
+			import { start } from ${s(prefixed(entry.file))};
+
+			start({
+				env: ${s(options.public_env)},
+				hydrate: ${page_config.ssr ? `{
+					status: ${status},
+					error: ${s(error)},
+					node_ids: [${branch.map(({ node }) => node.index).join(', ')}],
+					params: ${devalue(event.params)},
+					routeId: ${s(event.routeId)},
+					data: ${serialized.data},
+					form: ${serialized.form}
+				}` : 'null'},
+				paths: ${s(options.paths)},
+				target: document.querySelector('[data-sveltekit-hydrate="${target}"]').parentNode,
+				trailing_slash: ${s(options.trailing_slash)}
+			});
+		`;
+
 		for (const dep of modulepreloads) {
 			const path = prefixed(dep);
 			link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
 			if (state.prerendering) {
-				head += `\n\t<link rel="modulepreload" href="${path}">`;
+				head += `\n\t\t<link rel="modulepreload" href="${path}">`;
 			}
 		}
 
@@ -280,11 +270,21 @@ export async function render_response({
 	}
 
 	if (options.service_worker) {
+		// we use an anonymous function instead of an arrow function to support
+		// older browsers (https://github.com/sveltejs/kit/pull/5417)
+		const init_service_worker = `
+			if ('serviceWorker' in navigator) {
+				addEventListener('load', function () {
+					navigator.serviceWorker.register('${prefixed('service-worker.js')}');
+				});
+			}
+		`;
+
 		// always include service worker unless it's turned off explicitly
 		csp.add_script(init_service_worker);
 
 		head += `
-			<script${csp.script_needs_nonce ? ` nonce="${csp.nonce}"` : ''}>${init_service_worker}</script>`;
+		<script${csp.script_needs_nonce ? ` nonce="${csp.nonce}"` : ''}>${init_service_worker}</script>`;
 	}
 
 	if (state.prerendering) {
diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts
index 247f3b710..c48dba8ad 100644
--- a/packages/kit/types/index.d.ts
+++ b/packages/kit/types/index.d.ts
@@ -265,7 +265,7 @@ export interface LoadEvent<
 	Data extends Record<string, unknown> | null = Record<string, any> | null,
 	ParentData extends Record<string, unknown> = Record<string, any>
 > extends NavigationEvent<Params> {
-	fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
+	fetch: typeof fetch;
 	data: Data;
 	setHeaders: (headers: Record<string, string>) => void;
 	parent: () => Promise<ParentData>;
diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts
index aebf0be71..29f84240d 100644
--- a/packages/kit/types/internal.d.ts
+++ b/packages/kit/types/internal.d.ts
@@ -298,7 +298,7 @@ export interface SSROptions {
 	public_env: Record<string, string>;
 	read(file: string): Buffer;
 	root: SSRComponent['default'];
-	service_worker?: string;
+	service_worker: boolean;
 	app_template({
 		head,
 		body,


Test patch:
diff --git a/packages/kit/test/prerendering/basics/src/service-worker.js b/packages/kit/test/prerendering/basics/src/service-worker.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/kit/test/prerendering/basics/test/test.js b/packages/kit/test/prerendering/basics/test/test.js
index 44d80bfff..a7135660a 100644
--- a/packages/kit/test/prerendering/basics/test/test.js
+++ b/packages/kit/test/prerendering/basics/test/test.js
@@ -225,4 +225,9 @@ test('prerenders a page in a (group)', () => {
 	assert.ok(content.includes('<h1>grouped</h1>'));
 });
 
+test('injects relative service worker', () => {
+	const content = read('index.html');
+	assert.ok(content.includes(`navigator.serviceWorker.register('./service-worker.js')`));
+});
+
 test.run();