Skip to content

엔트리포인트 로더

빌드 시점에 매니페스트와 기타 파일을 생성하려면, WXT는 각 엔트리포인트를 가져와 콘텐츠 스크립트의 matches와 같은 옵션을 얻어야 합니다. HTML 파일의 경우 이 과정은 간단합니다. 하지만 JS/TS 엔트리포인트의 경우 더 복잡한 과정을 거칩니다.

JS/TS 엔트리포인트를 로드할 때, 이들은 일반적으로 실행되는 browser 환경이 아닌 NodeJS 환경에서 가져옵니다. 이로 인해 브라우저 전용 코드를 NodeJS 환경에서 실행할 때 발생하는 문제가 생길 수 있습니다. 예를 들어, 전역 변수가 누락되는 경우가 있습니다.

WXT는 이 과정에서 발생할 수 있는 오류를 방지하기 위해 몇 가지 전처리 단계를 거칩니다:

  1. linkedom을 사용하여 window, document 등과 같은 일부 브라우저 전역 변수를 사용할 수 있게 합니다.
  2. @webext-core/fake-browser를 사용하여 확장 프로그램에서 기대하는 chromebrowser 전역 변수의 가짜 버전을 생성합니다.
  3. JS/TS 코드를 전처리하여 main 함수를 제거하고 파일에서 사용되지 않는 코드를 트리쉐이킹합니다.

그러나 이 과정은 완벽하지 않습니다. 브라우저에서 찾을 수 있는 모든 전역 변수를 설정하지 않으며, API가 다르게 동작할 수 있습니다. 따라서 엔트리포인트의 main 함수 외부에서 브라우저나 확장 프로그램 API를 사용하지 않는 것이 좋습니다!

TIP

엔트리포인트를 가져오는 동안 오류가 발생한다면, wxt prepare --debug를 실행하여 이 과정에 대한 자세한 정보를 확인할 수 있습니다. 디버깅 시 WXT는 전처리된 코드를 출력하여 문제를 식별하는 데 도움을 줍니다.

환경이 폴리필되고 코드가 전처리되면, 엔트리포인트 로더가 코드를 가져와 기본 내보내기에서 옵션을 추출합니다.

엔트리포인트를 로드하는 두 가지 옵션이 있습니다:

  1. vite-node - v0.19.0부터 기본값
  2. jiti (더 이상 사용되지 않음, v0.20.0에서 제거 예정) - v0.19.0 이전의 기본값

vite-node

0.19.0 버전부터 WXT는 Vitest와 Nuxt에서 사용하는 동일한 도구인 vite-node를 사용하여 엔트리포인트 파일을 불러옵니다. 이 도구는 확장 프로그램을 빌드할 때 사용하는 Vite 설정을 그대로 재사용하므로 가장 안정적인 엔트리포인트 로더 역할을 합니다.

jiti

jiti를 활성화하려면:

ts
export default defineConfig({
  entrypointLoader: 'jiti',
});

이것은 WXT가 TS 파일을 가져오기 위해 사용했던 원래 방식입니다. 하지만 vite-node와 같은 vite 플러그인을 지원하지 않기 때문에, 추가적인 전처리 단계를 거칩니다: 코드에서 모든 import를 제거합니다.

이것은 콘텐츠 스크립트의 matches나 다른 옵션과 같이, JS 엔트리포인트에서 main 함수 외부에서 import된 변수를 사용할 수 없다는 것을 의미합니다:

ts
// entrypoints/content.ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns';

export default defineContentScript({
  matches: GOOGLE_MATCHES,
  main() {
    // ...
  },
});
$ wxt build
wxt build

WXT 0.14.1
ℹ Building chrome-mv3 for production with Vite 5.0.5
✖ Command failed after 360 ms

[8:55:54 AM]  ERROR  entrypoints/content.ts: Cannot use imported variable "GOOGLE_MATCHES" before main function.

일반적으로 이 오류는 옵션을 공유 파일로 추출하려고 하거나 main 함수 외부에서 코드를 실행할 때 발생합니다. 위의 예제를 수정하려면, 엔트리포인트를 정의할 때 import된 값 대신 리터럴 값을 사용하세요:

ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns'; 

export default defineContentScript({
  matches: GOOGLE_MATCHES, 
  matches: ['*//*.google.com/*'], 
  main() {
    // ...
  },
});