Ce plugin est alimenté par Workbox et d'autres bonnes choses.
Partagez votre superbe projet PWA ici
Caractéristiques
next-i18next
blitz.config.js
).module.js
lorsque next.config.js
a experimental.modern
défini sur true
REMARQUE 1 -
next-pwa
version 2.0.0+ ne devrait fonctionner qu'avecnext.js
9.1+, et les fichiers statiques ne doivent être servis que via le répertoirepublic
. Cela rendra les choses plus simples.REMARQUE 2 - Si vous rencontrez l'erreur
TypeError: Cannot read property **'javascript' of undefined**
pendant la construction, veuillez envisager la mise à niveau vers webpack5 dansnext.config.js
.
Si vous êtes nouveau sur
next.js
ou surreact.js
, vous souhaiterez peut-être d'abord consulter le document next.js ou next.js. Commencez ensuite par un exemple simple ou un exemple d'application Web progressive dans le référentiel next.js.
yarn add next-pwa
Mettez à jour ou créez next.config.js
avec
const withPWA = require ( 'next-pwa' ) ( {
dest : 'public'
} )
module . exports = withPWA ( {
// next.js config
} )
Après avoir exécuté next build
, cela générera deux fichiers dans votre public
: workbox-*.js
et sw.js
, qui seront automatiquement servis de manière statique.
Si vous utilisez Next.js version 9 ou plus récente, ignorez les options ci-dessous et passez à l'étape 2.
Si vous utilisez Next.js avant la version 9, vous devrez choisir une option ci-dessous avant de passer à l'étape 2.
Copiez les fichiers sur votre serveur d'hébergement de fichiers statiques, afin qu'ils soient accessibles à partir des chemins suivants : https://yourdomain.com/sw.js
et https://yourdomain.com/workbox-*.js
.
Un exemple consiste à utiliser le service d'hébergement Firebase pour héberger ces fichiers de manière statique. Vous pouvez automatiser l'étape de copie à l'aide de scripts dans votre flux de travail de déploiement.
Pour des raisons de sécurité, vous devez héberger ces fichiers directement depuis votre domaine. Si le contenu est livré à l'aide d'une redirection, le navigateur refusera d'exécuter le service worker.
Lorsqu'une requête HTTP est reçue, testez si ces fichiers sont demandés, puis renvoyez ces fichiers statiques.
Exemple de server.js
const { createServer } = require ( 'http' )
const { join } = require ( 'path' )
const { parse } = require ( 'url' )
const next = require ( 'next' )
const app = next ( { dev : process . env . NODE_ENV !== 'production' } )
const handle = app . getRequestHandler ( )
app . prepare ( ) . then ( ( ) => {
createServer ( ( req , res ) => {
const parsedUrl = parse ( req . url , true )
const { pathname } = parsedUrl
if ( pathname === '/sw.js' || / ^/(workbox|worker|fallback)-w+.js$ / . test ( pathname ) ) {
const filePath = join ( __dirname , '.next' , pathname )
app . serveStatic ( req , res , filePath )
} else {
handle ( req , res , parsedUrl )
}
} ) . listen ( 3000 , ( ) => {
console . log ( `> Ready on http://localhost: ${ 3000 } ` )
} )
} )
La configuration suivante n'a rien à voir avec le plugin
next-pwa
, et vous les avez probablement déjà configurés. Sinon, allez-y et configurez-les.
Créez un fichier manifest.json
dans votre dossier public
:
{
"name" : " PWA App " ,
"short_name" : " App " ,
"icons" : [
{
"src" : " /icons/android-chrome-192x192.png " ,
"sizes" : " 192x192 " ,
"type" : " image/png " ,
"purpose" : " any maskable "
},
{
"src" : " /icons/android-chrome-384x384.png " ,
"sizes" : " 384x384 " ,
"type" : " image/png "
},
{
"src" : " /icons/icon-512x512.png " ,
"sizes" : " 512x512 " ,
"type" : " image/png "
}
],
"theme_color" : " #FFFFFF " ,
"background_color" : " #FFFFFF " ,
"start_url" : " / " ,
"display" : " standalone " ,
"orientation" : " portrait "
}
Ajoutez ce qui suit dans _document.jsx
ou _app.tsx
, dans :
< meta name =" application-name " content =" PWA App " />
< meta name =" apple-mobile-web-app-capable " content =" yes " />
< meta name =" apple-mobile-web-app-status-bar-style " content =" default " />
< meta name =" apple-mobile-web-app-title " content =" PWA App " />
< meta name =" description " content =" Best PWA App in the world " />
< meta name =" format-detection " content =" telephone=no " />
< meta name =" mobile-web-app-capable " content =" yes " />
< meta name =" msapplication-config " content =" /icons/browserconfig.xml " />
< meta name =" msapplication-TileColor " content =" #2B5797 " />
< meta name =" msapplication-tap-highlight " content =" no " />
< meta name =" theme-color " content =" #000000 " />
< link rel =" apple-touch-icon " href =" /icons/touch-icon-iphone.png " />
< link rel =" apple-touch-icon " sizes =" 152x152 " href =" /icons/touch-icon-ipad.png " />
< link rel =" apple-touch-icon " sizes =" 180x180 " href =" /icons/touch-icon-iphone-retina.png " />
< link rel =" apple-touch-icon " sizes =" 167x167 " href =" /icons/touch-icon-ipad-retina.png " />
< link rel =" icon " type =" image/png " sizes =" 32x32 " href =" /icons/favicon-32x32.png " />
< link rel =" icon " type =" image/png " sizes =" 16x16 " href =" /icons/favicon-16x16.png " />
< link rel =" manifest " href =" /manifest.json " />
< link rel =" mask-icon " href =" /icons/safari-pinned-tab.svg " color =" #5bbad5 " />
< link rel =" shortcut icon " href =" /favicon.ico " />
< link rel =" stylesheet " href =" https://fonts.googleapis.com/css?family=Roboto:300,400,500 " />
< meta name =" twitter:card " content =" summary " />
< meta name =" twitter:url " content =" https://yourdomain.com " />
< meta name =" twitter:title " content =" PWA App " />
< meta name =" twitter:description " content =" Best PWA App in the world " />
< meta name =" twitter:image " content =" https://yourdomain.com/icons/android-chrome-192x192.png " />
< meta name =" twitter:creator " content =" @DavidWShadow " />
< meta property =" og:type " content =" website " />
< meta property =" og:title " content =" PWA App " />
< meta property =" og:description " content =" Best PWA App in the world " />
< meta property =" og:site_name " content =" PWA App " />
< meta property =" og:url " content =" https://yourdomain.com " />
< meta property =" og:image " content =" https://yourdomain.com/icons/apple-touch-icon.png " />
Astuce : placez la balise méta de la tête
viewport
dans_app.js
plutôt que dans_document.js
si vous en avez besoin.
< meta
name = 'viewport'
content = 'minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover'
/ >
Les solutions de secours hors ligne sont utiles lorsque la récupération échoue à la fois depuis le cache et le réseau, une ressource pré-mise en cache est servie au lieu de présenter une erreur du navigateur.
Pour commencer, ajoutez simplement une page /_offline
telle que pages/_offline.js
ou pages/_offline.jsx
ou pages/_offline.ts
ou pages/_offline.tsx
. Alors vous êtes prêt ! Lorsque l'utilisateur est hors ligne, toutes les pages qui ne sont pas mises en cache reviendront à «/_offline».
Utilisez cet exemple pour le voir en action
next-pwa
vous aide à pré-cacher ces ressources lors du premier chargement, puis à injecter un gestionnaire de secours au plugin handlerDidError
dans toutes les configurations runtimeCaching
, afin que les ressources pré-cachées soient servies en cas d'échec de la récupération.
Vous pouvez également configurer precacheFallback.fallbackURL
dans votre entrée de configuration runtimeCaching pour implémenter des fonctionnalités similaires. La différence est que la méthode ci-dessus est basée sur le type de ressource, cette méthode est basée sur un modèle d'URL correspondant. Si cette configuration est définie dans l'entrée de configuration runtimeCaching, le repli basé sur le type de ressource sera automatiquement désactivé pour ce modèle d'URL particulier afin d'éviter les conflits.
Il existe des options que vous pouvez utiliser pour personnaliser le comportement de ce plugin en ajoutant un objet pwa
dans la configuration suivante dans next.config.js
:
const withPWA = require ( 'next-pwa' ) ( {
dest : 'public'
// disable: process.env.NODE_ENV === 'development',
// register: true,
// scope: '/app',
// sw: 'service-worker.js',
//...
} )
module . exports = withPWA ( {
// next.js config
} )
false
disable: false
, afin qu'il génère un service Worker à la fois dev
et prod
disable: true
pour désactiver complètement PWAdev
, vous pouvez définir disable: process.env.NODE_ENV === 'development'
true
false
lorsque vous souhaitez gérer vous-même le travailleur de service d'enregistrement, cela peut être fait dans componentDidMount
de votre application racine. vous pouvez considérer le register.js comme exemple.basePath
dans next.config.js
ou /
/app
afin que le chemin sous /app
soit PWA alors que les autres ne le sont pas/sw.js
public
de la mise en cache.['!noprecache/**/*']
- cela signifie que le comportement par défaut mettra en cache tous les fichiers de votre dossier public
, à l'exception des fichiers du dossier /public/noprecache
. Vous pouvez simplement placer les fichiers dans ce dossier pour ne pas les mettre en cache sans configurer cela.['!img/super-large-image.jpg', '!fonts/not-used-fonts.otf']
.next/static
(ou votre build personnalisé)[]
[/chunks/images/.*$/]
- Ne pré-mettez pas en cache les fichiers sous .next/static/chunks/images
(je le recommande vivement pour fonctionner avec le plugin next-optimized-images
)true
true
cacheStartUrl
est défini sur true
/login
, il est recommandé de configurer cette URL redirigée pour la meilleure expérience utilisateur.undefined
dynamicStartUrlRedirect
est défini sur true
/_offline
telle que pages/_offline.js
et vous êtes prêt, aucune configuration n'est nécessaireobject
fallbacks.document
- route de secours pour le document (page), par défaut /_offline
si vous avez créé cette pagefallbacks.image
- itinéraire de secours pour l'image, par défaut aucunfallbacks.audio
- itinéraire de secours pour l'audio, par défaut aucunfallbacks.video
- itinéraire de secours pour la vidéo, par défaut aucunfallbacks.font
- itinéraire de secours pour la police, par défaut aucunnext/link
sur le front-end. Consultez cet exemple pour obtenir un aperçu des raisons pour lesquelles cela est implémenté.false
""
- c'est-à-dire par défaut sans préfixe/subdomain
si l'application est hébergée sur example.com/subdomain
location.reload()
pour actualiser l'application.true
next-pwa
recherche une implémentation de travailleur personnalisé à ajouter au service worker généré par workbox. Pour plus d’informations, consultez l’exemple du travailleur personnalisé.worker
next-pwa
utilise workbox-webpack-plugin
, d'autres options qui pourraient également être placées dans l'objet pwa
peuvent être trouvées SUR LA DOCUMENTATION pour GenerateSW et InjectManifest. Si vous spécifiez swSrc
, le plugin InjectManifest
sera utilisé, sinon GenerateSW
sera utilisé pour générer un service worker.
next-pwa
utilise un cache.js d'exécution par défaut
Il est fort probable que vous souhaitiez personnaliser vos propres règles de mise en cache d'exécution. N'hésitez pas à copier le fichier cache.js
par défaut et à personnaliser les règles à votre guise. N'oubliez pas d'injecter les configurations dans votre configuration pwa
dans next.config.js
.
Voici le document expliquant comment écrire des configurations de mise en cache d'exécution, y compris les fonctionnalités de synchronisation en arrière-plan et de mise à jour de diffusion et bien plus encore !
{command: 'doSomething', message: ''}
lorsque postMessage
au service worker. De sorte que sur l'auditeur, il pourrait effectuer plusieurs tâches différentes en utilisant if...else...
.clean application cache
pour réduire certaines erreurs irrégulières.runtimeCaching
par exemple options.cacheableResponse.statuses=[200,302]
.sw.js
généré pour comprendre ce qui se passe réellement.next-pwa
à générer la version de production de la boîte de travail en spécifiant l'option mode: 'production'
dans votre section pwa
de next.config.js
. Bien que next-pwa
génère automatiquement la version de développement de la boîte de travail pendant le développement (en exécutant next
) et la version de production de la boîte de travail pendant la production (en exécutant next build
et next start
). Vous souhaiterez peut-être toujours le forcer à passer en production, même pendant le développement de votre application Web, pour la raison suivante :self.__WB_DISABLE_DEV_LOGS = true
dans votre worker/index.js
(créez-en un si vous n'en avez pas).userAgent
pour déterminer si les utilisateurs utilisent Safari/iOS/MacOS ou une autre plate-forme, la bibliothèque ua-parser-js est un bon ami à cette fin. MIT