SolidJS
You can use the built-in Vite
virtual module virtual:pwa-register/solid
for SolidJS
which will return createSignal
stateful values (createSignal<boolean>
) for offlineReady
and needRefresh
.
警告
你需要将 workbox-window
作为 dev
依赖添加到你的 Vite
项目中
类型声明
提示
如果你的 TypeScript 构建时或 IDE 抱怨在导入时找不到模块或类型定义,请将以下内容添加到tsconfig.json
的 compilerOptions.types
数组中:
{
"compilerOptions": {
"types": ["vite-plugin-pwa/client"]
}
}
或者你可以添加以下引用到任何 d.ts
文件中(例如,在 vite-env.d.ts
或 global.d.ts
中):
/// <reference types="vite-plugin-pwa/client" />
From version 0.14.5
you can also use types definition for solid instead of vite-plugin-pwa/client
:
{
"compilerOptions": {
"types": ["vite-plugin-pwa/solid"]
}
}
Or you can add the following reference in any of your d.ts
files (for example, in vite-env.d.ts
or global.d.ts
):
/// <reference types="vite-plugin-pwa/solid" />
declare module 'virtual:pwa-register/solid' {
import type { Accessor, Setter } from 'solid-js';
import type { RegisterSWOptions } from 'vite-plugin-pwa/types';
export type { RegisterSWOptions };
export function useRegisterSW(options?: RegisterSWOptions): {
needRefresh: [Accessor<boolean>, Setter<boolean>];
offlineReady: [Accessor<boolean>, Setter<boolean>];
updateServiceWorker: (reloadPage?: boolean) => Promise<void>;
};
}
Prompt for update
You can use this ReloadPrompt.tsx
component:
ReloadPrompt.tsx
import type { Component } from 'solid-js';
import { Show } from 'solid-js';
import { useRegisterSW } from 'virtual:pwa-register/solid';
import styles from './ReloadPrompt.module.css';
const ReloadPrompt: Component = () => {
const {
offlineReady: [offlineReady, setOfflineReady],
needRefresh: [needRefresh, setNeedRefresh],
updateServiceWorker,
} = useRegisterSW({
onRegistered(r) {
// eslint-disable-next-line prefer-template
console.log('SW Registered: ' + r);
},
onRegisterError(error) {
console.log('SW registration error', error);
},
});
const close = () => {
setOfflineReady(false);
setNeedRefresh(false);
};
return (
<div className={styles.Container}>
<Show when={offlineReady() || needRefresh()}>
<div className={styles.Toast}>
<div className={styles.Message}>
<Show
fallback={
<span>
New content available, click on reload button to update.
</span>
}
when={offlineReady()}
>
<span>App ready to work offline</span>
</Show>
</div>
<Show when={needRefresh()}>
<button
className={styles.ToastButton}
onClick={() => updateServiceWorker(true)}
>
Reload
</button>
</Show>
<button className={styles.ToastButton} onClick={() => close()}>
Close
</button>
</div>
</Show>
</div>
);
};
export default ReloadPrompt;
and its corresponding ReloadPrompt.module.css
styles module:
ReloadPrompt.module.css
.Container {
padding: 0;
margin: 0;
width: 0;
height: 0;
}
.Toast {
position: fixed;
right: 0;
bottom: 0;
margin: 16px;
padding: 12px;
border: 1px solid #8885;
border-radius: 4px;
z-index: 1;
text-align: left;
box-shadow: 3px 4px 5px 0 #8885;
background-color: white;
}
.ToastMessage {
margin-bottom: 8px;
}
.ToastButton {
border: 1px solid #8885;
outline: none;
margin-right: 5px;
border-radius: 2px;
padding: 3px 10px;
}
Periodic SW Updates
As explained in 定期更新 Service Worker , you can use this code to configure this behavior on your application with the virtual module virtual:pwa-register/solid
:
import { useRegisterSW } from 'virtual:pwa-register/solid';
const intervalMS = 60 * 60 * 1000;
const updateServiceWorker = useRegisterSW({
onRegistered(r) {
r &&
setInterval(() => {
r.update();
}, intervalMS);
},
});
The interval must be in milliseconds, in the example above it is configured to check the service worker every hour.
警告
这只适用于在导入任何虚拟模块或使用 workbox-window
模块时
因为 workbox-window
使用基于时间的 heuristic
算法来处理 service worker 更新,因此,如果您构建了自己的 service worker 并再次注册它,如果上次注册和本次注册之间的时间不足 1 分钟,那么workbox-window
将把 service worker update found
事件作为外部事件处理,因此可能会有很奇怪的行为(例如,如果使用 prompt
,将显示离线准备就绪的对话框,而不是显示新内容可用的对话框;如果使用 autoUpdate
,将显示离线准备就绪的对话框,然而它不应该显示)。