플러그인 사용

Workbox를 사용할 때는 요청과 응답이 가져오거나 캐시될 때 이를 조작하는 것이 좋습니다. Workbox 플러그인을 사용하면 최소한의 추가 상용구로 서비스 워커에 동작을 추가할 수 있습니다. 이러한 도구는 패키징하여 자체 프로젝트에 재사용하거나 다른 사람들이 사용하도록 공개적으로 출시할 수 있습니다.

Workbox는 즉시 사용할 수 있는 여러 플러그인을 제공하며, 기술이 있는 경우 애플리케이션 요구사항에 맞게 맞춤 플러그인을 작성할 수 있습니다.

사용 가능한 Workbox 플러그인

Workbox는 서비스 워커에 사용할 수 있는 다음과 같은 공식 플러그인을 제공합니다.

Workbox 플러그인은 위에 나열된 플러그인 중 하나든 맞춤 플러그인이든 플러그인 인스턴스를 전략의 plugins 속성에 추가하여 Workbox 전략과 함께 사용됩니다.

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  ({request}) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

커스텀 플러그인의 메서드

Workbox 플러그인은 하나 이상의 콜백 함수를 구현해야 합니다. 전략에 플러그인을 추가하면 적절한 시점에 콜백 함수가 자동으로 실행됩니다. 전략은 콜백 함수에 현재 요청 또는 응답과 관련된 정보를 전달하여 플러그인에 조치를 취하는 데 필요한 컨텍스트를 제공합니다. 다음 콜백 함수가 지원됩니다.

  • cacheWillUpdate: 캐시를 업데이트하는 데 Response가 사용되기 전에 호출됩니다. 이 메서드에서는 응답이 캐시에 추가되기 전에 변경되거나 null를 반환하여 캐시를 완전히 업데이트하지 않을 수 있습니다.
  • cacheDidUpdate: 새 항목이 캐시에 추가되거나 기존 항목이 업데이트될 때 호출됩니다. 이 메서드를 사용하는 플러그인은 캐시 업데이트 후 작업을 수행하려는 경우에 유용할 수 있습니다.
  • cacheKeyWillBeUsed: 요청이 캐시 키로 사용되기 전에 호출됩니다. 이는 캐시 조회 (mode'read'인 경우)와 캐시 쓰기 (mode'write'인 경우) 모두에 대해 발생합니다. 이 콜백은 URL을 캐시에 액세스하는 데 사용하기 전에 재정의하거나 정규화해야 하는 경우에 유용합니다.
  • cachedResponseWillBeUsed: 캐시의 응답이 사용되기 직전에 호출되므로 이 응답을 검사할 수 있습니다. 이 시점에서 다른 응답을 반환하거나 null를 반환할 수 있습니다.
  • requestWillFetch: 요청이 네트워크로 전송되려고 할 때마다 호출됩니다. 네트워크로 전송되기 직전에 Request를 변경해야 할 때 유용합니다.
  • fetchDidFail: 네트워크 연결이 없기 때문에 네트워크 요청이 실패할 때 호출되며 브라우저에 네트워크 연결이 있지만 오류 (예: 404 Not Found)가 수신될 때는 실행되지 않습니다.
  • fetchDidSucceed: HTTP 응답 코드와 관계없이 네트워크 요청이 성공할 때마다 호출됩니다.
  • handlerWillStart: 핸들러 로직이 실행되기 전에 호출됩니다. 초기 핸들러 상태를 설정해야 하는 경우에 유용합니다. 예를 들어 핸들러가 응답을 생성하는 데 걸린 시간을 확인하려면 이 콜백에서 시작 시간을 기록하면 됩니다.
  • handlerWillRespond: 전략의 handle() 메서드가 응답을 반환하기 전에 호출됩니다. 이는 응답을 RouteHandler 또는 다른 맞춤 로직으로 반환하기 전에 수정해야 하는 경우에 유용합니다.
  • handlerDidRespond: 전략의 handle() 메서드가 응답을 반환한 후에 호출됩니다. 이때 최종 응답 세부정보를 기록하는 것이 유용할 수 있습니다 (예: 다른 플러그인이 변경한 후).
  • handlerDidComplete: 전략 호출에서 이벤트에 추가된 모든 전체 기간 연장 프라미스가 해결된 후에 호출됩니다. 이는 캐시 적중 상태, 캐시 지연 시간, 네트워크 지연 시간 및 기타 유용한 정보를 계산하기 위해 핸들러가 완료될 때까지 기다려야 하는 데이터를 보고해야 하는 경우에 유용합니다.
  • handlerDidError: 핸들러가 모든 소스에서 유효한 응답을 제공할 수 없는 경우 호출됩니다. 이는 완전 실패의 대안으로 일종의 대체 응답을 제공하기에 최적의 시간입니다.

이러한 모든 콜백은 async이므로 캐시 또는 가져오기 이벤트가 관련 콜백의 관련 지점에 도달할 때마다 await를 사용해야 합니다.

플러그인이 위의 모든 콜백을 사용했다면 다음과 같은 코드가 생성됩니다.

const myPlugin = {
  cacheWillUpdate: async ({request, response, event, state}) => {
    // Return `response`, a different `Response` object, or `null`.
    return response;
  },
  cacheDidUpdate: async ({
    cacheName,
    request,
    oldResponse,
    newResponse,
    event,
    state,
  }) => {
    // No return expected
    // Note: `newResponse.bodyUsed` is `true` when this is called,
    // meaning the body has already been read. If you need access to
    // the body of the fresh response, use a technique like:
    // const freshResponse = await caches.match(request, {cacheName});
  },
  cacheKeyWillBeUsed: async ({request, mode, params, event, state}) => {
    // `request` is the `Request` object that would otherwise be used as the cache key.
    // `mode` is either 'read' or 'write'.
    // Return either a string, or a `Request` whose `url` property will be used as the cache key.
    // Returning the original `request` will make this a no-op.
    return request;
  },
  cachedResponseWillBeUsed: async ({
    cacheName,
    request,
    matchOptions,
    cachedResponse,
    event,
    state,
  }) => {
    // Return `cachedResponse`, a different `Response` object, or null.
    return cachedResponse;
  },
  requestWillFetch: async ({request, event, state}) => {
    // Return `request` or a different `Request` object.
    return request;
  },
  fetchDidFail: async ({originalRequest, request, error, event, state}) => {
    // No return expected.
    // Note: `originalRequest` is the browser's request, `request` is the
    // request after being passed through plugins with
    // `requestWillFetch` callbacks, and `error` is the exception that caused
    // the underlying `fetch()` to fail.
  },
  fetchDidSucceed: async ({request, response, event, state}) => {
    // Return `response` to use the network response as-is,
    // or alternatively create and return a new `Response` object.
    return response;
  },
  handlerWillStart: async ({request, event, state}) => {
    // No return expected.
    // Can set initial handler state here.
  },
  handlerWillRespond: async ({request, response, event, state}) => {
    // Return `response` or a different `Response` object.
    return response;
  },
  handlerDidRespond: async ({request, response, event, state}) => {
    // No return expected.
    // Can record final response details here.
  },
  handlerDidComplete: async ({request, response, error, event, state}) => {
    // No return expected.
    // Can report any data here.
  },
  handlerDidError: async ({request, event, error, state}) => {
    // Return a `Response` to use as a fallback, or `null`.
    return fallbackResponse;
  },
};

위에 나열된 콜백에서 사용할 수 있는 event 객체는 가져오기 또는 캐시 작업을 트리거한 원래 이벤트입니다. 원본 이벤트가 없는 경우도 있으므로 코드는 이벤트를 참조하기 전에 이벤트가 있는지 확인해야 합니다.

모든 플러그인 콜백에는 특정 플러그인과 해당 플러그인이 호출하는 전략에 고유한 state 객체도 전달됩니다. 즉, 한 콜백이 동일한 플러그인의 다른 콜백이 실행한 작업을 기반으로 조건부로 작업을 실행할 수 있는 플러그인을 작성할 수 있습니다 (예: requestWillFetch() 실행과 fetchDidSucceed() 또는 fetchDidFail() 실행 간의 차이 계산).

서드 파티 플러그인

개발 중인 플러그인이 프로젝트 외부에서 사용되고 있다고 생각되면 모듈로 게시할 것을 권장합니다. 다음은 커뮤니티에서 제공하는 Workbox 플러그인의 목록입니다.

npm 저장소에서 검색하여 더 많은 커뮤니티 제공 Workbox 플러그인을 찾을 수 있습니다.

마지막으로 공유하려는 Workbox 플러그인을 빌드한 경우 게시할 때 workbox-plugin 키워드를 추가합니다. 문제가 있다면 트위터 @WorkboxJS로 알려주세요.