diff --git a/.vitepress/config.ts b/.vitepress/config.ts index 45aaf2e..d6d85c1 100644 --- a/.vitepress/config.ts +++ b/.vitepress/config.ts @@ -107,6 +107,10 @@ const Frameworks = [ text: 'SolidJS', link: '/frameworks/solidjs', }, + { + text: 'SolidStart', + link: '/frameworks/solidstart', + }, { text: 'Preact', link: '/frameworks/preact', diff --git a/frameworks/solidstart.md b/frameworks/solidstart.md new file mode 100644 index 0000000..f6b2c1d --- /dev/null +++ b/frameworks/solidstart.md @@ -0,0 +1,195 @@ +--- +title: SolidStart | Frameworks +--- + +# SolidStart + +::: warning +At the time of writing SolidStart is still in beta. All of this information is subject to change. +::: + +You can use the built-in `Vite` virtual module `virtual:pwa-register/solid` for `SolidStart`. + +::: warning +You will need to add `workbox-window` as a `dev` dependency to your `Vite` project. +::: + +## Getting started + +Vite-Plugin-PWA will not register the service worker and inject the manifest automatically in SolidStart. For this, +you will need to interface with `useRegisterSW` and `pwaInfo` directly. This can be achieved easily by making the +following changes to your `root.tsx`. + +```tsx +/* Add the following imports */ +import { useRegisterSW } from "virtual:pwa-register/solid"; +import { pwaInfo } from "virtual:pwa-info"; + +export default function Root() { + // Register the service worker + useRegisterSW({immediate: true}); + return ( + + + {/* The rest of your Head */} + {/* check for and add a Link for the webmanifest */} + { pwaInfo?.webManifest?.href ? : '' } + {/* ..... */} + + ); +} +``` + + +## Type declarations + +::: tip + +::: + +```ts +declare module 'virtual:pwa-register/solid' { + // @ts-expect-error ignore when solid-js is not installed + import type { Accessor, Setter } from 'solid-js' + + export interface RegisterSWOptions { + immediate?: boolean + onNeedRefresh?: () => void + onOfflineReady?: () => void + /** + * Called only if `onRegisteredSW` is not provided. + * + * @deprecated Use `onRegisteredSW` instead. + * @param registration The service worker registration if available. + */ + onRegistered?: (registration: ServiceWorkerRegistration | undefined) => void + /** + * Called once the service worker is registered (requires version `0.12.8+`). + * + * @param swScriptUrl The service worker script url. + * @param registration The service worker registration if available. + */ + onRegisteredSW?: (swScriptUrl: string, registration: ServiceWorkerRegistration | undefined) => void + onRegisterError?: (error: any) => void + } + + export function useRegisterSW(options?: RegisterSWOptions): { + needRefresh: [Accessor, Setter] + offlineReady: [Accessor, Setter] + updateServiceWorker: (reloadPage?: boolean) => Promise + } +} +``` + +## Prompt for update + +You can use this `ReloadPrompt.tsx` component: + +::: details 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 ( +
+ +
+
+ New content available, click on reload button to update.} + when={offlineReady()} + > + App ready to work offline + +
+ + + + +
+
+
+ ) +} + +export default ReloadPrompt +``` +::: + +and its corresponding `ReloadPrompt.module.css` styles module: + +::: details 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 [Periodic Service Worker Updates](/guide/periodic-sw-updates), 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.