sveltekit-cache-first 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -7
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/no-update.svelte +17 -0
- package/dist/no-update.svelte.d.ts +7 -0
- package/dist/update-available.svelte +17 -0
- package/dist/update-available.svelte.d.ts +9 -0
- package/dist/update.d.ts +1 -1
- package/dist/update.js +13 -5
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SvelteKit Cache First
|
|
2
2
|
|
|
3
|
-
A small library to make your SvelteKit Web App / PWA
|
|
3
|
+
A small library to make your SvelteKit Web App / PWA use a cache first approach: instant second visit loads and fast performance on poor network conditions.
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -11,14 +11,35 @@ npm install sveltekit-cache-first
|
|
|
11
11
|
```js
|
|
12
12
|
// src/service-worker.js
|
|
13
13
|
import { version, build, files } from '$service-worker';
|
|
14
|
-
import { setupServiceWorker } from 'sveltekit-cache-first';
|
|
14
|
+
import { setupServiceWorker } from 'sveltekit-cache-first/sw';
|
|
15
15
|
|
|
16
16
|
setupServiceWorker(self, { version, build, files });
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
#### Component method
|
|
20
|
+
```svelte
|
|
21
|
+
<script>
|
|
22
|
+
import { UpdateAvailable } from 'sveltekit-cache-first';
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<UpdateAvailable>
|
|
26
|
+
{#snippet children({ accept })}
|
|
27
|
+
<h2>An update is available</h2>
|
|
28
|
+
<p>Refresh to update</p>
|
|
29
|
+
<button onclick={() => accept()}>Refresh</button>
|
|
30
|
+
{/snippet}
|
|
31
|
+
</UpdateAvailable>
|
|
32
|
+
|
|
33
|
+
<!-- Optional -->
|
|
34
|
+
<!-- Note: This will disappear after the update has been detected, which may take a few seconds to appear. Only use this if your app must always be running the latest version. And if that is that is the case, strongly consider if cache-first is the right approach, or use other methods like api versioning. -->
|
|
35
|
+
<NoUpdate>
|
|
36
|
+
Main logic here
|
|
37
|
+
</NoUpdate>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Custom handler method, using [svelte-sonner](https://github.com/wobsoriano/svelte-sonner)
|
|
19
41
|
```js
|
|
20
42
|
// src/routes/+layout.svelte
|
|
21
|
-
// Example using toast from svelte-sonner
|
|
22
43
|
import { toast } from 'svelte-sonner';
|
|
23
44
|
import { onUpdate } from 'sveltekit-cache-first';
|
|
24
45
|
|
|
@@ -26,7 +47,7 @@ onMount(() => {
|
|
|
26
47
|
onUpdate((accept) => {
|
|
27
48
|
// Your notification logic here, eg:
|
|
28
49
|
toast('An update is available', {
|
|
29
|
-
description: 'Refresh
|
|
50
|
+
description: 'Refresh to update',
|
|
30
51
|
action: {
|
|
31
52
|
label: 'Refresh',
|
|
32
53
|
onClick: () => accept()
|
|
@@ -41,8 +62,9 @@ onMount(() => {
|
|
|
41
62
|
```js
|
|
42
63
|
// default values
|
|
43
64
|
const options = {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
65
|
+
cachePageData: false, // Cache _data.json: data returned by load functions
|
|
66
|
+
ignoredRoutes: ['/api'] // Routes to always fetch fresh for
|
|
67
|
+
};
|
|
47
68
|
|
|
48
69
|
setupServiceWorker(self, { version, build, files, options });
|
|
70
|
+
```
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import UpdateAvailable from "./update-available.svelte";
|
|
2
2
|
import { onUpdate } from "./update.ts";
|
|
3
|
-
|
|
3
|
+
import NoUpdate from "./no-update.svelte";
|
|
4
|
+
export { onUpdate, UpdateAvailable, NoUpdate };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Reexport your entry components here
|
|
2
|
-
import
|
|
2
|
+
import UpdateAvailable from "./update-available.svelte";
|
|
3
3
|
import { onUpdate } from "./update.js";
|
|
4
|
-
|
|
4
|
+
import NoUpdate from "./no-update.svelte";
|
|
5
|
+
export { onUpdate, UpdateAvailable, NoUpdate };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, type Snippet } from 'svelte';
|
|
3
|
+
import { onUpdate } from './update.js';
|
|
4
|
+
|
|
5
|
+
let { children }: { children?: Snippet } = $props();
|
|
6
|
+
|
|
7
|
+
let updateAvailable = $state(false);
|
|
8
|
+
onMount(() => {
|
|
9
|
+
onUpdate(() => {
|
|
10
|
+
updateAvailable = true;
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{#if !updateAvailable}
|
|
16
|
+
{@render children?.()}
|
|
17
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount, type Snippet } from 'svelte';
|
|
3
|
+
import { onUpdate } from './update.js';
|
|
4
|
+
|
|
5
|
+
let { children }: { children?: Snippet<[{ accept: () => void }]> } = $props();
|
|
6
|
+
|
|
7
|
+
let handleAccept: (() => void) | null = $state(null);
|
|
8
|
+
onMount(() => {
|
|
9
|
+
onUpdate((accept) => {
|
|
10
|
+
handleAccept = accept;
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
{#if handleAccept !== null}
|
|
16
|
+
{@render children?.({ accept: handleAccept })}
|
|
17
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Snippet } from 'svelte';
|
|
2
|
+
type $$ComponentProps = {
|
|
3
|
+
children?: Snippet<[{
|
|
4
|
+
accept: () => void;
|
|
5
|
+
}]>;
|
|
6
|
+
};
|
|
7
|
+
declare const UpdateAvailable: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type UpdateAvailable = ReturnType<typeof UpdateAvailable>;
|
|
9
|
+
export default UpdateAvailable;
|
package/dist/update.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function onUpdate(handle: (onAccept: () => void) => void):
|
|
1
|
+
export declare function onUpdate(handle: (onAccept: () => void) => void): void;
|
package/dist/update.js
CHANGED
|
@@ -18,7 +18,9 @@ async function checkVersionChanged(worker) {
|
|
|
18
18
|
function handleAccept(worker) {
|
|
19
19
|
worker.postMessage({ type: 'SKLOCALFIRST_SKIP_WAITING' });
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const handlers = [];
|
|
22
|
+
let listenerSetUp = false;
|
|
23
|
+
function setupSWListener() {
|
|
22
24
|
if (!('serviceWorker' in navigator)) {
|
|
23
25
|
return () => { };
|
|
24
26
|
}
|
|
@@ -29,7 +31,7 @@ export function onUpdate(handle) {
|
|
|
29
31
|
if (reg.waiting) {
|
|
30
32
|
const sw = reg.waiting;
|
|
31
33
|
if (await checkVersionChanged(sw)) {
|
|
32
|
-
handle(() => handleAccept(sw));
|
|
34
|
+
handlers.forEach((handle) => handle(() => handleAccept(sw)));
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
// 2️⃣ Listen for new SW installations
|
|
@@ -39,8 +41,7 @@ export function onUpdate(handle) {
|
|
|
39
41
|
return;
|
|
40
42
|
sw.addEventListener('statechange', () => {
|
|
41
43
|
if (sw.state === 'installed' && navigator.serviceWorker.controller) {
|
|
42
|
-
|
|
43
|
-
handle(() => handleAccept(sw));
|
|
44
|
+
handlers.forEach((handle) => handle(() => handleAccept(sw)));
|
|
44
45
|
}
|
|
45
46
|
});
|
|
46
47
|
});
|
|
@@ -49,5 +50,12 @@ export function onUpdate(handle) {
|
|
|
49
50
|
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
|
50
51
|
window.location.reload();
|
|
51
52
|
});
|
|
52
|
-
|
|
53
|
+
listenerSetUp = true;
|
|
54
|
+
}
|
|
55
|
+
export function onUpdate(handle) {
|
|
56
|
+
handlers.push(handle);
|
|
57
|
+
if (!listenerSetUp) {
|
|
58
|
+
setupSWListener();
|
|
59
|
+
}
|
|
60
|
+
handlers.push(handle);
|
|
53
61
|
}
|