모듈 작업자로 웹 스레딩

이제 웹 작업자의 JavaScript 모듈을 사용하여 복잡하고 어려운 작업을 백그라운드 스레드로 더 쉽게 이동할 수 있습니다.

JavaScript는 단일 스레드이므로 한 번에 하나의 작업만 수행할 수 있습니다. 이것은 직관적이고 많은 웹 사례에서 잘 작동하지만 필요할 때 문제가 될 수 있습니다. 데이터 처리, 파싱, 계산 또는 분석과 같은 어려운 작업을 수행할 수 있습니다. 점점 더 복잡한 애플리케이션이 웹 상에서 제공될 때 멀티 스레드 및 가장 적합합니다

웹 플랫폼에서 스레딩 및 동시 로드의 기본 프리미티브는 웹 환경 작업자 API 작업자는 운영체제 위에 위치한 경량의 추상화임 API를 전달하는 메시지를 노출하는 스레드 스레드 간 통신을 지원합니다 이는 비용이 많이 드는 계산을 수행하거나 대규모 데이터 세트에서 작업하므로 기본 스레드가 원활하게 실행되도록 하나 이상의 백그라운드 스레드에서 비용이 많이 드는 작업을 지원합니다.

다음은 worker 스크립트가 메인 스레드를 생성하고 자체 메시지를 다시 보내 응답합니다.

page.js:

const worker = new Worker('worker.js');
worker.addEventListener('message', e => {
  console.log(e.data);
});
worker.postMessage('hello');

worker.js:

addEventListener('message', e => {
  if (e.data === 'hello') {
    postMessage('world');
  }
});

Web Worker API는 대부분의 브라우저에서 10년 이상 사용되어 왔습니다. 하지만 작업자가 뛰어난 브라우저 지원을 받고 최적화가 잘 되어 있으므로 JavaScript 모듈보다 이전 버전이었습니다 worker를 설계할 때 모듈 시스템이 없었기 때문에 API는 코드를 작업자에 로드하고 스크립트를 작성하는 과정은 동기 스크립트와 유사하게 유지되었습니다. 2009년에 보편적인 로드 방식을 채택했습니다.

기록: 기본 작업자

Worker 생성자는 기존 스크립트 URL은 문서 URL을 기준으로 합니다. 새 작업자 인스턴스에 대한 참조가 즉시 반환되며 이 코드는 메시지 인터페이스뿐 아니라 terminate() 메서드를 노출하여 즉시 중단하고 작업자를 소멸시킵니다.

const worker = new Worker('worker.js');

importScripts() 함수는 추가 코드를 로드하기 위해 웹 작업자 내에서 사용할 수 있지만 각 스크립트를 가져오고 평가하기 위해 작업자의 실행을 일시중지합니다. 또한 스크립트를 실행함 기존 <script> 태그와 같이 전역 범위에 있어야 합니다. 즉, 한 스크립트의 변수가 덮어쓰게 됩니다

worker.js:

importScripts('greet.js');
// ^ could block for seconds
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

// global to the whole worker
function sayHello() {
  return 'world';
}

이러한 이유로 웹 작업자는 역사적으로 휴대전화의 아키텍처에 애플리케이션입니다. 개발자들은 기발한 도구와 임시방편 장치를 개발하여 최신 개발 방식을 포기하지 않고 웹 작업자를 사용할 수 있습니다. 예를 들어 번들러는 webpack은 importScripts()를 사용하여 생성된 코드에 작은 모듈 로더 구현을 삽입합니다. 지원하지만 변수 충돌을 방지하고 시뮬레이션하기 위해 함수에서 모듈을 래핑합니다. 종속 항목 가져오기 및 내보내기를 수행할 수 있습니다

모듈 작업자 입력

웹 작업자를 위한 새로운 모드: JavaScript의 인체공학과 성능 측면의 이점 제공 모듈은 모듈 작업자라고 하는 Chrome 80에서 제공됩니다. 이 이제 Worker 생성자가 새 {type:"module"} 옵션을 허용합니다. 이 옵션은 스크립트 로드 및 <script type="module">에 맞게 실행

const worker = new Worker('worker.js', {
  type: 'module'
});

모듈 작업자는 표준 JavaScript 모듈이므로 import 및 export 문을 사용할 수 있습니다. 따라서 모든 JavaScript 모듈과 함께 종속 항목은 주어진 컨텍스트 (기본 스레드, 등)가 있으며, 이후의 모든 가져오기는 이미 실행된 모듈 인스턴스를 참조합니다. 로드 JavaScript 모듈의 실행도 브라우저에 의해 최적화됩니다. 모듈의 종속 항목은 모듈이 실행되기 전에 로드되므로 전체 모듈 트리를 있습니다. 모듈을 로드하면 파싱된 코드도 캐시됩니다. 즉, 기본 애플리케이션에서 사용되는 모듈은 한 번만 파싱하면 됩니다.

또한 JavaScript 모듈로 이동하면 동적 속성 import를 해서는 안 됩니다. 작업을 수행합니다 동적 가져오기는 importScripts()를 사용하여 종속 항목을 로드하는 것보다 훨씬 더 명시적입니다. 가져온 모듈의 내보내기가 전역 변수에 의존하지 않고 반환되기 때문입니다.

worker.js:

import { sayHello } from './greet.js';
addEventListener('message', e => {
  postMessage(sayHello());
});

greet.js:

import greetings from './data.js';
export function sayHello() {
  return greetings.hello;
}

최적의 성능을 보장하기 위해 이전 importScripts() 메서드는 모듈 내에서 사용할 수 없습니다. 있습니다 JavaScript 모듈을 사용하도록 작업자를 전환하면 모든 코드가 엄격한 모드로 설정합니다. 다른 주목할 만한 변경사항은 JavaScript 모듈의 최상위 범위에 있는 this 값이 undefined, 기존 worker에서는 값이 작업자의 전역 범위입니다. 다행히도 항상 전역 범위 참조를 제공하는 self 전역 변수였습니다. 제공 국가: 서비스 워커를 포함한 모든 유형의 작업자와 DOM에서 사용할 수 있습니다.

modulepreload로 worker 미리 로드

모듈 작업자와 함께 제공되는 상당한 성능 개선 사항 중 하나는 종속 항목이 포함됩니다 모듈 작업자를 사용하면 스크립트가 표준으로 로드되고 실행됩니다. JavaScript 모듈: modulepreload를 사용하여 미리 로드하고 파싱할 수도 있습니다.

<!-- preloads worker.js and its dependencies: -->
<link rel="modulepreload" href="worker.js">

<script>
  addEventListener('load', () => {
    // our worker code is likely already parsed and ready to execute!
    const worker = new Worker('worker.js', { type: 'module' });
  });
</script>

미리 로드된 모듈은 기본 스레드와 모듈 작업자 모두 사용할 수도 있습니다. 이는 두 컨텍스트 모두, 또는 미리 알 수 없는 모듈을 가져올 수도 있습니다. 모듈을 기본 스레드에서 사용할지 또는 작업자에서 사용할지를 지정합니다.

이전에는 웹 작업자 스크립트를 미리 로드하는 데 사용할 수 있는 옵션이 제한되었으며 반드시 신뢰할 수 있어야 합니다 기존 노동자에게는 자신만의 '직원'이 있음 리소스 유형을 선택하고 브라우저에서 <link rel="preload" as="worker">를 구현했습니다. 따라서 기본 기법은 웹 워커를 미리 로드하는 데 사용할 수 있었던 <link rel="prefetch">는 HTTP 캐시에 저장된 값을 확인할 수 있습니다 올바른 캐싱 헤더와 함께 사용하면 가능한 작업자 인스턴스화를 위해 작업자 스크립트 다운로드를 기다릴 필요가 없습니다. 그러나 modulepreload 이 기법은 종속 항목 미리 로드 또는 사전 파싱을 지원하지 않았습니다.

공유 작업자의 경우는 어떤가요?

공유 작업자는 Chrome 83부터 JavaScript 모듈을 지원하도록 업데이트되었습니다. 전담 직원과 마찬가지로 {type:"module"} 옵션을 사용하여 공유 작업자를 구성하면 이제 작업자 스크립트가 모듈을 사용하는 것이 좋습니다.

const worker = new SharedWorker('/worker.js', {
  type: 'module'
});

JavaScript 모듈을 지원하기 전에는 SharedWorker() 생성자가 URL 및 선택적 name 인수 기존 공유 작업자 사용에서는 계속 작동합니다. 하지만 모듈 공유 작업자를 만들려면 새 options 인수를 사용해야 합니다. 사용 가능한 옵션 다음을 대체하는 name 옵션을 포함하여 전용 작업자와 동일합니다. 이전 name 인수

서비스 워커는 어떤가요?

서비스 워커 사양은 이미 업데이트된 자바스크립트 모듈을 진입점으로, 모듈 작업자와 동일한 {type:"module"} 옵션을 사용합니다. 하지만 브라우저에서는 아직 이 변경사항이 구현되지 않았습니다. 이렇게 하면 다음 코드를 사용하여 JavaScript 모듈을 사용하여 서비스 워커를 인스턴스화할 수 있습니다.

navigator.serviceWorker.register('/sw.js', {
  type: 'module'
});

이제 사양이 업데이트되었으므로 브라우저에서 새로운 동작을 구현하기 시작했습니다. JavaScript를 가져오는 것과 관련하여 몇 가지 추가 복잡성이 있기 때문에 시간이 걸립니다. 서비스 워커로 전환할 수 있습니다 서비스 워커 등록에서 가져온 스크립트를 비교해야 함 이전에 캐시된 버전을 복원하는 것이 업데이트 트리거 여부를 결정하며 이는 JavaScript 모듈에 대해 구현되어야 합니다. 서비스 워커에 사용될 수 있습니다. 또한 서비스 워커는 서비스 워커에 의해 캐시를 하지 않는 경우가 있습니다. 업데이트 확인 중.

추가 리소스 및 추가 자료