서비스 담당자: 캐시 및 오프라인 모드 정책

본고에서 우리는 캐시와 오프라인 모델 같은 서비스 종사자의 기능을 소개할 것이다.
우선 자원 서버가 필요합니다.Apiumhub에서 우리는 작은 예시 서버를 만들었다. 우리는 html, js, css와 다른 자원을 제공할 것이다. 이것은 Node에서 만든 것이다. 왜냐하면 이것은 간단하기 때문이다.그것은 우리가 다음에 볼 서비스 인원 서류도 포함한다.LINK

서비스 담당자: 캐시 정책 및 오프라인 모드


fetch API와 cache API를 결합하면 서비스 직원들을 위해 서로 다른 캐시 정책을 만들 수 있습니다.다음은 가장 흔히 볼 수 있는 몇 가지 방법을 상세하게 소개하였다.

먼저 캐시


이 정책은 캐시 메모리의 자원 버전에 캐시된 요청에 응답합니다.처음이지만 캐시 자원을 찾지 못하면 네트워크에서 자원을 되돌려주고 다음에 참고할 수 있도록 캐시를 저장합니다.


const cacheFirst = (event) => {
 event.respondWith(
   caches.match(event.request).then((cacheResponse) => {
     return cacheResponse || fetch(event.request).then((networkResponse) => {
       return caches.open(currentCache).then((cache) => {
         cache.put(event.request, networkResponse.clone());
         return networkResponse;
       })
     })
   })
 )
};

나는 보통 미디어 자원에 대해 이런 전략을 사용한다. 예를 들어 이미지, 영상 등이다. 왜냐하면 그들은 더욱 무거운 자원이기 때문에 불러오는 시간이 더 길기 때문이다.

캐시만


이 정책은 자원 캐시 버전을 사용하여 요청에 직접 응답합니다.캐시 버전이 존재하지 않으면 오류를 되돌려줍니다.


const cacheOnly = (event) => {
 event.respondWith(caches.match(event.request));
};

나는 아직 그것의 어떤 용례도 찾지 못했다.

네트워크 우선


이 정책은 캐시된 버전이 이미 존재하더라도 네트워크를 통해 최신 자원 버전을 가져오려고 시도합니다.네트워크 응답이 만족스러우면 캐시를 업데이트합니다.네트워크 응답에 오류가 있으면 캐시에서 자원을 직접 되돌려줍니다.


const networkFirst = (event) => {
 event.respondWith(
   fetch(event.request)
     .then((networkResponse) => {
       return caches.open(currentCache).then((cache) => {
         cache.put(event.request, networkResponse.clone());
         return networkResponse;
       })
     })
     .catch(() => {
       return caches.match(event.request);
     })
 )
};

나는 보통api 호출에서 그것을 사용하는데,api 호출에서는 내용 변경의 빈도가 매우 낮기 때문에 최신 내용 버전으로 돌아가는 것은 중요하지 않다.이렇게 하면 나는 새로운 내용을 우선적으로 고려하고 오프라인 모드에 자리를 양보할 것이다. 오프라인 모드에서 우리는 지난 세션의 데이터 버전이 연결되어 있는 것을 볼 수 있다.

네트워크만


이런 전략은 항상 필요한 네트워크를 얻기 위해 최신 자원 버전을 우선적으로 고려한다.요청이 실패하면 오류를 되돌려줍니다.


const networkOnly = (event) => {
 event.respondWith(fetch(event.request));
};

나는api 호출에서 그것을 사용하는데,api 호출에서 우리가 표시하는 데이터 버전은 반드시 최신이어야 한다는 것이 매우 중요하다.예를 들어, 만약 제품이 이미 품절되었다면, 우리는 {stock:5}와 같은 캐시 응답을 받아서는 안 된다.

재검증 시 만료


앞의 전략과 결합함으로써 우리는 자신의 맞춤형 전략을 만들 수 있다. 예를 들어 본 예와 같다.
이 정책은 캐시 내용에 대해 우선순위를 정하여 자원(캐시 우선)을 즉시 불러오고 네트워크에 요청을 보내서 최신 버전의 자원으로 캐시 내용을 업데이트하여 미래의 요청에 대비합니다.첫 번째 캐시에 내용이 없으면 먼저 네트워크 요청을 보냅니다.


const staleWhileRevalidate = (event) => {
 event.respondWith(
   caches.match(event.request).then((cacheResponse) => {
     if (cacheResponse) {
       fetch(event.request).then((networkResponse) => {
         return caches.open(currentCache).then((cache) => {
           cache.put(event.request, networkResponse.clone());
           return networkResponse;
         })
       });
       return cacheResponse;
     } else {
       return fetch(event.request).then((networkResponse) => {
         return caches.open(currentCache).then((cache) => {
           cache.put(event.request, networkResponse.clone());
           return networkResponse;
         })
       });
     }
   })
 );
};

css, js 등 정적 파일에 사용합니다. 새 코드를 배치할 때만 변경할 수 있기 때문입니다.

Dell 서비스 직원 테스트


이제 우리는 서로 다른 캐시 정책을 알고 사용자 정의 정책을 만들 수 있다. 현재 일하고 있는 서비스 담당자의 예시를 볼 때가 되었다.
우리 프로젝트는 다음 파일로 구성되어 있습니다.

  • 색인html은 서비스 직원이 등록한 홈페이지입니다.

  • 서남js는 서비스 인원 자체입니다.

  • 서남책략.js는 저희 서비스 직원들이 사용할 다양한 전략을 포함하고 있습니다.

  • 에셋은 이미지, 스크립트 및 스타일 파일을 저장하는 폴더입니다.
  • 색인에 있습니다.html 파일은 저희가 스크립트를 가지고 서비스 인원을 등록할 것입니다.
    
    if ('serviceWorker' in navigator) {
     window.addEventListener('load', function() {
       navigator.serviceWorker.register('/sw.js').then(function(registration) {
         console.log('SW registration successful with scope: ', registration.scope);
       }, function(err) {
         console.log('SW registration failed: ', err);
       });
     });
    }
    
    
    등록 작업이 정상적으로 수행되는 경우 아래 그림과 같이 등록된 서비스 직원을 볼 수 있습니다.

    저희 서비스 직원은 두 부분으로 구성되어 있으며, 첫 번째 부분은 요청과/또는 캐시 요청을 포착합니다.
    
    const router = {
     find: (url) => router.routes.find(it => url.match(it.url)),
     routes: [
       { url: `^http://apiumhub.com:[0-9]{1,5}$`, handle: strategy.staleWhileRevalidate },
       { url: `^http://apiumhub.com:[0-9]{1,5}/.*\\.html`, handle: strategy.staleWhileRevalidate },
       { url: `^http://apiumhub.com:[0-9]{1,5}/.*\\.css`, handle: strategy.staleWhileRevalidate },
       { url: `^http://apiumhub.com:[0-9]{1,5}/.*\\.js`, handle: strategy.staleWhileRevalidate },
       { url: `^http://apiumhub.com:[0-9]{1,5}/.*\\.jpeg`, handle: strategy.cacheFirst }
     ]
    };
    
    self.addEventListener("fetch", event => {
     const found = router.find(event.request.url);
     if (found) found.handle(event);
    });
    
    
    두 번째 부분은 우리가 먼저 캐시를 비워야 할 때 캐시를 완전히 비워야 하는 것을 방지하기 위해 리셋 메커니즘이다.예를 들어 키를 수동으로 v2로 변경하기 전에 모든 자원은 v1 캐시에 저장됩니다.
    
    const currentCache = 'v1'; // ← CHANGE IT TO RESET CACHE
    
    self.addEventListener('activate', event => {
     event.waitUntil(
       caches.keys().then(cacheNames => Promise.all(
         cacheNames
           .filter(cacheName => cacheName !== currentCache)
           .map(cacheName => caches.delete(cacheName))
       ))
     );
    });
    
    
    마지막으로 페이지를 로드하고 모든 것이 정상적이라면 다음 그림과 같이 캐시된 리소스를 볼 수 있습니다.

    다음 기사에서는 Google workbox 라이브러리를 사용하여 이와 유사한 작업을 하는 방법을 보여 드리겠습니다.
    게시물Service worker: Caching and offline mode strategies이 가장 먼저Apiumhub에 올라왔다.

    좋은 웹페이지 즐겨찾기