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

[feat] allow to disable service worker auto inject #2988

Merged
merged 7 commits into from
Dec 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/wise-rules-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

Add serviceWorker.register option
4 changes: 2 additions & 2 deletions documentation/docs/06-service-workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ title: Service workers

Service workers act as proxy servers that handle network requests inside your app. This makes it possible to make your app work offline, but even if you don't need offline support (or can't realistically implement it because of the type of app you're building), it's often worth using service workers to speed up navigation by precaching your built JS and CSS.

In SvelteKit, if you have a `src/service-worker.js` file (or `src/service-worker.ts`, or `src/service-worker/index.js`, etc) it will be built with Vite and automatically registered.
In SvelteKit, if you have a `src/service-worker.js` file (or `src/service-worker.ts`, or `src/service-worker/index.js`, etc) it will be built with Vite and automatically registered. You can disable automatic registration if you need to register the service worker with your own logic (e.g. prompt user for update, configure periodic updates, use `workbox`, etc).

> You can change the location of your service worker in your [project configuration](#configuration-files).
> You can change the location of your service worker and disable automatic registration in your [project configuration](#configuration-files).

Inside the service worker you have access to the [`$service-worker` module](#modules-$service-worker).

Expand Down
3 changes: 2 additions & 1 deletion documentation/docs/14-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ const config = {
},
router: true,
serviceWorker: {
register: true,
files: (filepath) => !/\.DS_STORE/.test(filepath)
},
ssr: true,
target: null,
trailingSlash: 'never',
vite: () => ({})
},

// SvelteKit uses vite-plugin-svelte. Its options can be provided directly here.
// See the available options at https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md

Expand Down
11 changes: 8 additions & 3 deletions packages/kit/src/core/build/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/
}),
output_dir,
client_entry_file: `${SVELTE_KIT}/build/runtime/internal/start.js`,
service_worker_entry_file: resolve_entry(config.kit.files.serviceWorker)
service_worker_entry_file: resolve_entry(config.kit.files.serviceWorker),
service_worker_register: config.kit.serviceWorker.register
};

const client_manifest = await build_client(options);
Expand Down Expand Up @@ -85,6 +86,7 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string | null;
* service_worker_register: boolean;
* }} options
*/
async function build_client({
Expand Down Expand Up @@ -199,6 +201,7 @@ async function build_client({
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string | null;
* service_worker_register: boolean;
* }} options
* @param {import('vite').Manifest} client_manifest
* @param {string} runtime
Expand All @@ -212,7 +215,8 @@ async function build_server(
build_dir,
output_dir,
client_entry_file,
service_worker_entry_file
service_worker_entry_file,
service_worker_register
},
client_manifest,
runtime
Expand Down Expand Up @@ -338,7 +342,7 @@ async function build_server(
prerender: ${config.kit.prerender.enabled},
read: settings.read,
root,
service_worker: ${service_worker_entry_file ? "'/service-worker.js'" : 'null'},
service_worker: ${service_worker_entry_file && service_worker_register ? "'/service-worker.js'" : 'null'},
router: ${s(config.kit.router)},
ssr: ${s(config.kit.ssr)},
target: ${s(config.kit.target)},
Expand Down Expand Up @@ -504,6 +508,7 @@ async function build_server(
* output_dir: string;
* client_entry_file: string;
* service_worker_entry_file: string | null;
* service_worker_register: boolean;
* }} options
* @param {import('vite').Manifest} client_manifest
*/
Expand Down
8 changes: 6 additions & 2 deletions packages/kit/src/core/config/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ test('fills in defaults', () => {
dir: 'package',
emitTypes: true
},
serviceWorker: {},
serviceWorker: {
register: true
},
paths: {
base: '',
assets: ''
Expand Down Expand Up @@ -136,7 +138,9 @@ test('fills in partial blanks', () => {
dir: 'package',
emitTypes: true
},
serviceWorker: {},
serviceWorker: {
register: true
},
paths: {
base: '',
assets: ''
Expand Down
1 change: 1 addition & 0 deletions packages/kit/src/core/config/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ const options = object(
router: boolean(true),

serviceWorker: object({
register: boolean(true),
files: fun((filename) => !/\.DS_STORE/.test(filename))
}),

Expand Down
4 changes: 3 additions & 1 deletion packages/kit/src/core/config/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ async function testLoadDefaultConfig(path) {
dir: 'package',
emitTypes: true
},
serviceWorker: {},
serviceWorker: {
register: true
},
paths: { base: '', assets: '' },
prerender: {
crawl: true,
Expand Down
1 change: 1 addition & 0 deletions packages/kit/test/apps/options-2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This app exists to test options that are equivalent with the ones specified in the other `options` test app.
16 changes: 16 additions & 0 deletions packages/kit/test/apps/options-2/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "test-options-2",
"private": true,
"version": "0.0.1",
"scripts": {
"dev": "../../../svelte-kit.js dev",
"build": "../../../svelte-kit.js build",
"preview": "../../../svelte-kit.js preview"
},
"devDependencies": {
"@sveltejs/adapter-node": "workspace:*",
"@sveltejs/kit": "workspace:*",
"svelte": "^3.43.0"
},
"type": "module"
}
11 changes: 11 additions & 0 deletions packages/kit/test/apps/options-2/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%svelte.head%
</head>
<body>
%svelte.body%
</body>
</html>
29 changes: 29 additions & 0 deletions packages/kit/test/apps/options-2/src/routes/_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as assert from 'uvu/assert';

/** @type {import('test').TestMaker} */
export default function (test) {
test('serves /', '/', async ({ page }) => {
assert.equal(await page.textContent('h1'), 'Hello');
});

test(
'build /service-worker.js',
'/',
async ({ fetch }) => {
const res = await fetch('/service-worker.js');
const content = await res.text();

assert.match(content, /\/_app\/start-[a-z0-9]+\.js/);
},
{ dev: false, js: true }
);

test(
'does not register /service-worker.js',
'/',
async ({ page }) => {
assert.not.match(await page.content(), /navigator\.serviceWorker/);
},
{ dev: false, js: true }
);
}
1 change: 1 addition & 0 deletions packages/kit/test/apps/options-2/src/routes/index.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>Hello</h1>
53 changes: 53 additions & 0 deletions packages/kit/test/apps/options-2/src/service-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { timestamp, build } from '$service-worker';

const name = `cache-${timestamp}`;

self.addEventListener('install', (event) => {
// @ts-expect-error
event.waitUntil(caches.open(name).then((cache) => cache.addAll(build)));
});

self.addEventListener('activate', (event) => {
// @ts-expect-error
event.waitUntil(
caches.keys().then(async (keys) => {
for (const key of keys) {
if (!key.includes(String(timestamp))) caches.delete(key);
}
})
);
});

self.addEventListener('fetch', (event) => {
// @ts-expect-error
const { request } = event;

if (request.method !== 'GET' || request.headers.has('range')) return;

const url = new URL(request.url);
const cached = caches.match(request);

if (url.origin === location.origin && build.includes(url.pathname)) {
// always return build files from cache
// @ts-expect-error
event.respondWith(cached);
} else if (url.protocol === 'https:' || location.hostname === 'localhost') {
// hit the network for everything else...
const promise = fetch(request);

// ...and cache successful responses...
promise.then((response) => {
// cache successful responses
if (response.ok && response.type === 'basic') {
const clone = response.clone();
caches.open(name).then((cache) => {
cache.put(request, clone);
});
}
});

// ...but if it fails, fall back to cache if available
// @ts-expect-error
event.respondWith(promise.catch(() => cached || promise));
}
});
10 changes: 10 additions & 0 deletions packages/kit/test/apps/options-2/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
serviceWorker: {
register: false
}
}
};

export default config;
3 changes: 2 additions & 1 deletion packages/kit/types/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ export interface Config {
};
router?: boolean;
serviceWorker?: {
files?(filepath: string): boolean;
register?: boolean;
files?: (filepath: string) => boolean;
};
ssr?: boolean;
target?: string;
Expand Down