Skip to content

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.jsoncompilerOptions.types 数组中:

json
{
  "compilerOptions": {
    "types": ["vite-plugin-pwa/client"]
  }
}

或者你可以添加以下引用到任何 d.ts 文件中(例如,在 vite-env.d.tsglobal.d.ts 中):

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:

json
{
  "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):

ts
/// <reference types="vite-plugin-pwa/solid" />
ts
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
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
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:

ts
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 ,将显示离线准备就绪的对话框,然而它不应该显示)。

在MIT许可下发布.