서비스 워커의 ES 모듈

importScripts()의 최신 대안

배경

ES 모듈은 한동안 개발자가 즐겨 사용한 모듈입니다. 기타 여러 이점 외에도 공유 코드를 한 번 출시하여 브라우저 및 Node.js와 같은 대체 런타임에서 실행할 수 있는 범용 모듈 형식을 제공합니다. 모든 최신 브라우저가 일부 ES 모듈을 지원하지만 모두 코드가 실행될 수 있는 모든 위치를 지원하는 것은 아닙니다. 특히 브라우저의 서비스 워커 내부에서 ES 모듈을 가져오기 위한 지원이 이제 더욱 폭넓게 제공되기 시작했습니다.

이 문서에서는 일반적인 브라우저 전반에서 서비스 워커의 현재 ES 모듈 지원 상태와 피해야 할 몇 가지 주의사항, 이전 버전과 호환되는 서비스 워커 코드를 제공하기 위한 권장사항을 자세히 설명합니다.

사용 사례

서비스 워커 내부에 있는 ES 모듈의 이상적인 사용 사례는 ES 모듈을 지원하는 다른 런타임과 공유되는 최신 라이브러리 또는 구성 코드를 로드하는 것입니다.

불필요한 상용구를 포함하는 UMD와 같은 이전의 '범용' 모듈 형식을 사용하는 ES 모듈 이전에 이러한 방식으로 코드 공유를 시도하고 전역적으로 노출된 변수를 변경하는 코드를 작성하는 것이었습니다.

ES 모듈을 통해 가져온 스크립트는 importScripts()동작과 일치하도록 콘텐츠가 변경되면 서비스 워커 업데이트 흐름을 트리거할 수 있습니다.

현재 제한사항

정적 가져오기만

ES 모듈은 정적으로 import ... from '...' 구문을 사용하거나 import() 메서드를 사용하여 동적으로 가져오는 두 가지 방법 중 하나로 가져올 수 있습니다. 현재 서비스 워커 내에서는 정적 문법만 지원됩니다.

이 제한은 importScripts() 사용에 적용되는 유사한 제한과 유사합니다. 동적 importScripts() 호출은 서비스 워커 내에서 작동하지 않으며, 기본적으로 동기식인 모든 importScripts() 호출은 서비스 워커가 install 단계를 완료하기 전에 완료되어야 합니다. 이 제한을 통해 브라우저에서 설치 중에 서비스 워커의 구현에 필요한 모든 JavaScript 코드를 알고 있고 암시적으로 캐시할 수 있습니다.

결국 이 제한은 해제될 수 있으며 동적 ES 모듈 가져오기가 허용될 수 있습니다. 지금은 서비스 워커 내에서 정적 구문만 사용해야 합니다.

다른 직원은 어떤가요?

'전용' 작업자의 ES 모듈(new Worker('...', {type: 'module'})로 구성된 모듈)에 대한 지원이 더 광범위하게 지원되고 있으며 버전 80부터 Chrome과 Edge는 물론 Safari의 최신 버전에서도 지원되고 있습니다. 정적 및 동적 ES 모듈 가져오기 모두 전용 작업자에서 지원됩니다.

Chrome 및 Edge는 버전 83부터 공유 작업자의 ES 모듈을 지원했지만 현재 다른 브라우저에서는 지원되지 않습니다.

맵 가져오기에 대한 지원 없음

가져오기 맵을 사용하면 런타임 환경에서 모듈 지정자를 다시 작성할 수 있습니다(예: ES 모듈을 로드할 수 있는 기본 CDN의 URL 앞에 추가).

Chrome 및 Edge 버전 89 이상은 가져오기 맵을 지원하지만 현재 서비스 워커에서는 사용할 수 없습니다.

브라우저 지원

서비스 워커의 ES 모듈은 버전 91부터 Chrome 및 Edge에서 지원됩니다.

Safari는 기술 미리보기 122 출시에서 지원을 추가했으며 개발자는 향후 Safari 안정화 버전에서 이 기능이 출시될 예정입니다.

예시 코드

다음은 웹 앱의 window 컨텍스트에서 공유 ES 모듈을 사용하는 동시에 동일한 ES 모듈을 사용하는 서비스 워커를 등록하는 기본적인 예입니다.

// Inside config.js:
export const cacheName = 'my-cache';
// Inside your web app:
<script type="module">
  import {cacheName} from './config.js';
  // Do something with cacheName.

  await navigator.serviceWorker.register('es-module-sw.js', {
    type: 'module',
  });
</script>
// Inside es-module-sw.js:
import {cacheName} from './config.js';

self.addEventListener('install', (event) => {
  event.waitUntil((async () => {
    const cache = await caches.open(cacheName);
    // ...
  })());
});

이전 버전과의 호환성

모든 브라우저가 서비스 워커의 ES 모듈을 지원하면 위의 예는 문제없이 작동하지만, 이 문서를 작성하는 시점에서는 그렇지 않습니다.

기본 지원 기능이 없는 브라우저를 수용하려면 ES 모듈 호환 번들러를 통해 서비스 워커 스크립트를 실행하여 모든 모듈 코드를 인라인으로 포함하고 이전 브라우저에서 작동하는 서비스 워커를 만들 수 있습니다. 또는 가져오려는 모듈이 이미 IIFE 또는 UMD 형식으로 번들로 제공되는 경우 importScripts()를 사용하여 가져올 수 있습니다.

ES 모듈을 사용하는 버전과 사용하지 않는 두 가지 버전의 서비스 워커를 사용할 수 있게 되면 현재 브라우저에서 지원하는 항목을 감지하고 해당 서비스 워커 스크립트를 등록해야 합니다. 지원 감지를 위한 권장사항은 현재 다양하지만 이 GitHub 문제의 설명을 따라 권장사항을 확인할 수 있습니다.

_사진: Vlado Paunovic, Unsplash_