From 2188cbac81f0eb58482fce4b99f90e285473b306 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 13 Mar 2025 12:36:35 +0100 Subject: [PATCH 1/5] feat: allow to specify options for the service worker in `svelte.config.js` --- .changeset/fuzzy-guests-obey.md | 5 ++++ packages/kit/src/core/config/options.js | 1 + packages/kit/src/core/sync/write_server.js | 1 + packages/kit/src/exports/public.d.ts | 28 ++++++++++++++----- .../kit/src/runtime/server/page/render.js | 9 +++++- packages/kit/src/types/internal.d.ts | 1 + packages/kit/types/index.d.ts | 28 ++++++++++++++----- 7 files changed, 58 insertions(+), 15 deletions(-) create mode 100644 .changeset/fuzzy-guests-obey.md diff --git a/.changeset/fuzzy-guests-obey.md b/.changeset/fuzzy-guests-obey.md new file mode 100644 index 000000000000..98a430f51847 --- /dev/null +++ b/.changeset/fuzzy-guests-obey.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': minor +--- + +feat: allow to specify options for the service worker in `svelte.config.js` diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index a2b9bb81759d..b8aec62fc852 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -267,6 +267,7 @@ const options = object( serviceWorker: object({ register: boolean(true), + options: object({}, true), files: fun((filename) => !/\.DS_Store/.test(filename)) }), diff --git a/packages/kit/src/core/sync/write_server.js b/packages/kit/src/core/sync/write_server.js index 5e93d5c1cd25..5643e9108c2c 100644 --- a/packages/kit/src/core/sync/write_server.js +++ b/packages/kit/src/core/sync/write_server.js @@ -46,6 +46,7 @@ export const options = { preload_strategy: ${s(config.kit.output.preloadStrategy)}, root, service_worker: ${has_service_worker}, + service_worker_options: ${config.kit.serviceWorker.register ? s(config.kit.serviceWorker.options) : 'null'}, templates: { app: ({ head, body, assets, nonce, env }) => ${s(template) .replace('%sveltekit.head%', '" + head + "') diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 2ff29f3571a0..96f447d8e21c 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -683,17 +683,31 @@ export interface KitConfig { resolution?: 'client' | 'server'; }; serviceWorker?: { - /** - * Whether to automatically register the service worker, if it exists. - * @default true - */ - register?: boolean; /** * Determine which files in your `static` directory will be available in `$service-worker.files`. * @default (filename) => !/\.DS_Store/.test(filename) */ - files?(filepath: string): boolean; - }; + files?: (file: string) => boolean; + } & ( + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register: true; + /** + * Options for serviceWorker.register("...", options); + */ + options?: Parameters[1]; + } + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register?: false; + } + ); typescript?: { /** * A function that allows you to edit the generated `tsconfig.json`. You can mutate the config (recommended) or return a new one. diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js index 59d9229164dc..e6cadddf7eba 100644 --- a/packages/kit/src/runtime/server/page/render.js +++ b/packages/kit/src/runtime/server/page/render.js @@ -454,7 +454,14 @@ export async function render_response({ } if (options.service_worker) { - const opts = __SVELTEKIT_DEV__ ? ", { type: 'module' }" : ''; + let opts = __SVELTEKIT_DEV__ ? ", { type: 'module' }" : ''; + if (options.service_worker_options != null) { + const service_worker_options = { ...options.service_worker_options }; + if (__SVELTEKIT_DEV__) { + service_worker_options.type = 'module'; + } + opts = `, ${s(service_worker_options)}`; + } // we use an anonymous function instead of an arrow function to support // older browsers (https://github.com/sveltejs/kit/pull/5417) diff --git a/packages/kit/src/types/internal.d.ts b/packages/kit/src/types/internal.d.ts index 82317e8417ab..7b5a42ceb7b5 100644 --- a/packages/kit/src/types/internal.d.ts +++ b/packages/kit/src/types/internal.d.ts @@ -422,6 +422,7 @@ export interface SSROptions { preload_strategy: ValidatedConfig['kit']['output']['preloadStrategy']; root: SSRComponent['default']; service_worker: boolean; + service_worker_options: Parameters[1]; templates: { app(values: { head: string; diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index af14891d66d3..6011b386fae8 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -665,17 +665,31 @@ declare module '@sveltejs/kit' { resolution?: 'client' | 'server'; }; serviceWorker?: { - /** - * Whether to automatically register the service worker, if it exists. - * @default true - */ - register?: boolean; /** * Determine which files in your `static` directory will be available in `$service-worker.files`. * @default (filename) => !/\.DS_Store/.test(filename) */ - files?(filepath: string): boolean; - }; + files?: (file: string) => boolean; + } & ( + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register: true; + /** + * Options for serviceWorker.register("...", options); + */ + options?: Parameters[1]; + } + | { + /** + * Whether to automatically register the service worker, if it exists. + * @default true + */ + register?: false; + } + ); typescript?: { /** * A function that allows you to edit the generated `tsconfig.json`. You can mutate the config (recommended) or return a new one. From dda927735fd7ef89595164b32797a5fe04a0c8f5 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 13 Mar 2025 14:56:30 +0100 Subject: [PATCH 2/5] fix: better validation of `options` config --- packages/kit/src/core/config/options.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index b8aec62fc852..3d0912bc7e3d 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -267,7 +267,9 @@ const options = object( serviceWorker: object({ register: boolean(true), - options: object({}, true), + // options could be undefined but if it is defined we only validate that + // it's an object since the type comes from the browser itself + options: validate(undefined, () => object({}, true)), files: fun((filename) => !/\.DS_Store/.test(filename)) }), From 4c760cb287956700e4c68d064af7d9c56c9dc8f8 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 13 Mar 2025 15:06:29 +0100 Subject: [PATCH 3/5] fix: use easier types --- packages/kit/src/exports/public.d.ts | 2 +- packages/kit/src/types/internal.d.ts | 2 +- packages/kit/types/index.d.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/exports/public.d.ts b/packages/kit/src/exports/public.d.ts index 96f447d8e21c..9f1b63a95b1a 100644 --- a/packages/kit/src/exports/public.d.ts +++ b/packages/kit/src/exports/public.d.ts @@ -698,7 +698,7 @@ export interface KitConfig { /** * Options for serviceWorker.register("...", options); */ - options?: Parameters[1]; + options?: RegistrationOptions; } | { /** diff --git a/packages/kit/src/types/internal.d.ts b/packages/kit/src/types/internal.d.ts index 7b5a42ceb7b5..0640e9c10e43 100644 --- a/packages/kit/src/types/internal.d.ts +++ b/packages/kit/src/types/internal.d.ts @@ -422,7 +422,7 @@ export interface SSROptions { preload_strategy: ValidatedConfig['kit']['output']['preloadStrategy']; root: SSRComponent['default']; service_worker: boolean; - service_worker_options: Parameters[1]; + service_worker_options: RegistrationOptions; templates: { app(values: { head: string; diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 6011b386fae8..d713c730e8bf 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -680,7 +680,7 @@ declare module '@sveltejs/kit' { /** * Options for serviceWorker.register("...", options); */ - options?: Parameters[1]; + options?: RegistrationOptions; } | { /** From 42ea5a19c6ed38bddb951f851aa562719fe195d1 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 13 Mar 2025 16:15:40 +0100 Subject: [PATCH 4/5] chore: add test for service worker `options` --- .../kit/test/apps/basics/svelte.config.js | 6 +++++ packages/kit/test/apps/basics/test/test.js | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/kit/test/apps/basics/svelte.config.js b/packages/kit/test/apps/basics/svelte.config.js index bca05e5376ee..35e294f609c7 100644 --- a/packages/kit/test/apps/basics/svelte.config.js +++ b/packages/kit/test/apps/basics/svelte.config.js @@ -27,6 +27,12 @@ const config = { ], handleHttpError: 'warn' }, + serviceWorker: { + register: true, + options: { + updateViaCache: 'imports' + } + }, version: { name: 'TEST_VERSION' diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index c5867f34e00c..225d5c8243e1 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -1532,3 +1532,25 @@ test.describe('Serialization', () => { expect(await page.textContent('h1')).toBe('It works!'); }); }); + +test.describe('service worker option', () => { + test('pass the options to the service worker', async ({ page }) => { + await page.goto('/'); + const content = await page.content(); + const matching = content.match(/navigator\.serviceWorker\.register\(.+?, (?{.+?})\)/); + let options = {}; + if (matching && matching.groups) { + options = JSON.parse(matching.groups.options); + } + if (process.env.DEV) { + expect(options).toMatchObject({ + type: 'module', + updateViaCache: 'imports' + }); + } else { + expect(options).toMatchObject({ + updateViaCache: 'imports' + }); + } + }); +}); From 394d86b9b0398e090fedc6780a48993baa213d43 Mon Sep 17 00:00:00 2001 From: paoloricciuti Date: Thu, 13 Mar 2025 17:04:02 +0100 Subject: [PATCH 5/5] fix: `object` is already a function --- packages/kit/src/core/config/options.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/core/config/options.js b/packages/kit/src/core/config/options.js index 3d0912bc7e3d..a9afcd398ab1 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -269,7 +269,7 @@ const options = object( register: boolean(true), // options could be undefined but if it is defined we only validate that // it's an object since the type comes from the browser itself - options: validate(undefined, () => object({}, true)), + options: validate(undefined, object({}, true)), files: fun((filename) => !/\.DS_Store/.test(filename)) }),