You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// what the app and server are currently usingexportconstanalyticsEndpoint='/beacon';// what we can use as an aliasexportconstanalyticsFacadeEndpoint='/analytics';// used to trigger the batching and dispatch of analyticsexportconstanalyticsOffloadEndpoint='/sw/_analytics_offload';// the cache name we will be utilizingexportconstanalyticsCacheName='analytics';
sw.js - Service Worker Thread
import{isPushSupported,showNotification,unregister,onInstall,onActivate,onFetch,onPush,}from'@americanexpress/one-service-worker';import{analyticsEndpoint,analyticsFacadeEndpoint,analyticsOffloadEndpoint,analyticsCacheName,}from'./config.js';// bootstrapself.addEventListener('install',onInstall());self.addEventListener('activate',onActivate());// helpersfunctiongetCacheEntries(cache){returncache.keys().then(requests=>{cache.matchAll(requests.map(request=>request.clone())).then(responses=>[newMap([responses.map((response,index)=>[requests[index],response]),]),requests,responses,]);});}functioncreateAcceptedResponse(){returnnewResponse(null,{status: 202,statusText: 'OK',});}constdispatchAnalytics=events=>{returnfetch(analyticsEndpoint,{body: JSON.stringify({
events,}),});};constanalyticsMiddleware=event=>{switch(event.request.url){default:
// if the event does not match, we bailreturnfalse;// we can aggregate our analytics data from the cache// and send a batch of events every once in a whilecaseanalyticsOffloadEndpoint: {event.waitUntil(Promise.all(caches.open(analyticsCacheName).then(cache=>{returngetCacheEntries(cache).then(([entries])=>{constevents=[];entries.forEach(([request,response])=>{event.waitUntil(cache.delete(request));events.push(response.json());});returnPromise.all(events).then(dispatchAnalytics);});}),),);break;}// for all our analytics endpoints, we can store them to be queuedcaseanalyticsFacadeEndpoint:
caseanalyticsEndpoint: {event.waitUntil(caches.open(analyticsCacheName).then(cache=>{constresponse=newResponse({timestamp: Date.getTime(),
...JSON.parse(event.request.clone().body),});returncache.put(event.request,response);}),);}}// we send over confirmation responseevent.respondWith(createAcceptedResponse());returntrue;};self.addEventListener('fetch',onFetch([analyticsMiddleware]));// we can check the runtime for supportif(isPushSupported()){constpushMiddleware=event=>{const{ id, notification }=event.data.json();leteventName;switch(id){default: {if(notification){eventName='push-notification:notification';event.waitUntil(showNotification(notification.title,notification.options),);break;}returnfalse;}case'module-update': {eventName='push-notification:module-update';event.waitUntil(Promise.all([// update a module and its dependencies]),);event.waitUntil(showNotification('Module Update'));break;}case'escape-hatch': {eventName='push-notification:escape-hatch';// emergency push to unregister service workerevent.waitUntil(unregister());event.waitUntil(showNotification('Uninstalling Service Worker'));break;}}if(eventName){event.waitUntil(fetch(newRequest(analyticsFacadeEndpoint,{body: JSON.stringify({
event,}),}),),);returntrue;}returnfalse;};self.addEventListener('push',onPush([pushMiddleware]));}
client.js - Main Thread
import{// runtimeisPushSupported,isSyncSupported,// core APIregister,subscribe,registerTag,on,registerTagEvent,}from'@americanexpress/one-service-worker';import{analyticsFacadeEndpoint,analyticsOffloadEndpoint}from'./config.js';constsubscribeEndpoint='/subscribe';// helpersconstoffloadAnalytics=()=>fetch(analyticsOffloadEndpoint);constsendAnalytics=({ event, data })=>fetch(newRequest(analyticsFacadeEndpoint,{body: JSON.stringify({
event,
data,}),}),);constsendSubscription=subscription=>fetch(newRequest(subscribeEndpoint,{method: 'POST',body: JSON.stringify(subscription),}),);// to install the service worker, we have to register the scriptregister('/sw.js',{scope: '/',updateViaCache: 'none',}).catch(error=>console.error(error)).then(()=>{// set up our analytics interval to every 5 minutessetInterval(offloadAnalytics,1000*60*5);document.querySelector('#analytics-offload-button').addEventListener('click',()=>{offloadAnalytics();});if(isPushSupported()){document.querySelector('#subscribe-button').addEventListener('click',()=>{// after registration and once clicked, we subscribe the usersubscribe({applicationServerKey: 'your-app-key',userVisibleOnly: true,}).then(subscription=>{// once subscribed, send your users subscription to your server for keepingsendSubscription(subscription);sendAnalytics({event: 'push-subscribe',});});});}if(isSyncSupported()){on(registerTagEvent,tag=>{/* update state if needed */sendAnalytics({event: 'sync-tag',data: {
tag,},});});document.querySelector('#sync-server').addEventListener('click',()=>{consttag=document.querySelector('#sync-select-tag').value;registerTag(tag).catch(console.error).then(syncRegistration=>{console.log('syncRegistration:',syncRegistration);sendAnalytics({event: 'sync-tag-registration',data: {
tag,},});});});}});