• Stars
    star
    1,589
  • Rank 29,435 (Top 0.6 %)
  • Language
    JavaScript
  • Created almost 7 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

make your Next.js application work offline using service workers via Google's workbox

next-offline

Use Workbox with Next.js and
easily enable offline functionality in your application!


Installation

$ npm install --save next-offline
$ yarn add next-offline

Usage

There are two important things to set up, first we need next-offline to wrap your next config.

If you haven't yet, create a next.config.js in your project.

// next.config.js
const withOffline = require('next-offline')

const nextConfig = {
  ...
}

module.exports = withOffline(nextConfig)

Next we need to make sure our application is properly serving the service worker, this setup depends on how you're hosting your application. There is documentation below. If you're not using Now 2.0, the Now 1.0 example should work in most circumstances.

Documentation

Serving service worker

Because service workers are so powerful, the API has some restrictions built in. For example, service workers must be served on the domain they're being used on - you can't use a CDN.

Now 1.0

You'll want to use the next.js custom server API. The easiest way to do that is creating a server.js that looks like this:

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

      // handle GET request to /service-worker.js
      if (pathname === '/service-worker.js') {
        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}`)
    })
  })

You can read more about custom servers in the Next.js docs

If you're not hosting with Now, I'd probably follow the Now 1.0 approach because the custom server API can enable a lot of functionality, it just simply doesn't work well with Now 2.0 🙇‍♂️

Now 2.0

Because Now 2.0 works so different than the previous version, so does serving the service worker. There are a few different ways to do this, but I'd recommend checking out this now2 example app. The changes to be aware of are in the now.json and next.config.js.

Registering service worker

Compile-time registration

By default next-offline will register a service worker with the script below, this is automatically added to your client side bundle once withOffline is invoked.

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function () {
    navigator.serviceWorker.register('/service-worker.js', { scope: '/' }).then(function (registration) {
      console.log('SW registered: ', registration)
    }).catch(function (registrationError) {
      console.log('SW registration failed: ', registrationError)
    })
  })
}

Runtime registration

Alternative to compile-time, you can take control of registering/unregistering in your application code by using the next-offline/runtime module.

import { register, unregister } from 'next-offline/runtime'

class App extends React.Component {
  componentDidMount () {
    register()
  }
  componentWillUnmount () {
    unregister()
  }
  ..
}

You can choose to pass the service worker path and scope if needed.

import { register, unregister } from 'next-offline/runtime'

class App extends React.Component {
  componentDidMount () {
    /** 
      * Default service worker path is '/service-worker.js' 
      * Refer https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register for default scope rules
      *
    */
    register('/sub_folder/service-worker.js', {scope: '/sub_folder'}) 
  }
  componentWillUnmount () {
    unregister()
  }
  ..
}

If you're handling registration on your own, pass dontAutoRegisterSw to next-offline.

// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({ dontAutoRegisterSw: true })

Customizing service worker

Using workbox

If you're new to workbox, I'd recommend reading this quick guide -- anything inside of workboxOpts will be passed to workbox-webpack-plugin.

Define a workboxOpts object in your next.config.js and it will gets passed to workbox-webpack-plugin. Workbox is what next-offline uses under the hood to generate the service worker, you can learn more about it here.

// next.config.js
const withOffline = require('next-offline')

const nextConfig = {
  workboxOpts: {
    ...
  }
}

module.exports = withOffline(nextConfig)

next-offline options

On top of the workbox options, next-offline has some options built in flags to give you finer grain control over how your service worker gets generated.

Name Type Description Default
generateSw Boolean If false, next-offline will not generate a service worker and will instead try to modify the file found in workboxOpts.swSrc using WorkBox's [Inject Plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin#injectmanifest_plugin) true
dontAutoRegisterSw Boolean If true, next-offline won't automatically push the registration script into the application code. This is required if you're using runtime registration or are handling registration on your own. false
devSwSrc String Path to be registered by next-offline during development. By default next-offline will register a noop during development false
generateInDevMode Boolean If true, the service worker will also be generated in development mode. Otherwise the service worker defined in devSwSrc will be used. false
registerSwPrefix String If your service worker isn't at the root level of your application, this can help you prefix the path. This is useful if you'd like your service worker on foobar.com/my/long/path/service-worker.js. This affects the [scope](https://developers.google.com/web/ilt/pwa/introduction-to-service-worker#registration_and_scope) of your service worker. false
scope String This is passed to the automatically registered service worker allowing increase or decrease what the service worker has control of. "/"

Cache strategies

By default next-offline has the following blanket runtime caching strategy. If you customize next-offline with workboxOpts, the default behaviour will not be passed into workbox-webpack-plugin. This article is great at breaking down various different cache recipes.

{
  runtimeCaching: [
    {
      urlPattern: /^https?.*/,
      handler: 'NetworkFirst',
      options: {
        cacheName: 'offlineCache',
        expiration: {
          maxEntries: 200
        }
      }
    }
  ]
}
// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({
  workboxOpts: {
    runtimeCaching: [
      {
        urlPattern: /.png$/,
        handler: 'CacheFirst'
      },
      {
        urlPattern: /api/,
        handler: 'NetworkFirst',
        options: {
          cacheableResponse: {
            statuses: [0, 200],
            headers: {
              'x-test': 'true'
            }
          }
        }
      }
    ]
  }
})

Service worker path

If your application doesn't live on the root of your domain, you can use registerSwPrefix. This is helpful if your application is on domain.com/my/custom/path because by default next-offline assumes your application is on domain.com and will try to register domain.com/service-worker.js. We can't support using assetPrefix because service workers must be served on the root domain. For a technical breakdown on that limitation, see the following link: Is it possible to serve service workers from CDN/remote origin?

By default next-offline will precache all the Next.js webpack emitted files and the user-defined static ones (inside /static) - essentially everything that is exported as well.

If you'd like to include some more or change the origin of your static files use the given workbox options:

workboxOpts: {
  modifyURLPrefix: {
    'app': assetPrefix,
  },
  runtimeCaching: {...}
}

Development mode

By default next-offline will add a no-op service worker in development. If you want to provide your own pass its filepath to devSwSrc option. This is particularly useful if you want to test web push notifications in development, for example.

// next.config.js
const withOffline = require('next-offline')

module.exports = withOffline({
  devSwSrc: '/path/to/my/dev/service-worker.js'
})

You can disable this behavior by setting the generateInDevMode option to true.

next export

In [email protected] we've rewritten the export functionality to work in more cases, more reliably, with less code thanks to some of the additions in Next 7.0.0!

You can read more about exporting at Next.js docs but next offline should Just Work™️.

next offline 5.0

If you're upgrading to the latest version of next-offline I recommend glancing at what's been added/changed inside of Workbox in 5.x releases along with the 4.0 release which included the breaking changes. Next Offline's API hasn't changed, but a core dependency has!


Questions? Feedback? Please let me know

Contributing

next-offline is a lerna monorepo which uses yarn workspaces. After cloning the repo, run the following

$ yarn bootstrap

This will ensure your development version of next-offline is symlinked in the examples & tests which should allow you to quickly make changes!

License (MIT)

WWWWWW||WWWWWW
 W W W||W W W
      ||
    ( OO )__________
     /  |           \
    /o o|    MIT     \
    \___/||_||__||_|| *
         || ||  || ||
        _||_|| _||_||
       (__|__|(__|__|

Copyright © 2017-present Jack Hanford, [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

More Repositories

1

trends

ultra high performance github trending application
TypeScript
486
star
2

react-drag-drawer

A responsive mobile drawer that is draggable on mobile, and falls back to a modal on desktop
JavaScript
157
star
3

remark-slate

Remark plugin to compile Markdown as a slate 0.50+ compatible object.
TypeScript
153
star
4

chirp

🐦 A cross platform twitter application
JavaScript
126
star
5

facebook-data-parser

A node app for parsing facebook data and outputting pretty graphs
JavaScript
105
star
6

github-native

📱 mobile github client built with react-native
Objective-C
95
star
7

react-kanban

Beautiful Kanban implementation built on react-motion
JavaScript
42
star
8

await-exec

Small wrapper around node's child_process exec command, allowing it to easily be used with async/await
JavaScript
29
star
9

Instachrome

📸 Browse Instagram from anywhere
JavaScript
28
star
10

uber-chrome

🚗 Chrome extension allowing you to call an Uber from your desktop
JavaScript
22
star
11

bundle-cop

🚓 compare webpack stats between branches
JavaScript
20
star
12

Veneer

A simple chrome extension for writing custom CSS on all websites
JavaScript
17
star
13

defer-render-hoc

defer expensive react renders until the next two rAF's
JavaScript
16
star
14

personal-website

My personal website, it's also a PWA
TypeScript
16
star
15

angular-notify

A super tiny angular service with a easy API for using browser notifications.
JavaScript
15
star
16

react-fab-fan

Floating action button fan built with react and react-motion
JavaScript
14
star
17

next-static-manifest

Create a static page manifest of your Next.js exported html pages, allowing you to route to dynamic HTML pages
TypeScript
13
star
18

react-page-transition

drop in react page transition component
JavaScript
12
star
19

add-component

Generate a PureComponent or Functional Component, stylehseet and a test in one command
JavaScript
11
star
20

angular-vdom

angular .component() wrapper for virtual-dom components
JavaScript
10
star
21

use-loadable

React hook for knowing when an async function is loading or had an error
JavaScript
9
star
22

react-tooltip-portal

Small unopinionated react tooltip library that utilizes React 16's Portal API
JavaScript
9
star
23

angular-toast

Micro angular pop up library
HTML
8
star
24

render-react-from-cms

render react components that are intertwined in wysiwyg output
JavaScript
7
star
25

bi-directional-mfe

Webpack 5 Microfrontend, with Relay hooks and React Suspense
JavaScript
7
star
26

angular-phone-input

An easy to use directive for formatting / capturing phone numbers
HTML
6
star
27

react-flick-list

react bindings for kinetic scrolling
JavaScript
6
star
28

react-scroll-listen

efficiently save the scroll position of the document.body in React
JavaScript
6
star
29

cloudinary-export

streamingly export all images from cloudinary
JavaScript
5
star
30

simple-angular-dialog

Small library for creating dynamic modals with angularjs
JavaScript
5
star
31

await-wrap

use async/await without try/catch blocks
JavaScript
4
star
32

trends-sidebar

Chrome extension for trends.now.sh
JavaScript
4
star
33

animate

drop in, easy to use, natural looking animations with 0 config
JavaScript
4
star
34

website-performance

Gather common performance metrics from a website like Time To Interactive (TTI) and DOMContentLoaded
JavaScript
4
star
35

react-document-visibility

functional react component that re renders and informs children when the document is currently focussed or not
JavaScript
4
star
36

angular-sidebar

super small, mobile ready, vanilla angular sidebar component
JavaScript
4
star
37

pipe-fns

helper function enabling easy functional piping
JavaScript
3
star
38

now-playing

GraphQL + The movie database + Apollo & Next.js
JavaScript
3
star
39

pnpm-peer-deps

JavaScript
3
star
40

relay-swc-jest

TypeScript
3
star
41

mfe-poc

Simple project implementing a Module Federation Micro frontend
JavaScript
3
star
42

ci-github

easily comment on github commits / PR's from CircleCI or TravisCI
JavaScript
3
star
43

react-pinch-to-zoom

JavaScript
3
star
44

check-in

react native + yelp fusion API
JavaScript
3
star
45

sink

Store a local files/directories in iCloud drive ☁️
JavaScript
3
star
46

miniflare-shared-test-environment

Bug with r2_persist / jest-environment-miniflare
JavaScript
3
star
47

next-version-file

TypeScript
3
star
48

fast-flix

set playback speed of any HTML5 video on the internet
JavaScript
3
star
49

install-resolver

never guess whether a project is using yarn or npm again
JavaScript
3
star
50

credit-cards-react

Fork of react-credit-cards with css-in-js support
JavaScript
3
star
51

worker-rp-pages

TypeScript
3
star
52

remove-cors

Small Proxy for removing CORs headers
JavaScript
3
star
53

intersection-observer-image-grid

simple example using intersection-observer's in a react application
JavaScript
3
star
54

scrolltop-on-mount

react HOC that resets window scrollTop on mount
JavaScript
2
star
55

react-freeze-body

Declaratively apply overflow: hidden to the document.body
JavaScript
2
star
56

tinder-chrome

browse tinder from anywhere using this nifty chrome extension
JavaScript
2
star
57

react-zipcode

micro zipcode input with validation, mobile keypad keyboard built for react
JavaScript
2
star
58

apple-maps

small repo demonstrating how to recreate part of Apple maps native UI using web technology
JavaScript
2
star
59

array-dedupe

remove duplicated instances from an array by object key values
JavaScript
2
star
60

react-touchable-component

Touchable / draggable react component with an easy to use API
JavaScript
2
star
61

react-flexbox-helpers

Helper components for quickly using flexbox with React
JavaScript
2
star
62

preload-component

preload an array of image URL's the react way
JavaScript
2
star
63

add-deploy

generate circleci deployment scripts for now and heroku hosted node apps
JavaScript
2
star
64

request-callback

requestIdleCallback polyfill
JavaScript
2
star
65

bug-swcMinify-next-12.1.1

JavaScript
2
star
66

react-state-component

functional react component that exposes an additional external state to children
JavaScript
2
star
67

is-webapp

Detect if website was launched from mobile phone homescreen
JavaScript
2
star
68

relay-swc-monorepo

TypeScript
2
star
69

react-resize-width

Notify a component in react when the document.body is resized
JavaScript
2
star
70

relay-compiler-ci

TypeScript
2
star
71

many-workers

JavaScript
2
star
72

add-shallow

easily generate a shallow render test with one command
JavaScript
2
star
73

angular-disable-inflight

Angular directive for disabling elements while requests are in flight
JavaScript
2
star
74

next-on-pages-42

TypeScript
2
star
75

12.2-exports

JavaScript
2
star
76

react-image-loaded

Add a nice animation as soon as an image is loaded
JavaScript
2
star
77

required-parameter

require parameters when functions are invoked
JavaScript
2
star
78

react-github-badge

A 'Star on github' badge made for react
JavaScript
2
star
79

next-on-pages-32

TypeScript
2
star
80

many-relay-next

TypeScript
2
star
81

cacher

chrome extension for overwriting and adding permanent cache headers on all assets
JavaScript
2
star
82

url-constructor

A small library for dynamically matching urls with parameters
JavaScript
2
star
83

website-performance-hoc

react bindings for the website-performance NPM module
JavaScript
2
star
84

dot

setup / startup scripts for new computers / HDD's
Shell
2
star
85

twitter-popup

JavaScript
2
star
86

full-height-hoc

Loop over elements so a page can use flexbox height
JavaScript
2
star
87

storybook-deploy

JavaScript
2
star
88

react-flip-list

react <List /> component with FLIP animations built in
JavaScript
2
star
89

react-commit

lazily execute async functions on user initiated action
JavaScript
2
star
90

react-sherlock

react input with nlp superpowers
JavaScript
1
star
91

angular-sherlock

JavaScript
1
star
92

Bookmarker

A simple chrome extenstion to open all my bookmarks in the background.
JavaScript
1
star
93

angular-date-input

angular directive to streamline inputting dates
JavaScript
1
star
94

hanford.github.io

Home page
HTML
1
star
95

chrome-version

library for getting major chrome version from a user agent string
JavaScript
1
star
96

angular-faux-loader

Directive for displaying a loading message while data is coming in
JavaScript
1
star
97

angular-sticky-thead

JavaScript
1
star
98

angular-restrict-number

Directive for enforcing inpuit's ngModel is always a number
JavaScript
1
star
99

angular-maxlength

Small directive for _really_ enforcing maxlength
JavaScript
1
star
100

MobileGit-Server

JavaScript
1
star