I've been using next-pwa
(npm link) to automate the service-worker setup stuff for setting up a PWA in NextJS. For the most part, everything has been going fine. However, I cannot for the life of me figure out how to solve the one error (shown below) still appearing in the lighthouse audit. I've read a good amount of posts and tried to implement several different solutions but so far no dice.
Here is the sw.js
that is automatically created by NextJS
.
// sw.js
if (!self.define) {
const e = e => {
'require' !== e && (e += '.js');
let n = Promise.resolve();
return (
i[e] ||
(n = new Promise(async n => {
if ('document' in self) {
const i = document.createElement('script');
(i.src = e), document.head.appendChild(i), (i.onload = n);
} else importScripts(e), n();
})),
n.then(() => {
if (!i[e]) throw new Error(`Module ${e} didn’t register its module`);
return i[e];
})
);
},
n = (n, i) => {
Promise.all(n.map(e)).then(e => i(1 === e.length ? e[0] : e));
},
i = { require: Promise.resolve(n) };
self.define = (n, s, c) => {
i[n] ||
(i[n] = Promise.resolve().then(() => {
let i = {};
const r = { uri: location.origin + n.slice(1) };
return Promise.all(
s.map(n => {
switch (n) {
case 'exports':
return i;
case 'module':
return r;
default:
return e(n);
}
})
).then(e => {
const n = c(...e);
return i.default || (i.default = n), i;
});
}));
};
}
define('./sw.js', ['./workbox-1ca495a9'], function(e) {
'use strict';
importScripts(),
self.skipWaiting(),
e.clientsClaim(),
e.precacheAndRoute(
[
{
url: '/_next/static/Bf0fOQ5vTfsmLElkL5uPJ/_buildManifest.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/Bf0fOQ5vTfsmLElkL5uPJ/_ssgManifest.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/224-5da05219d75f4eb1a9e2.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/580-2d0b17ccc09c231c1f63.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/597-27159eb1f0ff7f4322bb.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/framework-40503bb0b87dcc30c2dc.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/main-f0954d00fdee968e0986.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/pages/_app-f80cf1ab407b29886a1c.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/pages/_error-8470b41bc6cfedf1d350.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/pages/index-e03b34c1331d21cd05ac.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/polyfills-3d2c0f0875171918a758.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/_next/static/chunks/webpack-fb3a8e0c92f7e9ed77fb.js',
revision: 'Bf0fOQ5vTfsmLElkL5uPJ'
},
{
url: '/browserconfig.xml',
revision: '653d077300a12f09a69caeea7a8947f8'
},
{ url: '/favicon.ico', revision: '21b739d43fcb9bbb83d8541fe4fe88fa' },
{
url: '/icons/android-icon-144x144.png',
revision: 'ba231a435173f4830fe422263f5dd3eb'
},
{
url: '/icons/android-icon-192x192.png',
revision: '93bde9a252c9a48d377f60dfa88b25e2'
},
{
url: '/icons/android-icon-36x36.png',
revision: '60cbd3297c42a432069c7f5e9d640c12'
},
{
url: '/icons/android-icon-48x48.png',
revision: '4b898d6d22adce8db36ede1b8c811f1b'
},
{
url: '/icons/android-icon-512x512.png',
revision: '6a8a40c983dbc0bc42a97b9e4cda77a6'
},
{
url: '/icons/android-icon-72x72.png',
revision: '3d1f4c9b46b285fa6cb2c587ea2334e0'
},
{
url: '/icons/android-icon-96x96.png',
revision: '5f522065b076d980b50278fecf7c0f34'
},
{
url: '/icons/apple-icon-114x114.png',
revision: 'ca65289710709e327077cf035bade9e0'
},
{
url: '/icons/apple-icon-120x120.png',
revision: '478371dd294735fa2d579d0c027442be'
},
{
url: '/icons/apple-icon-144x144.png',
revision: 'ba231a435173f4830fe422263f5dd3eb'
},
{
url: '/icons/apple-icon-152x152.png',
revision: 'c7c7e34b1d917f17a4132eb253262424'
},
{
url: '/icons/apple-icon-180x180.png',
revision: '117fea2a93944d8ecab1797de5bbe301'
},
{
url: '/icons/apple-icon-512x512.png',
revision: '6a8a40c983dbc0bc42a97b9e4cda77a6'
},
{
url: '/icons/apple-icon-57x57.png',
revision: '5c0a5653d999f01b12ba2a2c1343a664'
},
{
url: '/icons/apple-icon-60x60.png',
revision: '6ee47df922e9336918c9266c651fbb11'
},
{
url: '/icons/apple-icon-72x72.png',
revision: '3d1f4c9b46b285fa6cb2c587ea2334e0'
},
{
url: '/icons/apple-icon-76x76.png',
revision: 'f7e6c5d5649be3dac2479043e0c3c05f'
},
{
url: '/icons/apple-icon-precomposed.png',
revision: '528eff11ef1a3f9094763b37bb9ef69e'
},
{
url: '/icons/apple-icon.png',
revision: '528eff11ef1a3f9094763b37bb9ef69e'
},
{
url: '/icons/favicon-16x16.png',
revision: 'e90dc768aad2517760a068c794a8e7da'
},
{
url: '/icons/favicon-32x32.png',
revision: '2804f09f47660e4593b8f05f1007973f'
},
{
url: '/icons/favicon-96x96.png',
revision: '5f522065b076d980b50278fecf7c0f34'
},
{
url: '/icons/maskable_icon_x1.png',
revision: 'cab51d5ebecc0e119828c83518472714'
},
{
url: '/icons/ms-icon-144x144.png',
revision: 'ba231a435173f4830fe422263f5dd3eb'
},
{
url: '/icons/ms-icon-150x150.png',
revision: 'f0b0f7361d893e945de9e383b898b485'
},
{
url: '/icons/ms-icon-310x310.png',
revision: 'f3258e3670d0eb63ba56fb40ad30386c'
},
{
url: '/icons/ms-icon-512x512.png',
revision: '6a8a40c983dbc0bc42a97b9e4cda77a6'
},
{
url: '/icons/ms-icon-70x70.png',
revision: '7a04d01451acba7481bd3ddfadb7255d'
},
{ url: '/manifest.json', revision: '973196764f3f071b66c8f53b18a0eda3' },
{ url: '/vercel.svg', revision: '4b4f1876502eb6721764637fe5c41702' }
],
{ ignoreURLParametersMatching: [] }
),
e.cleanupOutdatedCaches(),
e.registerRoute(
'/',
new e.NetworkFirst({
cacheName: 'start-url',
plugins: [
new e.ExpirationPlugin({
maxEntries: 1,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/^https:\/\/fonts\.(?:googleapis|gstatic)\.com\/.*/i,
new e.CacheFirst({
cacheName: 'google-fonts',
plugins: [
new e.ExpirationPlugin({
maxEntries: 4,
maxAgeSeconds: 31536e3,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
new e.StaleWhileRevalidate({
cacheName: 'static-font-assets',
plugins: [
new e.ExpirationPlugin({
maxEntries: 4,
maxAgeSeconds: 604800,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
new e.StaleWhileRevalidate({
cacheName: 'static-image-assets',
plugins: [
new e.ExpirationPlugin({
maxEntries: 64,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\.(?:js)$/i,
new e.StaleWhileRevalidate({
cacheName: 'static-js-assets',
plugins: [
new e.ExpirationPlugin({
maxEntries: 32,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\.(?:css|less)$/i,
new e.StaleWhileRevalidate({
cacheName: 'static-style-assets',
plugins: [
new e.ExpirationPlugin({
maxEntries: 32,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\.(?:json|xml|csv)$/i,
new e.NetworkFirst({
cacheName: 'static-data-assets',
plugins: [
new e.ExpirationPlugin({
maxEntries: 32,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/\/api\/.*$/i,
new e.NetworkFirst({
cacheName: 'apis',
networkTimeoutSeconds: 10,
plugins: [
new e.ExpirationPlugin({
maxEntries: 16,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
),
e.registerRoute(
/.*/i,
new e.NetworkFirst({
cacheName: 'others',
networkTimeoutSeconds: 10,
plugins: [
new e.ExpirationPlugin({
maxEntries: 32,
maxAgeSeconds: 86400,
purgeOnQuotaError: !0
})
]
}),
'GET'
);
});
Here is the next.config.js
const withPWA = require('next-pwa');
module.exports = withPWA({
disable: process.env.NODE_ENV === 'development',
register: true,
sw: '/sw.js',
future: { webpack5: true },
distDir: '/.next',
pwa: {
dest: 'public'
}
});
and my public/manifest.json
{
"name": "Parakeat Language Learning",
"short_name": "Parakeat",
"icons": [
{
"src": "icons/android-icon-36x36.png",
"sizes": "36x36",
"type": "image/png",
"density": "0.75"
},
{
"src": "icons/android-icon-48x48.png",
"sizes": "48x48",
"type": "image/png",
"density": "1.0"
},
{
"src": "icons/android-icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"density": "1.5"
},
{
"src": "icons/android-icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"density": "2.0"
},
{
"src": "icons/android-icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"density": "3.0"
},
{
"src": "icons/android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"density": "4.0"
},
{
"src": "icons/android-icon-512x512.png",
"sizes": "512x512",
"type": "image/png",
"density": "4.0"
},
{
"src": "icons/maskable_icon_x1.png",
"sizes": "196x196",
"type": "image/png",
"purpose": "any maskable"
}
],
"start_url": "/",
"scope": "",
"orientation": "portrait",
"display": "standalone",
"theme_color": "#002",
"background_color": "#ffffff"
}
I'm pretty much out of ideas, I've been reading through the next-pwa npm docs, the associated example file, and third-party resources, and for all of them it just seems to work, yet ... I'm having no such luck.
Lastly, the response when I deploy it (although it succeeds, maybe this is part of the issue?)
According to:
https://github.com/shadowwalker/next-pwa/issues/107
https://github.com/shadowwalker/next-pwa/issues/108
https://github.com/shadowwalker/next-pwa/issues/124
They think it is a bug with Lighthouse. It certainly seems to work correctly when I disable the network.