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..a9afcd398ab1 100644 --- a/packages/kit/src/core/config/options.js +++ b/packages/kit/src/core/config/options.js @@ -267,6 +267,9 @@ const options = object( serviceWorker: 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)), 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..9f1b63a95b1a 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?: RegistrationOptions; + } + | { + /** + * 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..0640e9c10e43 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: RegistrationOptions; templates: { app(values: { head: string; 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' + }); + } + }); +}); diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index af14891d66d3..d713c730e8bf 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?: RegistrationOptions; + } + | { + /** + * 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.