Este complemento funciona con Workbox y otras cosas buenas.
Comparte tu increíble proyecto PWA aquí
Características
next-i18next
blitz.config.js
).module.js
cuando next.config.js
tiene experimental.modern
configurado en true
NOTA 1 : la versión 2.0.0+
next-pwa
solo debería funcionar connext.js
9.1+, y los archivos estáticos solo deberían entregarse a través del directoriopublic
. Esto simplificará las cosas.NOTA 2 : si encuentra el error
TypeError: Cannot read property **'javascript' of undefined**
durante la compilación, considere actualizar a webpack5 ennext.config.js
.
Si es nuevo en
next.js
oreact.js
, es posible que desee consultar primero el documento next.js o next.js. Luego comience con un ejemplo simple o un ejemplo de aplicación web progresiva en el repositorio next.js.
yarn add next-pwa
Actualice o cree next.config.js
con
const withPWA = require ( 'next-pwa' ) ( {
dest : 'public'
} )
module . exports = withPWA ( {
// next.js config
} )
Después de ejecutar next build
, esto generará dos archivos en su public
: workbox-*.js
y sw.js
, que se entregarán automáticamente de forma estática.
Si está utilizando Next.js versión 9 o posterior, omita las opciones siguientes y continúe con el Paso 2.
Si está utilizando Next.js anterior a la versión 9, deberá elegir una de las siguientes opciones antes de continuar con el Paso 2.
Copie los archivos a su servidor de alojamiento de archivos estáticos, para que sean accesibles desde las siguientes rutas: https://yourdomain.com/sw.js
y https://yourdomain.com/workbox-*.js
.
Un ejemplo es el uso del servicio de alojamiento Firebase para alojar esos archivos de forma estática. Puede automatizar el paso de copia utilizando scripts en su flujo de trabajo de implementación.
Por razones de seguridad, debes alojar estos archivos directamente desde tu dominio. Si el contenido se entrega mediante una redirección, el navegador se negará a ejecutar el trabajador del servicio.
Cuando se reciba una solicitud HTTP, pruebe si se solicitan esos archivos y luego devuelva esos archivos estáticos.
Ejemplo 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 siguiente configuración no tiene nada que ver con el complemento
next-pwa
y probablemente ya los haya configurado. Si no, continúa y configúralos.
Cree un archivo manifest.json
en su carpeta 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 "
}
Agregue lo siguiente en _document.jsx
o _app.tsx
, en :
< 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 " />
Consejo: coloque la metaetiqueta del encabezado de
viewport
en_app.js
en lugar de_document.js
si la necesita.
< meta
name = 'viewport'
content = 'minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover'
/ >
Las alternativas sin conexión son útiles cuando la recuperación falla tanto desde el caché como desde la red, se sirve un recurso almacenado previamente en el caché en lugar de presentar un error desde el navegador.
Para comenzar, simplemente agregue una página /_offline
como pages/_offline.js
o pages/_offline.jsx
o pages/_offline.ts
o pages/_offline.tsx
. ¡Entonces ya está todo listo! Cuando el usuario está desconectado, todas las páginas que no están almacenadas en caché volverán a '/_offline'.
Utilice este ejemplo para verlo en acción.
next-pwa
le ayuda a almacenar en caché esos recursos en la primera carga, luego inyectar un controlador alternativo al complemento handlerDidError
en todas las configuraciones runtimeCaching
, de modo que los recursos almacenados en caché se entreguen cuando falle la recuperación.
También puede configurar precacheFallback.fallbackURL
en su entrada de configuración de runtimeCaching para implementar una funcionalidad similar. La diferencia es que el método anterior se basa en el tipo de recurso, este método se basa en un patrón de URL coincidente. Si esta configuración se establece en la entrada de configuración de runtimeCaching, el respaldo basado en el tipo de recurso se deshabilitará automáticamente para este patrón de URL en particular para evitar conflictos.
Hay opciones que puede usar para personalizar el comportamiento de este complemento agregando el objeto pwa
en la siguiente configuración en 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
para que genere un trabajador de servicio tanto en dev
como en prod
disable: true
para deshabilitar completamente PWAdev
, puede configurar disable: process.env.NODE_ENV === 'development'
true
false
cuando desee manejar el registro del trabajador del servicio usted mismo, esto se puede hacer en componentDidMount
de su aplicación raíz. puedes considerar el registro.js como ejemplo.basePath
en next.config.js
o /
/app
para que la ruta en /app
sea PWA mientras que otras no lo sean/sw.js
public
del almacenamiento en caché previo.['!noprecache/**/*']
- esto significa que el comportamiento predeterminado almacenará en caché todos los archivos dentro de su carpeta public
excepto los archivos dentro de la carpeta /public/noprecache
. Simplemente puede colocar archivos dentro de esa carpeta para no almacenarlos en caché sin configurar esto.['!img/super-large-image.jpg', '!fonts/not-used-fonts.otf']
.next/static
(o su compilación personalizada)[]
[/chunks/images/.*$/]
- No almacene en caché los archivos en .next/static/chunks/images
(recomiendo esto para trabajar con el complemento next-optimized-images
)true
true
cacheStartUrl
se establece en true
/login
, se recomienda configurar esta URL redirigida para obtener la mejor experiencia de usuario.undefined
dynamicStartUrlRedirect
se establece en true
/_offline
como pages/_offline.js
y estará listo, no es necesaria ninguna configuración.object
fallbacks.document
: ruta alternativa para el documento (página), por defecto /_offline
si creó esa páginafallbacks.image
: ruta alternativa para la imagen, por defecto ningunafallbacks.audio
: ruta alternativa para audio, por defecto ningunafallbacks.video
: ruta alternativa para vídeo, por defecto ningunafallbacks.font
: ruta alternativa para la fuente, por defecto ningunanext/link
en la interfaz. Consulte este ejemplo para conocer el contexto sobre por qué se implementa esto.false
""
- es decir, predeterminado sin prefijo/subdomain
si la aplicación está alojada en example.com/subdomain
location.reload()
para actualizar la aplicación.true
next-pwa
busca una implementación de trabajador personalizado para agregar al trabajador de servicio generado por workbox. Para obtener más información, consulte el ejemplo del trabajador personalizado.worker
next-pwa
usa workbox-webpack-plugin
, otras opciones que también podrían incluirse en el objeto pwa
se pueden encontrar EN LA DOCUMENTACIÓN para GenerateSW e InjectManifest. Si especifica swSrc
, se utilizará el complemento InjectManifest
; de lo contrario, se utilizará GenerateSW
para generar el trabajador del servicio.
next-pwa
usa un caché.js de tiempo de ejecución predeterminado
Existe una gran posibilidad de que desee personalizar sus propias reglas de almacenamiento en caché en tiempo de ejecución. No dude en copiar el archivo cache.js
predeterminado y personalizar las reglas como desee. No olvide inyectar las configuraciones en su configuración pwa
en next.config.js
.
Aquí está el documento sobre cómo escribir configuraciones de almacenamiento en caché en tiempo de ejecución, incluidas las funciones de sincronización en segundo plano y actualización de transmisión, ¡y más!
{command: 'doSomething', message: ''}
objeto cuando postMessage
al trabajador del servicio. De modo que en el oyente, podría realizar múltiples tareas diferentes usando if...else...
.clean application cache
para reducir algunos errores poco frecuentes.runtimeCaching
como options.cacheableResponse.statuses=[200,302]
.sw.js
generado para descubrir qué está pasando realmente.next-pwa
a generar la compilación de producción de la caja de trabajo especificando la opción mode: 'production'
en la sección pwa
de next.config.js
. Aunque next-pwa
genera automáticamente la compilación de desarrollo de la caja de trabajo durante el desarrollo (ejecutando next
) y la compilación de producción de la caja de trabajo durante la producción (ejecutando next build
y next start
). Es posible que aún quieras forzar la compilación en producción incluso durante el desarrollo de tu aplicación web por el siguiente motivo:self.__WB_DISABLE_DEV_LOGS = true
en su worker/index.js
(cree uno si no tiene uno).userAgent
para determinar si los usuarios están usando Safari/iOS/MacOS o alguna otra plataforma, la biblioteca ua-parser-js es una buena amiga para ese propósito. MIT