Workbox를 사용할 때 요청 및 응답을 가져오거나 캐시할 때 이를 조작해야 할 수도 있습니다. Workbox 플러그인을 사용하면 최소한의 추가 상용구로 서비스 워커에 추가 동작을 추가할 수 있습니다. 자체 프로젝트에서 패키징하여 다시 사용할 수도 있고 다른 사람들이 사용하도록 공개적으로 출시할 수도 있습니다.
Workbox는 즉시 사용 가능한 여러 플러그인을 제공하며, 능숙한 개발자라면 애플리케이션 요구사항에 맞는 맞춤 플러그인을 작성할 수 있습니다.
사용 가능한 Workbox 플러그인
Workbox는 서비스 워커에서 사용할 수 있는 다음과 같은 공식 플러그인을 제공합니다.
BackgroundSyncPlugin
: 네트워크 요청이 실패해야 하는 경우 이 플러그인을 사용하면 백그라운드 동기화 대기열에 네트워크 요청을 추가하여 다음 동기화 이벤트가 트리거될 때 다시 요청되도록 할 수 있습니다.BroadcastUpdatePlugin
: 캐시가 업데이트될 때마다 브로드캐스트 채널 또는postMessage()
를 통해 메시지를 전달할 수 있습니다.CacheableResponsePlugin
: 특정 기준을 충족하는 요청만 캐시합니다.ExpirationPlugin
: 캐시에 있는 항목의 수와 최대 기간을 관리합니다.RangeRequestsPlugin
:Range
HTTP 요청 헤더가 포함된 요청에 응답합니다.
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 플러그인은 하나 이상의 콜백 함수를 구현해야 합니다. 전략에 플러그인을 추가하면 콜백 함수가 적절한 시점에 자동으로 실행됩니다. Strategy는 현재 요청 및 응답에 대한 콜백 함수 관련 정보를 전달하여 플러그인에서 작업을 실행하는 데 필요한 컨텍스트를 제공합니다. 다음과 같은 콜백 함수가 지원됩니다.
cacheWillUpdate
:Response
가 캐시를 업데이트하는 데 사용되기 전에 호출됩니다. 이 메서드에서 응답을 캐시에 추가하기 전에 변경할 수도 있고, 캐시 전체를 업데이트하지 않도록null
를 반환할 수도 있습니다.cacheDidUpdate
: 새 항목이 캐시에 추가되거나 기존 항목이 업데이트될 때 호출됩니다. 이 메서드를 사용하는 플러그인은 캐시 업데이트 후 작업을 실행하려는 경우에 유용할 수 있습니다.cacheKeyWillBeUsed
: 요청이 캐시 키로 사용되기 전에 호출됩니다. 이는 캐시 조회 (mode
가'read'
일 때) 및 캐시 쓰기 (mode
가'write'
일 때)에서 모두 발생합니다. 이 콜백은 URL을 사용하여 캐시에 액세스하기 전에 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 플러그인의 간단한 목록입니다.
cloudinary-workbox-plugin
: 현재 연결 속도를 기반으로 Cloudinary에서 호스팅하는 이미지에 대한 요청을 동적으로 재작성합니다.workbox-plugin-firebase-auth
를 사용하면 Firebase 인증이 필요한 발신 요청의Authorization: Bearer
를 관리할 수 있습니다.
npm 저장소에서 검색하여 커뮤니티에서 제공하는 더 많은 Workbox 플러그인을 확인할 수 있습니다.
마지막으로 Workbox 플러그인을 빌드하여 공유하려는 경우 게시할 때 workbox-plugin
키워드를 추가합니다. 참여가 필요하다면 트위터(@WorkboxJS)를 통해 알려주세요.