서비스 워커의 ES 모듈

importScripts()의 최신 대안

배경

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

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

사용 사례

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

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

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

현재 제한사항

정적 가져오기만

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

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

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

다른 직원들은 어떨까요?

'전용' 작업자의 ES 모듈(new Worker('...', {type: 'module'})로 구성됨)에 대한 지원이 더 광범위해졌으며 버전 80 이후 Chrome 및 Edge와 Safari 최신 버전에서도 지원되었습니다. 정적 및 동적 ES 모듈 가져오기 모두 전용 worker에서 지원됩니다.

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 제공)_