π²Progressive Web Apps (PWA)
Zero Config PWA Plugin for Next.js. This plugin is powered by workbox and other good stuff.
Features
Zero config for registering and generating a service worker
Optimized precache and runtime cache
Maximize lighthouse score
Easy to understand examples
Completely offline support
Use workbox and workbox-window v6
Work with cookies out of the box
No custom server needed for Next.js 9+
Handle PWA lifecycle events opt-in
Custom worker to run extra code in service worker with code splitting
Debug service worker with confidence in development mode without caching
Internationalization (a.k.a I18N) with
next-i18nextConfigurable by the same workbox configuration options for GenerateSW and InjectManifest
Spin up a GitPod and try out examples in rocket speed
(Experimental) precaching
.module.jswhennext.config.jshasexperimental.modernset totrue
How to use
Thanks to Next.js 9+, we can use the public folder to serve static files from the root / URL path. It cuts the need to write custom server only to serve those files. Therefore the setup is easier and concise. We can use next.config.js to config next-pwa to generates service worker and workbox files into the public folder.
Step 1: Install library
yarn add next-pwaStep 2: withPWA
Update or create next.config.js with
const withPWA = require('next-pwa')
module.exports = withPWA({
pwa: {
disable: process.env.NODE_ENV === 'development',
register: true,
scope: '/app',
sw: 'service-worker.js',
dest: 'public'
}
})Available Options
disable: boolean - whether to disable pwa feature as a whole
default to
falseset
disable: false, so that it will generate service worker in bothdevandprodset
disable: trueto completely disable PWAif you don't need to debug service worker in
dev, you can setdisable: process.env.NODE_ENV === 'development'
register: boolean - whether to let this plugin register service worker for you
default to
trueset to
falsewhen you want to handle register service worker yourself, this could be done incomponentDidMountof your root app. you can consider the register.js as an example.
scope: string - url scope for pwa
default to
/set to
/appso that path under/appwill be PWA while others are not
sw: string - service worker script file name
default to
/sw.jsset to another file name if you want to customize the output file name
runtimeCaching - caching strategies (array or callback function)
default: see the Runtime Caching section for the default configuration
accepts an array of cache entry objects, please follow the structure here
Note: the order of the array matters. The first rule that matches is effective. Therefore, please ALWAYS put rules with larger scope behind the rules with a smaller and specific scope.
publicExcludes - an array of glob pattern strings to exclude files in the
publicfolder from being precached.default:
[]- this means that the default behavior will precache all the files inside yourpublicfolderexample:
['!img/super-large-image.jpg', '!fonts/not-used-fonts.otf']
buildExcludes - an array of extra pattern or function to exclude files from being precached in
.next/static(or your custom build) folderdefault:
[]example:
[/chunks\/images\/.*$/]- Don't precache files under.next/static/chunks/images(Highly recommend this to work withnext-optimized-imagesplugin)doc: Array of (string, RegExp, or function()). One or more specifiers used to exclude assets from the precache manifest. This is interpreted following the same rules as Webpack's standard exclude option.
subdomainPrefix: string - url prefix to allow hosting static files on a subdomain
default:
""- i.e. default with no prefixexample:
/subdomainif the app is hosted onexample.com/subdomain
Step 3: Add Manifest File
Create a manifest.json file in your public folder:
{
"name": "Next Boilerplate",
"short_name": "Next Boilerplate",
"theme_color": "#F04B32",
"background_color": "#F04B32",
"display": "fullscreen",
"orientation": "portrait",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "img/logo/manifest/logo-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "img/logo/manifest/logo-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"splash_pages": null
}Step 4: Add Head Meta
Add the following into _document.jsx or _app.tsx, in <Head>:
<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' />
<!-- apple splash screen images -->
<!--
<link rel='apple-touch-startup-image' href='/images/apple_splash_2048.png' sizes='2048x2732' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_1668.png' sizes='1668x2224' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_1536.png' sizes='1536x2048' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_1125.png' sizes='1125x2436' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_1242.png' sizes='1242x2208' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_750.png' sizes='750x1334' />
<link rel='apple-touch-startup-image' href='/images/apple_splash_640.png' sizes='640x1136' />
--><meta name='viewport' content='minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover' />Last updated
Was this helpful?