question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

What is the recommended way for caching ajax requests or using push notifications w/ service workers in a CRA based PWA?

See original GitHub issue

I’m using the newest versions of create-react-app and react-scripts.

For a fully functional offline PWA, I would need to cache network requests to show some data while the user is offline, Most tutorials I saw were listening to the fetch event in the service-worker itself using self.addEventListener, but since CRA uses workbox-plugin to autogenerate the service worker as a developer I don’t have access to “self” so I can’t freely listen to the fetch event.

As a workaround I did something like this to cache my get requests…

function cachedGet (url, config) {
  return Promise.race([
    getFromCacheAfter4Seconds(url, config),
    getFromNetworkAndSaveToCache(url, config)
  ])
    .catch(error => {
      console.error('error', error)
      return getFromCacheAfter4Seconds(url, config)
    })
}

function getFromCacheAfter4Seconds (url, config) {
  const cacheKey = url.split('?')[0]

  return new Promise((resolve, reject) => {
    let timeout = setTimeout(() => {
      clearTimeout(timeout)
      const cachedResponse = window.localStorage.getItem(cacheKey)
      if (cachedResponse) {
        const response = JSON.parse(cachedResponse)
        console.log('getting from cache', url)
        console.log('cachedResponse', response)
        resolve(response)
      } else {
        console.log('no cached response found falling back to network', url)
        getFromNetworkAndSaveToCache(url, config)
          .then(resolve)
      }
    }, 4000)
  })
}

function getFromNetworkAndSaveToCache (url, config) {
  const cacheKey = url.split('?')[0] // For requests that use a startDate & endDate parameters
  return axios.get(url, config)
    .then(res => res.data)
    .then(data => {
      window.localStorage.setItem(cacheKey, JSON.stringify(data))
      return data
    })
}

or to avoid calling the setTimeout anyway whenever Promise.race() is called I did something like this

function cachedGet (url, config) {
  return getFromNetworkAndSaveToCache(url, config)
    .catch(error => {
      if (!error.status) {
        // Network error
        return getFromCacheAfter4Seconds(url, config)
      } else {
        throw error
      }
    })
}

Is there a better/ more recommended way? perhaps a configuration file I can use to specify cache-first vs offline-first vs whichever is faster? Same thing if I were to use other service worker features like background sync and/or push notifications.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7

github_iconTop GitHub Comments

7reactions
emibcncommented, Jan 2, 2019

@khaledosman You can append an epilog to the auto-generated SW in a build step (without ejecting or forking CRA) and, there, add a message listener which can access SW self object. For example, I use this technique to upgrade SW in https://github.com/emibcn/Rac1.js/blob/master/app/src/sw-epilog.js :

// Add a listener to receive messages from clients
self.addEventListener('message', function(event) {
  // Force SW upgrade (activation of new installed SW version)
  if ( event.data === 'skipWaiting' ) {
    self.skipWaiting();
  }
});

And then, from your app https://github.com/emibcn/Rac1.js/blob/master/app/src/index.js :

registration.waiting.postMessage('skipWaiting');

Note: Don’t forget to add the epilog to your build process in your package.json. For example https://github.com/emibcn/Rac1.js/blob/master/app/package.json#L27 :

...
    "build": "react-scripts build && yarn sw-epilog",
    "sw-epilog": "cat src/sw-epilog.js >> build/service-worker.js",
...
0reactions
stale[bot]commented, Mar 7, 2019

This issue has been automatically closed because it has not had any recent activity. If you have a question or comment, please open a new issue.

Read more comments on GitHub >

github_iconTop Results From Across the Web

5 Service Worker Caching Strategies for Your Next PWA App
PWAs use this strategy on high-priority, high-critical files. Also, non-GET requests like POST requests. POST requests responses are not cached ...
Read more >
Notifications, caching, and messages in a progressive web ...
Learn how to create notifications, add elements to the cache that aren't defined in the service worker, and establish worker-client ...
Read more >
Using Service Workers - Web APIs | MDN
A service worker functions like a proxy server, allowing you to modify requests and responses replacing them with items from its own cache....
Read more >
SSR or CSR - what is better for Progressive Web App?
These elements are then cached by the browser, which subsequently makes API requests via AJAX to fetch dynamic content JavaScript content ...
Read more >
Turning a website into a mobile app using Progressive Web ...
Configuring Caching in the Service Worker ... With the basic configuration working, there are a lot of things you can do like configuring...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found