@serwist/next
Version:
A module that integrates Serwist into your Next.js application.
89 lines (85 loc) • 2.91 kB
JavaScript
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 };