Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 77 additions & 7 deletions public/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,40 @@
/* eslint-disable no-unused-vars */
/* eslint-disable no-undef */
/* eslint-disable no-restricted-globals */
const version = 'v0.3.0';
const version = 'v0.3.1';
const cacheName = 'simorghCache_v1';

const service = self.location.pathname.split('/')[1];
const hasOfflinePageFunctionality = false;
const OFFLINE_PAGE = `/${service}/offline`;
const hasOfflinePageFunctionality = true;
const OFFLINE_PAGE = `/${service}.lite`;
const isLocalEnv = self.location.hostname === 'localhost';
let appEnv;
if (isLocalEnv) {
appEnv = 'local';
} else if (self.location.hostname.includes('test')) {
appEnv = 'test';
} else {
appEnv = 'live';
}

self.addEventListener('install', event => {
event.waitUntil(async () => {
const cache = await caches.open(cacheName);
if (hasOfflinePageFunctionality) await cache.add(OFFLINE_PAGE);
function logToClients(message) {
self.clients.matchAll().then(clients => {
clients.forEach(client => {
client.postMessage(message);
});
});
}

self.addEventListener('install', event => {
event.waitUntil(
(async () => {
const cache = await caches.open(cacheName);
if (hasOfflinePageFunctionality) {
await cache.add(OFFLINE_PAGE);
await cacheMostReadStories(cache);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this function defined?

}
})(),
);
});

const CACHEABLE_FILES = [
Expand Down Expand Up @@ -73,6 +95,18 @@ const fetchEventHandler = async event => {
return response;
})(),
);
} else if (isRequestForMostRead) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where is this variable defined? I can't find it anywhere on the diff?

event.respondWith(
(async () => {
const cache = await caches.open(cacheName);
let response = await cache.match(event.request);
if (!response) {
response = await fetch(event.request);
cache.put(event.request, response.clone());
}
return response;
})(),
);
} else if (hasOfflinePageFunctionality && event.request.mode === 'navigate') {
event.respondWith(async () => {
try {
Expand All @@ -93,3 +127,39 @@ const fetchEventHandler = async event => {
};

onfetch = fetchEventHandler;

self.addEventListener('message', async event => {
logToClients(`[SW] Received message: ${event.data?.type}`);
if (event.data && event.data.type === 'CACHE_HOME_PAGE_AND_MOST_READ') {
if (!navigator.serviceWorker.controller) {
logToClients(
'[SW] Service worker is not active. Skipping caching logic.',
);
return;
}
const { homePageUrl, mostReadUrls } = event.data;

try {
const cache = await caches.open('simorghCache_v1');
// Most read URLs by default are canonical--> Append ".lite" to each URL and cache all
if (homePageUrl && mostReadUrls && Array.isArray(mostReadUrls)) {
const liteUrls = mostReadUrls.map(url => `${url}.lite`);
await Promise.all(
liteUrls.map(async url => {
try {
await cache.add(url);
// eslint-disable-next-line no-console
console.log(`[SW] Cached most read URL: ${url}`);
} catch (err) {
// eslint-disable-next-line no-console
console.error('[SW] Failed to cache most read URL: %s', url, err);
}
}),
);
}
} catch (err) {
// eslint-disable-next-line no-console
console.error('[SW] Failed to cache URLs:', err);
}
}
});
2 changes: 2 additions & 0 deletions src/app/components/ServiceWorker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@
const swSrc = `${getEnvConfig().SIMORGH_BASE_URL}/${service}${swPath}`;

useEffect(() => {
console.log('Service Worker installing...');

Check warning on line 43 in src/app/components/ServiceWorker/index.tsx

View workflow job for this annotation

GitHub Actions / build (22.x)

Unexpected console statement
const shouldInstallServiceWorker =
swPath && onClient() && 'serviceWorker' in navigator;

if (shouldInstallServiceWorker) {
console.log('Registering service worker');

Check warning on line 48 in src/app/components/ServiceWorker/index.tsx

View workflow job for this annotation

GitHub Actions / build (22.x)

Unexpected console statement
navigator.serviceWorker.register(`/${service}${swPath}`);
}
}, [swPath, service]);
Expand Down
51 changes: 51 additions & 0 deletions src/app/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
/* @jsxFrag React.Fragment */
import React, { use } from 'react';
import { jsx } from '@emotion/react';
import { getMostReadEndpoint } from '#app/lib/utilities/getUrlHelpers/getMostReadUrls';
import VisuallyHiddenText from '#app/components/VisuallyHiddenText';
import useOptimizelyVariation, {
ExperimentType,
} from '#app/hooks/useOptimizelyVariation';
import OptimizelyPageMetrics from '#app/components/OptimizelyPageMetrics';
import { getEnvConfig } from '#app/lib/utilities/getEnvConfig';
import isLocal from '#app/lib/utilities/isLocal';
import ATIAnalytics from '../../components/ATIAnalytics';
import {
Curation,
Expand Down Expand Up @@ -74,6 +77,54 @@ const HomePage = ({ pageData }: HomePageProps) => {
}

const itemList = getItemList({ curations, name: brandName });
const MOST_READ_URL = `${getEnvConfig().SIMORGH_BASE_URL}${getMostReadEndpoint(
{
service: use(ServiceContext).service,
variant: null,
isBff: !isLocal(),
},
)}`;
const HOME_PAGE_URL = `${getEnvConfig().SIMORGH_BASE_URL}/${service}`;

const fetchMostReadItems = async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why can't this request be made from within the service worker?

try {
const response = await fetch(MOST_READ_URL, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

const { data } = await response.json();

return (
data?.items?.map((item: { href: string; title: string }) => ({
href: item.href,
title: item.title,
})) || []
);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error fetching most read items:', error);
return [];
}
};

fetchMostReadItems().then((items: { href: string; title: string }[]) => {
const MOST_READ_URLS = items.map(({ href }) => href);

if (navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage({
type: 'CACHE_HOME_PAGE_AND_MOST_READ',
HOME_PAGE_URL,
MOST_READ_URLS,
});
}

items.forEach(({ href }) => {
return href;
});
});

return (
<>
Expand Down
9 changes: 9 additions & 0 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,12 @@
if (module.hot) {
module.hot.accept();
}

if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/sw.js')
.then(() => console.log('Service Worker registered successfully'))

Check warning on line 61 in src/client.js

View workflow job for this annotation

GitHub Actions / build (22.x)

Unexpected console statement
.catch(err => console.error('Service Worker registration failed:', err));

Check warning on line 62 in src/client.js

View workflow job for this annotation

GitHub Actions / build (22.x)

Unexpected console statement
});
}
Loading