diff --git a/apps/web/pages/_app.jsx b/apps/web/pages/_app.jsx index 3660ed9..f16c4ff 100644 --- a/apps/web/pages/_app.jsx +++ b/apps/web/pages/_app.jsx @@ -1,3 +1,4 @@ +/* eslint-disable no-console */ import '../styles/fonts.css'; import '../styles/globals.css'; import '../styles/antd-fix.css'; @@ -15,7 +16,7 @@ import { trpcClient } from '@/trpc/client'; import { ApolloProvider } from '@apollo/client'; import { QueryClientProvider } from '@tanstack/react-query'; import Head from 'next/head'; -import { useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { ThemeProvider } from 'styled-components'; import { Config as AntdConfig } from 'ui/elements'; @@ -32,6 +33,21 @@ function App({ Component, pageProps }) { const { loading } = usePageLoading(); + useEffect(() => { + if ('serviceWorker' in navigator) { + window.addEventListener('load', () => { + navigator.serviceWorker + .register('/service-worker.js') + .then((registration) => { + console.log('Service Worker registered:', registration); + }) + .catch((error) => { + console.error('Service Worker registration failed:', error); + }); + }); + } + }, []); + return ( diff --git a/apps/web/public/service-worker.js b/apps/web/public/service-worker.js new file mode 100644 index 0000000..112f09f --- /dev/null +++ b/apps/web/public/service-worker.js @@ -0,0 +1,66 @@ +self.importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.4/workbox-sw.js'); + +// This will trigger the importScripts() for workbox.strategies and its dependencies +// so that it can be used in the event handlers +// https://developer.chrome.com/docs/workbox/modules/workbox-sw/#avoid-async-imports +workbox.loadModule('workbox-strategies'); +workbox.loadModule('workbox-expiration'); +workbox.loadModule('workbox-routing'); + +const cacheName = 'my-cache'; + +self.addEventListener('install', function () { + self.skipWaiting(); +}); + +self.addEventListener('fetch', (event) => { + const { request } = event; + const { pathname } = new URL(event.request.url); + + const createCacheFirstStrategy = ({ items, maxAgeSeconds, maxEntries }) => { + items.map((item) => { + // if modify method, fetch fresh data: + if (event.request.method !== 'GET') { + caches.delete(item); + } else { + event.respondWith( + new workbox.strategies.CacheFirst({ + cacheName, + plugins: [ + // use both: time restrictions and max entries + new workbox.expiration.ExpirationPlugin({ + maxAgeSeconds, + maxEntries, + }), + ], + }).handle({ event, request }) + ); + } + }); + }; + + createCacheFirstStrategy({ + items: ['/', '/unlimited'], + maxAgeSeconds: 60, + maxEntries: 15, + }); + + // optional: if you want to have a way to bust all caches quickly + if (pathname.includes('/refresh')) { + caches.keys().then((names) => names.map((name) => caches.delete(name))); + } else { + return; + } +}); + +// workbox.routing.registerRoute( +// ({ request }) => request.destination === '/', +// new workbox.strategies.CacheFirst({ +// cacheName: 'my-cache', +// plugins: [ +// new workbox.expiration.ExpirationPlugin({ +// maxAgeSeconds: 60, // Время кэширования в секундах +// }), +// ], +// }) +// );