UNPKG

@serwist/next

Version:

A module that integrates Serwist into your Next.js application.

89 lines (85 loc) 2.91 kB
import { jsx } from 'react/jsx-runtime'; import { Serwist } from '@serwist/window'; import { isCurrentPageOutOfScope } from '@serwist/window/internal'; import { createContext, useContext, useState, useEffect } from 'react'; const SerwistContext = createContext(null); const useSerwist = ()=>{ const context = useContext(SerwistContext); if (!context) { throw new Error("[useSerwist]: 'SerwistContext' is not available."); } return context; }; function SerwistProvider({ swUrl, disable = false, register = true, cacheOnNavigation = true, reloadOnOnline = true, options, children }) { const [serwist] = useState(()=>{ if (typeof window === "undefined") return null; if (disable) return null; const scope = options?.scope || "/"; if (!(window.serwist && window.serwist instanceof Serwist) && "serviceWorker" in navigator) { window.serwist = new Serwist(swUrl, { ...options, scope, type: options?.type || "module" }); if (register && !isCurrentPageOutOfScope(scope)) { void window.serwist.register(); } } return window.serwist ?? null; }); useEffect(()=>{ const cacheUrls = async (url)=>{ if (!window.navigator.onLine || !url) { return; } serwist?.messageSW({ type: "CACHE_URLS", payload: { urlsToCache: [ url ] } }); }; const cacheCurrentPathname = ()=>cacheUrls(window.location.pathname); const pushState = history.pushState; const replaceState = history.replaceState; if (cacheOnNavigation) { history.pushState = (...args)=>{ pushState.apply(history, args); cacheUrls(args[2]); }; history.replaceState = (...args)=>{ replaceState.apply(history, args); cacheUrls(args[2]); }; window.addEventListener("online", cacheCurrentPathname); } return ()=>{ history.pushState = pushState; history.replaceState = replaceState; window.removeEventListener("online", cacheCurrentPathname); }; }, [ serwist?.messageSW, cacheOnNavigation ]); useEffect(()=>{ const reload = ()=>location.reload(); if (reloadOnOnline) { window.addEventListener("online", reload); } return ()=>{ window.removeEventListener("online", reload); }; }, [ reloadOnOnline ]); return jsx(SerwistContext.Provider, { value: { serwist }, children: children }); } export { SerwistProvider, useSerwist };