Dans ce tutoriel, je vous propose de découvrir ensemble le plugin vite pwa qui va vous permettre de créer une progressive web app à partir d'un projet créé avec vite. Pour rappel, une progressive web APP est une application web qui va proposer une expérience utilisateur proche de celle d'une application mobile. Cela passe par plusieurs fonctionnalités, dont une qui va nous intéresser particulièrement aujourd'hui, c'est la possibilité de fonctionner hors ligne.
Pour commencer
Pour utiliser Vite PWA, vous avez 2 solutions. La première consiste à créer et initialiser un projet en utilisant leur template :
pnpm create @vite-pwa/pwa
Cette installation vous posera différentes questions qui vous permettront de configurer le fonctionnement de votre application.
La seconde approche consiste à ajouter Vite PWA à un projet existant. On commencera alors par installer le plugin :
pnpm add -D vite-plugin-pwa
Puis on l'ajoutera à notre fichier de configuration vite.
import { VitePWA } from 'vite-plugin-pwa'
export default defineConfig({
plugins: [
VitePWA({/* Options de configuration */})
]
})
Fonctionnement
Vite PWA se repose sur l'utilisation de workbox-build qui va lister l'ensemble des fichiers à mettre en cache lors du build . À partir de ces fichiers, il va générer un fichier sw.js qui servira de service worker et il
rajoutera aussi le code permettant l'enregistrement de ce dernier.
Il est possible de modifier la configuration pour spécifier les types de fichiers qui doivent être inclus dans la mise en cache.
VitePWA({
workbox: {
globPatterns: ['**/*.{js,css,html,svg,ico,png}'],
}
})
Avec cette simple configuration, si vous construisez votre projet et que vous le lancez, il va automatiquement fonctionner hors ligne après la première installation.
Mise à jour
Le problème que l'on rencontre maintenant est le besoin de mise à jour de notre application. En effet, le problème que l'on rencontre en général est qu'une application PWA est mise en mémoire par le navigateur et l'utilisateur n'est pas forcément au courant des changements de version. Vite PWA propose 2 stratégies pour cela :
autoUpdate
, avec ce comportement, dès que le navigateur détecte une nouvelle version de votre application, il mettra à jour les caches et rechargera automatiquement toutes les fenêtres/onglets du navigateur où l'application est ouverte pour en prendre le contrôle.promptUpdate
(défaut), Dès que le navigateur détecte une nouvelle version de votre application, une alerte s'affichera à l'utilisateur et lui permettra de recharger la page avec la nouvelle version.
Cette option se configure au travers de la clé registerType
:
VitePWA({
registerType: 'autoUpdate'
})
autoUpdate
Pour que l'autoUpdate fonctionne vous devrez rajouter le module permettant le rafraichissement dans votre application.
import { registerSW } from 'virtual:pwa-register'
registerSW({ immediate: true })
Sans ce code, le service worker sera bien rafraichit mais la page ne s'actualisera pas automatiquement.
promptUpdate
Dans le cadre de l'option promptUpdate il faudra ajouter les éléments d'interface dans le code de notre application. La documentation propose des exemples de code pour les différents frameworks.
import React from 'react'
import { useRegisterSW } from 'virtual:pwa-register/react'
export function ReloadPrompt() {
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>
{ (offlineReady || needRefresh)
&& <div>
<div>
{ offlineReady
? <span>App ready to work offline</span>
: <span>New content available, click on reload button to update.</span>
}
</div>
{ needRefresh && <button onClick={() => updateServiceWorker(true)}>Reload</button> }
<button onClick={() => close()}>Close</button>
</div>
}
</div>
)
}
Resources externes
Dans une application réelle, on a souvent des ressources externes (polices ou images chargées depuis un CDN). Pour gérer la mise en cache de ces ressources, il va falloir rajouter une configuration supplémentaire.
VitePWA({
workbox: {
runtimeCaching: [
{
urlPattern: /^https:\/\/fonts\.googleapis\.com\/.*/i,
handler: 'CacheFirst',
options: {
cacheName: 'google-fonts-cache',
expiration: {
maxEntries: 10,
maxAgeSeconds: 60 * 60 * 24 * 365 // <== 365 days
},
cacheableResponse: {
statuses: [0, 200]
}
}
}
]
}
})
Cette option permet la mise en cache de ressources lorsqu'elles sont rencontrées par le navigateur lors du premier chargement en ligne.