Skip to content

Commit 6129ea8

Browse files
committed
feat: move ThirdPartyScripts
1 parent c03e247 commit 6129ea8

File tree

6 files changed

+178
-140
lines changed

6 files changed

+178
-140
lines changed

public/service-worker.js

Lines changed: 103 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,105 @@
1-
function registerServiceWorker() {
2-
if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
3-
navigator.serviceWorker.register('/sw.js').then(() => {
4-
console.log('Service Worker registration successful.');
5-
});
1+
const VERSION = 'v4';
2+
const STATIC_CACHE = `static-${VERSION}`;
3+
const IMG_REGEX = /\/images\/.*\.(png|jpg|jpeg|gif|webp|svg)$/i;
4+
5+
self.addEventListener('install', () => {
6+
// event.waitUntil((async () => {})());
7+
console.log('Service Worker installed.');
8+
self.skipWaiting();
9+
});
10+
11+
self.addEventListener('activate', (event) => {
12+
console.log('Service Worker activated.');
13+
event.waitUntil(
14+
(async () => {
15+
// Clean
16+
const keys = await caches.keys();
17+
await Promise.all(
18+
keys.map((k) =>
19+
k.startsWith('static-') && k !== STATIC_CACHE ? caches.delete(k) : null
20+
)
21+
);
22+
23+
if ('navigationPreload' in self.registration) {
24+
try {
25+
await self.registration.navigationPreload.enable();
26+
} catch {}
27+
}
28+
await self.clients.claim();
29+
})()
30+
);
31+
});
32+
33+
const canCache = (req, res) => {
34+
if (req.method !== 'GET') return false;
35+
if (!res || !res.ok) return false;
36+
37+
const cacheControl = res.headers.get('Cache-Control') || '';
38+
39+
if (cacheControl.includes('no-store')) return false;
40+
if (res.type === 'opaque') return false;
41+
return true;
42+
};
43+
44+
self.addEventListener('fetch', (event) => {
45+
const req = event.request;
46+
47+
if (req.method !== 'GET') return;
48+
49+
const url = new URL(req.url);
50+
const sameOrigin = url.origin === self.location.origin;
51+
52+
if (
53+
url.searchParams.has('_rsc') ||
54+
url.pathname.startsWith('/api') ||
55+
url.pathname.startsWith('/_next/data') ||
56+
url.pathname.startsWith('/_next/static') ||
57+
url.pathname.startsWith('/_next/image')
58+
) {
59+
return;
60+
}
61+
62+
if (req.mode === 'navigate') {
63+
return;
64+
}
65+
66+
const isImage = sameOrigin && IMG_REGEX.test(url.pathname);
67+
if (!isImage) {
68+
return;
669
}
7-
}
870

9-
registerServiceWorker();
71+
event.respondWith(
72+
(async () => {
73+
const cache = await caches.open(STATIC_CACHE);
74+
const cached = await cache.match(req);
75+
76+
if (cached) {
77+
event.waitUntil(
78+
(async () => {
79+
try {
80+
const net = await fetch(req, { cache: 'no-store' });
81+
if (canCache(req, net)) await cache.put(req, net.clone());
82+
} catch {}
83+
})()
84+
);
85+
return cached;
86+
}
87+
88+
try {
89+
const preload = await event.preloadResponse;
90+
if (preload && canCache(req, preload)) {
91+
event.waitUntil(cache.put(req, preload.clone()));
92+
return preload;
93+
}
94+
} catch {}
95+
96+
try {
97+
const net = await fetch(req, { cache: 'no-store' });
98+
if (canCache(req, net)) event.waitUntil(cache.put(req, net.clone()));
99+
return net;
100+
} catch {
101+
return new Response('', { status: 504, statusText: 'Offline' });
102+
}
103+
})()
104+
);
105+
});

public/sw.js

Lines changed: 0 additions & 105 deletions
This file was deleted.

src/app/layout.tsx

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { GoogleAnalytics, GoogleTagManager } from '@next/third-parties/google';
2-
import { SpeedInsights } from '@vercel/speed-insights/next';
31
import { ToastContainer } from 'react-toastify';
42
import React, { Suspense } from 'react';
53
import type { Metadata } from 'next';
64
import Script from 'next/script';
75
import Image from 'next/image';
86

7+
import { ServiceWorkerRegistrar } from '@/layout/components/service-worker-registrar';
8+
import { ThirdPartyScripts } from '@/layout/components/third-party-scripts';
99
import { ProgressBar } from '@/layout/components/progress-bar';
1010
import { ENV } from '@/shared/constants';
1111
import { textFont } from '@/app/fonts';
@@ -25,11 +25,6 @@ const CookiesModal = React.lazy(() =>
2525
default: module.CookiesModal
2626
}))
2727
);
28-
const PerformanceMonitor = React.lazy(() =>
29-
import('@/shared/components/performance-monitor').then((module) => ({
30-
default: module.PerformanceMonitor
31-
}))
32-
);
3328

3429
import './globals.scss';
3530
import 'animate.css';
@@ -75,7 +70,7 @@ export const metadata: Metadata = {
7570
{
7671
width: 1200,
7772
height: 630,
78-
url: '/social-banner.png',
73+
url: '/images/social-banner.png',
7974
alt: `${PERSONAL_DATA.fullName} | ${PERSONAL_DATA.title}`
8075
}
8176
]
@@ -120,7 +115,9 @@ export default function RootLayout({
120115

121116
{children}
122117

123-
<CookiesModal />
118+
<Suspense fallback={null}>
119+
<CookiesModal />
120+
</Suspense>
124121

125122
<ToastContainer
126123
limit={4}
@@ -131,27 +128,11 @@ export default function RootLayout({
131128
toastClassName="!bg-gray-800 !text-white"
132129
/>
133130

134-
<SpeedInsights />
135-
136-
{ENV.ANALYZE_MODE && <PerformanceMonitor />}
137-
138131
{/* Optimized script loading */}
139132
<Script src="/click-spark.js" strategy="lazyOnload" />
140-
<Script src="/service-worker.js" strategy="afterInteractive" />
133+
<ServiceWorkerRegistrar />
141134

142-
{!!ENV.GOOGLE_ADSENSE && (
143-
<Script
144-
async
145-
crossOrigin="anonymous"
146-
src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ENV.GOOGLE_ADSENSE}`}
147-
/>
148-
)}
149-
{!!ENV.GOOGLE_ANALYTICS_CODE && (
150-
<GoogleAnalytics gaId={ENV.GOOGLE_ANALYTICS_CODE} />
151-
)}
152-
{!!ENV.GOOGLE_TAG_MANAGER_CODE && (
153-
<GoogleTagManager gtmId={ENV.GOOGLE_TAG_MANAGER_CODE} />
154-
)}
135+
<ThirdPartyScripts />
155136
</body>
156137
</html>
157138
);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
'use client';
2+
import { useEffect } from 'react';
3+
4+
export function ServiceWorkerRegistrar() {
5+
useEffect(() => {
6+
if ('serviceWorker' in navigator) {
7+
navigator.serviceWorker.register('/service-worker.js').catch(() => {
8+
console.log('Service Worker registration successful.');
9+
});
10+
}
11+
}, []);
12+
return null;
13+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
'use client';
2+
3+
import { GoogleAnalytics, GoogleTagManager } from '@next/third-parties/google';
4+
import { SpeedInsights } from '@vercel/speed-insights/next';
5+
import { useEffect, useState, Suspense } from 'react';
6+
import Script from 'next/script';
7+
8+
import { getCookiesModalStatus, type CookiesModalStatus } from '@/shared/helpers';
9+
import { COOKIES_MODAL_STATUS, ENV } from '@/shared/constants';
10+
11+
const PerformanceMonitor = () =>
12+
import('@/shared/components/performance-monitor').then((module) => ({
13+
default: module.PerformanceMonitor
14+
}));
15+
16+
export function ThirdPartyScripts() {
17+
const [status, setStatus] = useState<CookiesModalStatus>(COOKIES_MODAL_STATUS.NONE);
18+
19+
useEffect(() => {
20+
setStatus(getCookiesModalStatus());
21+
}, []);
22+
23+
if (status !== COOKIES_MODAL_STATUS.ACCEPT) return null;
24+
25+
return (
26+
<>
27+
<SpeedInsights />
28+
29+
{ENV.ANALYZE_MODE && (
30+
<Suspense fallback={null}>
31+
{/* @ts-expect-error async component for lazy import */}
32+
<PerformanceMonitor />
33+
</Suspense>
34+
)}
35+
36+
{!!ENV.GOOGLE_ADSENSE && (
37+
<Script
38+
async
39+
crossOrigin="anonymous"
40+
src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ENV.GOOGLE_ADSENSE}`}
41+
/>
42+
)}
43+
44+
{!!ENV.GOOGLE_ANALYTICS_CODE && (
45+
<GoogleAnalytics gaId={ENV.GOOGLE_ANALYTICS_CODE} />
46+
)}
47+
48+
{!!ENV.GOOGLE_TAG_MANAGER_CODE && (
49+
<GoogleTagManager gtmId={ENV.GOOGLE_TAG_MANAGER_CODE} />
50+
)}
51+
</>
52+
);
53+
}

src/shared/components/custom-cursor/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import React, { useEffect, useMemo, useRef, useState } from 'react';
3+
import { useEffect, useMemo, useRef, useState } from 'react';
44

55
import { useIsClient } from '@/shared/hooks';
66

0 commit comments

Comments
 (0)