명령형 캐싱 가이드

Andrew Guan
Andrew Guan
Demián Renzulli
Demián Renzulli

일부 웹 사이트는 결과를 알 수 있습니다 예를 들면 다음과 같습니다.

  • 페이지가 서비스 워커에게 프리페치가 사용되므로 사용자가 해당 문서나 페이지의 하위 리소스가 이미 캐시에 있는 경우, 훨씬 빠르게 탐색할 수 있습니다.
  • 이 페이지는 서비스 워커에게 일련의 주요 기사를 검색하고 캐시하여 오프라인으로 사용할 수 있습니다.

이러한 유형의 중요하지 않은 작업을 서비스 워커에 위임하면 사용자 상호작용에 응답하는 등 좀 더 긴급한 작업을 더 잘 처리하기 위한 기본 스레드입니다.

서비스 워커에 캐시할 리소스를 요청하는 페이지의 다이어그램

이 가이드에서는 페이지에서 일방 커뮤니케이션 기법을 구현하여 표준 브라우저 API와 Workbox 라이브러리를 사용하여 서비스 워커를 구현할 수 있습니다. 우리는 이러한 유형의 명령적 캐싱으로 사용할 수 있습니다.

프로덕션 케이스

1-800-Flowers.com은 다음을 통해 서비스 워커로 명령적 캐싱 (미리 가져오기)을 구현했습니다. postMessage()를 눌러 카테고리 페이지의 상위 항목 을 사용하여 제품 세부정보 페이지로의 후속 탐색 속도를 높입니다.

1-800 꽃 로고.

다음과 같이 혼합된 접근 방식을 사용하여 미리 가져올 항목을 결정합니다.

  • 페이지 로드 시 팀은 서비스 워커에게 상위 9개 항목에 대한 JSON 데이터를 검색하도록 요청합니다. 결과 응답 객체를 캐시에 추가합니다.
  • 나머지 항목에서 mouseover 이벤트가 될 수 있으므로 사용자가 항목 위로 커서를 이동하면 '수요' 시 리소스 가져오기를 트리거할 수 있습니다.

Cache API를 사용하여 JSON을 저장합니다. 응답:

<ph type="x-smartling-placeholder">
</ph> 1-800 꽃 로고.
1-800Flowers.com의 제품 등록정보 페이지에서 JSON 제품 데이터 미리 가져오기

사용자가 항목을 클릭하면 이와 관련된 JSON 데이터를 캐시에서 가져올 수 있습니다. 네트워크에 이동하지 않아도 탐색이 더 빨라집니다.

Workbox 사용

Workbox를 사용하면 간편하게 서비스 워커: workbox-window 패키지를 통한 모듈 집합 창 컨텍스트에서 실행되도록 의도된 것입니다. 다른 Workbox 패키지를 보완합니다. 서비스 워커에서 실행되는 작업을 보여줍니다

페이지를 서비스 워커와 통신하려면 먼저 등록된 서비스 워커:

const wb = new Workbox('/sw.js');
wb.register();

그런 다음 메시지를 가져오는 번거로움 없이 선언적으로 메시지를 직접 보낼 수 있습니다. 기본 커뮤니케이션 API를 고려하거나, 등록, 활성화 확인,

wb.messageSW({"type": "PREFETCH", "payload": {"urls": ["/data1.json", "data2.json"]}}); });

서비스 워커는 message 핸들러를 구현하여 이 메시지를 들을 수 있습니다. 선택적으로 응답을 반환할 수 있지만, 이와 같은 경우에는 필요하지 않습니다.

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'PREFETCH') {
    // do something
  }
});

브라우저 API 사용

Workbox 라이브러리가 요구사항을 충족하기에 충분하지 않다면 다음과 같은 방법으로 window to service를 구현할 수 있습니다. 작업자 통신을 지원합니다

postMessage API 페이지에서 서비스 워커로의 단방향 통신 메커니즘을 설정하는 데 사용할 수 있습니다.

페이지는 postMessage() 서비스 워커 인터페이스:

navigator.serviceWorker.controller.postMessage({
  type: 'MSG_ID',
  payload: 'some data to perform the task',
});

서비스 워커는 message 핸들러를 구현하여 이 메시지를 들을 수 있습니다.

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === MSG_ID) {
    // do something
  }
});

{type : 'MSG_ID'} 속성은 필수는 아니지만 페이지에서 다음 작업을 실행하도록 허용하는 한 가지 방법입니다. 서비스 워커에 다른 유형의 명령을 보냅니다 (즉, '미리 가져오기' vs. '지우기 위해'). 스토리지'). 서비스 워커는 이 플래그를 기반으로 다른 실행 경로로 분기할 수 있습니다.

작업이 성공하면 사용자는 이점을 얻을 수 있지만 그렇지 않은 경우 기본 사용자 플로우가 변경되지는 않습니다. 예를 들어 1-800-Flowers.com이 사전 캐시를 시도하는 경우 페이지는 서비스 워커가 성공했는지 여부를 알 필요가 없습니다. 포함되어 있으면 사용자가 더 빠르게 탐색할 수 있습니다. 그렇지 않은 경우에도 페이지가 새 페이지로 이동해야 합니다. 시간이 조금 더 걸릴 것 같습니다.

간단한 미리 가져오기의 예

명령적 캐싱의 가장 일반적인 적용 분야 중 하나는 미리 가져오기입니다. 미리 가져오기는 리소스를 할당하여 탐색 속도를 높일 수 있습니다.

사이트에서 미리 가져오기를 구현하는 방법에는 여러 가지가 있습니다.

문서 미리 가져오기와 같이 비교적 간단한 미리 가져오기 시나리오나 특정 자산 (JS, CSS 등)를 사용하는 것이 가장 좋습니다.

추가 로직이 필요한 경우(예: 미리 가져오기 리소스(JSON 파일 또는 페이지)를 내부 URL을 가져오려면 이 작업을 전부 서비스 워커를 지원합니다

이러한 유형의 작업을 서비스 워커에 위임하면 다음과 같은 이점이 있습니다.

  • 가져오기 및 가져오기 후 처리의 부담을 덜어줍니다 (다음에 도입될 예정). 두 번째 대화목록에 추가합니다. 이를 통해 기본 스레드가 더 중요한 작업을 처리할 수 있도록 예를 들어 사용자 상호작용에 응답하는 등의 작업을 수행해야 합니다
  • 여러 클라이언트 (예: 탭)가 공통 기능을 재사용할 수 있도록 허용하고 서비스를 동시에 호출할 수 있습니다.

제품 세부정보 페이지 미리 가져오기

다음에서 postMessage() 처음 사용 캐시할 URL 배열을 전달합니다.

navigator.serviceWorker.controller.postMessage({
  type: 'PREFETCH',
  payload: {
    urls: [
      'www.exmaple.com/apis/data_1.json',
      'www.exmaple.com/apis/data_2.json',
    ],
  },
});

서비스 워커에서 message 핸들러를 구현하여 모든 활성 탭에서 보내는 메시지를 가로채서 처리합니다.

addEventListener('message', (event) => {
  let data = event.data;
  if (data && data.type === 'PREFETCH') {
    let urls = data.payload.urls;
    for (let i in urls) {
      fetchAsync(urls[i]);
    }
  }
});

이전 코드에서는 fetchAsync()라는 작은 도우미 함수를 도입하여 각각에 대한 가져오기 요청을 실행합니다.

async function fetchAsync(url) {
  // await response of fetch call
  let prefetched = await fetch(url);
  // (optionally) cache resources in the service worker storage
}

응답을 얻으면 리소스의 캐싱 헤더를 사용할 수 있습니다. 많은 경우 그러나 제품 세부정보 페이지와 마찬가지로 리소스는 캐시되지 않습니다. 즉, no-cacheCache-control 헤더). 이러한 경우 다음을 실행하여 이 동작을 재정의할 수 있습니다. 서비스 워커 캐시에 가져온 리소스를 저장하지 않습니다 이렇게 하면 사용할 수 있습니다.

JSON 데이터 그 이상

서버 엔드포인트에서 JSON 데이터를 가져오면 다른 URL도 포함되는 경우가 많습니다. 이 첫 번째 레벨과 연결된 이미지 또는 기타 엔드포인트 데이터와 같이 미리 가져올 만한 가치가 있는 데이터를 수집하는 데 사용됩니다

이 예에서 반환된 JSON 데이터가 식료품 쇼핑 사이트의 정보라고 가정해 보겠습니다.

{
  "productName": "banana",
  "productPic": "https://cdn.example.com/product_images/banana.jpeg",
  "unitPrice": "1.99"
 }

제품 목록을 반복하고 히어로 이미지를 캐시하도록 fetchAsync() 코드를 수정합니다. 각각:

async function fetchAsync(url, postProcess) {
  // await response of fetch call
  let prefetched = await fetch(url);

  //(optionally) cache resource in the service worker cache

  // carry out the post fetch process if supplied
  if (postProcess) {
    await postProcess(prefetched);
  }
}

async function postProcess(prefetched) {
  let productJson = await prefetched.json();
  if (productJson && productJson.product_pic) {
    fetchAsync(productJson.product_pic);
  }
}

404와 같은 상황에서 이 코드에 예외 처리를 추가할 수 있습니다. 그러나 서비스 워커를 사용하여 미리 가져오는 것의 장점은 많은 양의 데이터가 없어도 실패할 수 있다는 것입니다. 페이지의 기본 스레드에 적용됩니다. 또한 미리 가져온 콘텐츠를 후처리하여 유연성을 높이고 미리 가져온 데이터와 있습니다. 원하는 대로 자유롭게 결정할 수 있습니다.

결론

이 도움말에서는 페이지와 서비스 간의 단방향 통신의 일반적인 사용 사례를 다루었습니다. worker: 명령적 캐싱. 여기서 설명하는 예는 다음 설명 중 한 가지 방법을 다른 사용 사례에도 동일한 접근 방식을 적용할 수 있습니다. 오프라인 소비, 북마크 등을 위해 주문형으로 인기 기사를 캐시합니다.

페이지 및 서비스 워커 통신의 더 많은 패턴을 보려면 다음을 참조하십시오.

  • 브로드캐스트 업데이트: 서비스 워커에서 페이지를 호출하여 (예: 새로운 버전의 웹 앱을 사용할 수 있는 경우))을 알릴 수 있습니다.
  • 양방향 통신: 작업을 서비스 워커 (예: 다운로드) 진행 상황에 대해 페이지에 계속 알려야 합니다.