서비스 워커의 ES 모듈

importScripts()의 최신 대안입니다.

배경

ES 모듈은 오랫동안 개발자의 인기를 얻고 있습니다. 다양한 이점 외에도 공유 코드를 한 번만 출시하고 브라우저와 Node.js와 같은 대체 런타임에서 실행할 수 있는 범용 모듈 형식을 제공합니다. 모든 최신 브라우저에서 일부 ES 모듈을 지원하지만 코드를 실행할 수 있는 모든 곳에서 지원되는 것은 아닙니다. 특히 브라우저의 서비스 워커 내에서 ES 모듈을 가져오는 기능이 점점 더 널리 사용되고 있습니다.

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

사용 사례

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

ES 모듈 이전에 이러한 방식으로 코드를 공유하려면 불필요한 상용구가 포함된 이전의 '범용' 모듈 형식(예: UMD)을 사용하고 전역으로 노출된 변수를 변경하는 코드를 작성해야 했습니다.

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

현재 제한사항

정적 가져오기만

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

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

결국 이 제한이 해제되고 동적 ES 모듈 가져오기가 허용될 수 있습니다. 지금은 서비스 워커 내에서만 정적 문법을 사용하세요.

다른 근로자는 어떨까요?

new Worker('...', {type: 'module'})로 생성된 '전용' 작업자에서 ES 모듈을 지원하는 기능은 더 광범위하게 사용되며 버전 80부터 Chrome 및 Edge와 최신 버전의 Safari에서 지원되었습니다. 전용 작업자에서는 정적 ES 모듈 가져오기와 동적 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 문제의 논의를 참고하여 권장사항을 확인할 수 있습니다.

_사진: Unsplash블라디오 파우노비치_