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: add solidstart docs #26

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions .vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ const Frameworks = [
text: 'SolidJS',
link: '/frameworks/solidjs',
},
{
text: 'SolidStart',
link: '/frameworks/solidstart',
},
{
text: 'Preact',
link: '/frameworks/preact',
Expand Down
195 changes: 195 additions & 0 deletions frameworks/solidstart.md
Original file line number Diff line number Diff line change
@@ -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 (
<Html lang="en">
<Head>
{/* The rest of your Head */}
{/* check for and add a Link for the webmanifest */}
{ pwaInfo?.webManifest?.href ? <Link rel="manifest" href={pwaInfo.webManifest.href}/> : '' }
{/* ..... */}
</Head>
);
}
```


## Type declarations

::: tip
<TypeScriptError2307 />
:::

```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<boolean>, Setter<boolean>]
offlineReady: [Accessor<boolean>, Setter<boolean>]
updateServiceWorker: (reloadPage?: boolean) => Promise<void>
}
}
```

## 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 (
<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:

::: 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.