Workbox v2에서 v3로 이전

이 가이드에서는 Workbox v2 설정에서 업그레이드할 때 필요한 변경사항의 예와 함께 Workbox v3에 도입된 브레이킹 체인지를 중점적으로 설명합니다.

현재 기존 sw-precache/sw-toolbox 조합을 사용 중이며 처음으로 Workbox로 전환하려는 경우 다음 다른 이전 가이드를 참고하세요.

v3 배경

Workbox의 v3 출시는 기존 코드베이스의 상당 부분을 리팩터링합니다. 중요한 목표는 다음과 같습니다.

  • 작업 상자 크기를 최소화합니다. 다운로드되고 실행되는 서비스 워커 런타임 코드의 양이 감소되었습니다. 모든 사용자를 모놀리식 번들을 선택하는 대신 사용 중인 특정 기능의 코드만 런타임에 가져옵니다.
  • Workbox에 CDN이 있습니다. Workbox 런타임 라이브러리에 액세스하기 위한 표준 옵션으로 완벽하게 지원되는 Google Cloud Storage 기반 CDN 호스팅을 제공하므로 Workbox를 쉽게 준비하고 실행할 수 있습니다.
  • 디버깅 및 로그 개선. 디버깅 및 로깅 환경이 크게 개선되었습니다. 디버그 로그는 Workbox가 localhost 출처에서 사용되고 프로덕션 빌드에서 모든 로깅 및 어설션이 제거될 때마다 기본적으로 사용 설정됩니다. Workbox v3에서 제공하는 디버그 로깅의 예
  • Webpack 플러그인 개선. workbox-webpack-plugin는 webpack 빌드 프로세스와 더 긴밀하게 통합되므로 빌드 파이프라인의 모든 애셋을 사전 캐시하려는 경우 구성 없이 사용 사례를 지원할 수 있습니다.

이러한 목표를 달성하고 이전 인터페이스에서 어색하거나 피해야 할 패턴으로 이어진 일부 요소를 정리하려면 v3 버전에 여러 브레이킹 체인지를 도입해야 했습니다.

이전 버전과 호환되지 않는 변경사항

빌드 구성

다음 변경사항은 공통 구성 옵션 세트를 공유하는 모든 빌드 도구 (workbox-build, workbox-cli, workbox-webpack-plugin)의 동작에 영향을 미칩니다.

  • 이전에는 'fastest' 핸들러 이름이 유효했으며 runtimeCaching를 구성할 때 'staleWhileRevalidate'의 별칭으로 처리되었습니다. 더 이상 유효하지 않으므로 개발자는 'staleWhileRevalidate'를 직접 사용하도록 전환해야 합니다.
  • 여러 runtimeCaching.options 속성 이름이 업데이트되었으며, 잘못된 구성이 사용되면 빌드가 실패하게 하는 추가 매개변수 유효성 검사가 적용되었습니다. 현재 지원되는 옵션 목록은 runtimeCaching 문서를 참고하세요.

작업 상자 백그라운드 동기화

  • 이제 maxRetentionTime 구성 매개변수가 밀리초가 아닌 분 단위로 해석됩니다.
  • 이제 대기열 이름을 나타내는 필수 문자열이 있습니다. 이 문자열은 플러그인 또는 독립형 클래스를 구성할 때 첫 번째 매개변수로 전달해야 합니다. (이전에는 옵션 속성으로 전달되었습니다.) 업데이트된 API 노출 영역은 문서를 참고하세요.

workbox-broadcast-cache-update

  • 이제 채널 이름을 나타내는 필수 문자열이 있습니다. 이 문자열은 플러그인 또는 독립형 클래스를 구성할 때 첫 번째 매개변수로 전달해야 합니다.

예를 들어 v2에서는 Plugin 클래스를 다음과 같이 초기화합니다.

new workbox.broadcastCacheUpdate.BroadcastCacheUpdatePlugin({
  channelName: 'cache-updates',
  headersToCheck: ['etag'],
});

v3에서 이와 동등한 사용법은 다음과 같습니다.

new workbox.broadcastUpdate.Plugin('cache-updates', {headersToCheck: ['etag']});

업데이트된 API 노출 영역은 문서를 참고하세요.

작업 상자 빌드

  • 기본적으로 glob 패턴 매칭은 이제 심볼릭 링크를 따르는 옵션 follow: true 및 '비정상적인' 오류를 덜 허용하는 strict: true를 사용하여 실행됩니다. 빌드 구성에서 globFollow: false 또는 globStrict: false를 설정하여 둘 중 하나를 사용 중지하고 이전 동작으로 돌아갈 수 있습니다.
  • workbox-build의 함수는 모두 함수가 반환하는 응답에서 추가 속성 warnings를 반환합니다. v2에서 치명적인 오류로 취급되던 일부 시나리오가 이제 허용되지만 문자열 배열인 warnings를 통해 보고됩니다.

v2에서는 다음과 같이 generateSW를 호출할 수 있습니다.

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size}) => console.log(`Precached ${count} files, totaling ${size} bytes.`))
  .catch((error) => console.error(`Something went wrong: ${error}`));

v3에서 동일한 코드를 사용할 수 있지만 warnings이 있는지 확인하고 로깅하는 것이 좋습니다.

const workboxBuild = require('workbox-build');

workboxBuild.generateSW({...})
  .then(({count, size, warnings}) => {
    for (const warning of warnings) {
      console.warn(warning);
    }
    console.log(`Precached ${count} files, totalling ${size} bytes.`);
  })
  .catch((error) => console.error(`Something went wrong: ${error}`));
  • v2에서 자체 맞춤 ManifestTransform 함수를 작성한 개발자는 객체에 매니페스트 배열을 반환해야 합니다 (즉, return manifestArray; 대신 return {manifest: manifestArray};를 사용해야 함). 이를 통해 플러그인에서 선택적 warnings 속성을 포함할 수 있습니다. 이 속성은 심각하지 않은 경고 정보를 포함하는 문자열 배열이어야 합니다.

v2에서 맞춤 ManifestTransform을 작성했다면 다음과 같이 코드를 작성합니다.

const cdnTransform = manifestEntries => {
  return manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
};

에는 다음과 같이 v3가 있습니다.

const cdnTransform = manifestEntries => {
  const manifest = manifestEntries.map(entry => {
    const cdnOrigin = 'https://example.com';
    if (entry.url.startsWith('/assets/')) {
      entry.url = cdnOrigin + entry.url;
    }
    return entry;
  });
  return {manifest, warnings: []};
};
  • getFileManifestEntries() 함수의 이름이 getManifest()로 변경되었으며 이제 반환된 프로미스에는 사전 캐시된 URL에 관한 추가 정보가 포함됩니다.

v2에서는 다음과 같이 코드를 작성합니다.

const manifestEntries = await workboxBuild.getFileManifestEntries({...});

v3에서 다음과 같이 다시 작성할 수 있습니다.

const {manifestEntries, count, size, warnings} = await workboxBuild.getManifest({...});

// Use manifestEntries like before.
// Optionally, log the new info returned in count, size, warnings.
  • generateFileManifest() 함수가 삭제되었습니다. 개발자는 대신 getManifest()를 호출하고 응답을 사용하여 적절한 형식으로 데이터를 디스크에 쓰는 것이 좋습니다.

작업 상자 캐시 만료

  • 플러그인 API는 동일하게 유지되어 대부분의 개발자가 사용하게 될 모드입니다. 그러나 API를 독립형 클래스로 사용하는 개발자에게 영향을 미치는 상당한 API 변경사항이 있습니다. 업데이트된 API 노출 영역은 문서를 참고하세요.

workbox-cli

개발자는 지원되는 전체 매개변수 집합에 대해 --help 플래그를 사용하여 CLI를 실행할 수 있습니다.

  • 바이너리 스크립트의 workbox-cli 별칭 지원이 삭제되었습니다. 이제 바이너리는 workbox로만 액세스할 수 있습니다.
  • v2 명령어 generate:swinject:manifest는 v3에서 generateSWinjectManifest로 이름이 변경되었습니다.
  • v2에서는 기본 구성 파일 (명시적으로 제공되지 않은 경우 사용됨)이 현재 디렉터리의 workbox-cli-config.js인 것으로 가정했습니다. v3에서는 workbox-config.js입니다.

종합하면 이는 v2에서 다음을 의미합니다.

$ workbox inject:manifest

v3의 workbox-cli-config.js에서 구성 읽기를 사용하여 '매니페스트 삽입' 빌드 프로세스를 실행합니다.

$ workbox injectManifest

동일한 작업을 실행하지만 workbox-config.js에서 구성을 읽습니다.

작업 상자 사전 캐싱

  • precache() 메서드는 이전에 캐시 수정을 모두 실행하고 캐시된 항목을 제공하도록 라우팅을 설정했습니다. 이제 precache()는 캐시 항목만 수정하며, 캐시된 응답을 제공할 경로를 등록하기 위해 새 메서드인 addRoute()가 노출되었습니다. 이전의 투인원 기능을 원하는 개발자는 precacheAndRoute() 호출로 전환할 수 있습니다.
  • WorkboxSW 생성자를 통해 구성되었던 여러 옵션이 이제 workbox.precaching.precacheAndRoute([...], options)options 매개변수로 전달됩니다. 구성되지 않은 경우 이러한 옵션의 기본값은 참조 문서에 나와 있습니다.
  • 기본적으로 파일 확장자가 없는 URL은 .html 확장자가 포함된 캐시 항목과 일치하는지 자동으로 확인됩니다. 예를 들어 (사전 캐시되지 않은) /path/to/index에 관한 요청이 발생하고 /path/to/index.html에 사전 캐시된 항목이 있는 경우 사전 캐시된 항목이 사용됩니다. 개발자는 옵션을 workbox.precaching.precacheAndRoute()에 전달할 때 {cleanUrls: false}를 설정하여 이 새로운 동작을 사용 중지할 수 있습니다.
  • workbox-broadcast-update가 더 이상 사전 캐시된 애셋의 캐시 업데이트를 알리도록 자동으로 구성되지 않습니다.

v2의 경우

const workboxSW = new self.WorkboxSW({
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
  precacheChannelName: 'precache-updates',
});
workboxSW.precache([...]);

에는 다음과 같이 v3가 있습니다.

workbox.precaching.addPlugins([
    new workbox.broadcastUpdate.Plugin('precache-updates')
]);

workbox.precaching.precacheAndRoute([...], {
  cleanUrls: false,
  directoryIndex: 'index.html',
  ignoreUrlParametersMatching: [/^utm_/],
});

작업 상자 라우팅

  • 이전에 WorkboxSW 객체의 workbox.router.* 네임스페이스를 통해 workbox-routing를 사용한 개발자는 새 네임스페이스인 workbox.routing.*로 전환해야 합니다.
  • 이제 경로가 먼저 등록된 순서로 평가됩니다. v2에서 사용된 Route 평가의 반대 순서이며, 마지막으로 등록된 Route가 우선 적용됩니다.
  • ExpressRoute 클래스 및 '익스프레스 스타일' 와일드 카드 지원이 삭제되었습니다. 이렇게 하면 workbox-routing의 크기가 상당히 줄어듭니다. workbox.routing.registerRoute()의 첫 번째 매개변수로 사용되는 문자열이 이제 일치검색으로 처리됩니다. 와일드 카드 또는 부분 일치는 RegExp에서 처리해야 합니다. 요청 URL의 일부 또는 전부와 일치하는 RegExp를 사용하면 경로를 트리거할 수 있습니다.
  • Router 클래스의 addFetchListener() 도우미 메서드가 삭제되었습니다. 개발자는 자체 fetch 핸들러를 명시적으로 추가하거나 workbox.routing에서 제공하는 인터페이스를 사용하여 fetch 핸들러를 암시적으로 만들 수 있습니다.
  • registerRoutes()unregisterRoutes() 메서드를 삭제했습니다. 단일 Route에서 작동하는 메서드의 버전은 변경되지 않았으며 대신 여러 경로를 한 번에 등록 또는 등록 취소해야 하는 개발자는 일련의 registerRoute() 또는 unregisterRoute() 호출을 실행해야 합니다.

v2의 경우

const workboxSW = new self.WorkboxSW();

workboxSW.router.registerRoute(
  '/path/with/.*/wildcard/',
  workboxSW.strategies.staleWhileRevalidate()
);

workboxSW.router.registerRoute(
  new RegExp('^https://example.com/'),
  workboxSW.strategies.networkFirst()
);

에는 다음과 같이 v3가 있습니다.

workbox.routing.registerRoute(
  new RegExp('^https://example.com/'),
  workbox.strategies.networkFirst()
);

workbox.routing.registerRoute(
  new RegExp('^/path/with/.*/wildcard'),
  workbox.strategies.staleWhileRevalidate()
);

workbox-strategies (이전 명칭: workbox-runtime-caching)

  • workbox-runtime-caching 모듈은 이제 공식적으로 workbox-strategies로 알려져 있으며 새 이름으로 npm에 게시되었습니다.
  • 캐시 이름을 제공하지 않은 채 전략에서 캐시 만료를 사용하면 더 이상 유효하지 않습니다. v2에서는 다음과 같이 가능했습니다.
workboxSW.strategies.staleWhileRevalidate({
  cacheExpiration: {maxEntries: 50},
});

이로 인해 기본 캐시에 항목이 만료되는 예기치 않은 상황이 발생합니다. v3에서는 캐시 이름이 필요합니다.

workboxSW.strategies.staleWhileRevalidate({
  cacheName: 'my-cache',
  plugins: [new workbox.expiration.Plugin({maxEntries: 50})],
});
  • cacheWillMatch 수명 주기 메서드의 이름이 cachedResponseWillBeUsed로 변경되었습니다. 개발자가 cacheWillMatch에 반응하는 자체 플러그인을 작성하지 않는 한 개발자에게 눈에 띄는 변화가 발생해서는 안 됩니다.
  • 전략을 구성할 때 플러그인을 지정하는 문법이 변경되었습니다. 각 플러그인은 전략 구성의 plugins 속성에 명시적으로 나열되어야 합니다.

v2의 경우

const workboxSW = new self.WorkboxSW();

const networkFirstStrategy = workboxSW.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  cacheExpiration: {
    maxEntries: 50,
  },
  cacheableResponse: {
    statuses: [0, 200],
  },
});

에는 다음과 같이 v3가 있습니다.

const networkFirstStrategy = workbox.strategies.networkFirst({
  cacheName: 'my-cache',
  networkTimeoutSeconds: 5,
  plugins: [
    new workbox.expiration.Plugin({maxEntries: 50}),
    new workbox.cacheableResponse.Plugin({statuses: [0, 200]}),
  ],
});

자세한 내용은 '플러그인 사용' 가이드를 참고하세요.

Workbox-sw

  • 내부적으로 workbox-sw는 경량의 '로더' 인터페이스로 재작성되었으며, 이 인터페이스는 기본 구성을 사용하고 런타임에 필요한 다른 모듈을 가져오는 역할을 합니다. 개발자는 WorkboxSW 클래스의 새 인스턴스를 구성하는 대신 전역 네임스페이스에 자동으로 노출되는 기존 인스턴스와 상호작용합니다.

이전 v2:

importScripts('<path to workbox-sw>/importScripts/workbox-sw.prod.v2.1.3.js');

const workbox = new WorkboxSW({
  skipWaiting: true,
  clientsClaim: true,
  // etc.
});

workbox.router.registerRoute(...);

v3에서는 workbox-sw.js 스크립트를 가져오기만 하면 됩니다. 그러면 즉시 사용할 수 있는 인스턴스가 전역 네임스페이스에서 workbox로 자동 제공됩니다.

importScripts('<path to workbox-sw>/3.0.0/workbox-sw.js');

// workbox is implicitly created and ready for use.
workbox.routing.registerRoute(...);
  • skipWaitingclientsClaim는 더 이상 WorkboxSW 생성자에 전달되는 옵션이 아닙니다. 대신 메서드 workbox.clientsClaim()workbox.skipWaiting()로 변경되었습니다.
  • 이전에 v2 생성자에서 지원되던 handleFetch 옵션이 v3에서는 더 이상 지원되지 않습니다. 가져오기 핸들러를 호출하지 않고 서비스 워커를 테스트하기 위해 유사한 기능이 필요한 개발자는 Chrome 개발자 도구에서 제공되는 '네트워크 우회' 옵션을 사용할 수 있습니다.
Chrome DevTools의 네트워크 우회 옵션

Workbox-webpack-plugin

이 플러그인은 상당히 다시 작성되었으며 많은 경우에 '제로 구성' 모드에서 사용할 수 있습니다. 업데이트된 API 노출 영역은 문서를 참고하세요.

  • 이제 API는 두 개의 클래스(GenerateSWInjectManifest)를 노출합니다. 이렇게 하면 모드 간 전환이 명확해집니다. 즉, swSrc의 존재에 따라 동작이 변경된 v2 동작과 비교했습니다.
  • 기본적으로 webpack 컴파일 파이프라인의 애셋은 사전 캐시되며 더 이상 globPatterns를 구성할 필요가 없습니다. globPatterns를 계속 사용하는 유일한 이유는 webpack 빌드에 포함되지 않은 애셋을 사전 캐시해야 하기 때문입니다. 일반적으로 v3 플러그인으로 이전할 때는 이전의 glob 기반 구성을 모두 삭제하는 것으로 시작하고 특별히 필요한 경우에만 다시 추가해야 합니다.

지원 받기

대부분의 이전은 간단할 것으로 예상됩니다. 이 가이드에서 다루지 않은 문제가 발생하면 GitHub에서 문제를 제기하여 알려주세요.