Skip to content

엔트리포인트

WXT는 확장 프로그램을 번들링할 때 entrypoints/ 디렉토리 내부의 파일을 입력으로 사용합니다. 이 파일들은 HTML, JS, CSS 또는 Vite에서 지원하는 파일 타입의 변형(Pug, TS, JSX, SCSS 등)일 수 있습니다.

다음은 엔트리포인트의 예제입니다:

html
📂 entrypoints/
   📂 popup/
      📄 index.html
      📄 main.ts
      📄 style.css
   📄 background.ts
   📄 content.ts

리스팅된 vs 언리스팅된

웹 확장 프로그램에는 두 가지 타입의 진입점이 있습니다:

  • 리스팅된: manifest.json에서 참조됨
  • 언리스팅된: manifest.json에서 참조되지 않음

WXT 문서의 나머지 부분에서는 리스팅된 진입점을 이름으로 참조합니다. 예를 들어:

  • 팝업
  • 옵션
  • 백그라운드
  • 콘텐츠 스크립트
  • 기타

"언리스팅된" 진입점의 몇 가지 예시:

  • 확장 프로그램이 설치될 때 표시되는 환영 페이지
  • 콘텐츠 스크립트가 페이지의 메인 월드에 주입하는 JS 파일

TIP

진입점이 리스팅되었는지 언리스팅되었는지 여부와 상관없이, 모든 진입점은 확장 프로그램에 번들링되어 런타임에 사용 가능합니다.

엔트리포인트 추가하기

엔트리포인트는 단일 파일 또는 내부에 index 파일이 있는 디렉토리로 정의할 수 있습니다.

html
📂 entrypoints/
   📄 background.ts
html
📂 entrypoints/
   📂 background/
      📄 index.ts

엔트리포인트의 이름은 엔트리포인트의 유형(목록에 포함된 것과 포함되지 않은 것)을 결정합니다. 이 예제에서 "background"는 "Background" 엔트리포인트의 이름입니다.

목록에 포함된 엔트리포인트와 해당 파일명 패턴의 전체 목록은 엔트리포인트 유형 섹션을 참조하세요.

Manifest 옵션 정의하기

대부분의 엔트리포인트는 manifest.json에 추가해야 하는 옵션이 있습니다. 하지만 WXT를 사용하면 별도의 파일에 옵션을 정의하는 대신, _엔트리포인트 파일 내부에서 이 옵션들을 정의_합니다.

예를 들어, 콘텐츠 스크립트의 matches를 정의하는 방법은 다음과 같습니다:

ts
// entrypoints/content.ts
export default defineContentScript({
  matches: ['*://*.wxt.dev/*'],
  main() {
    // ...
  },
});

HTML 엔트리포인트의 경우, 옵션은 <meta> 태그로 설정됩니다. 예를 들어, MV2 팝업에 page_action을 사용하려면 다음과 같이 작성합니다:

html
<!doctype html>
<html lang="en">
  <head>
    <meta name="manifest.type" content="page_action" />
  </head>
</html>

각 엔트리포인트 내부에서 설정 가능한 옵션 목록과 정의 방법은 엔트리포인트 타입 섹션을 참고하세요.

확장 프로그램을 빌드할 때, WXT는 엔트리포인트에 정의된 옵션을 확인하고 그에 따라 manifest를 생성합니다.

Entrypoint Types

백그라운드

Chrome DocsFirefox Docs

MV2에서는 백그라운드 스크립트가 백그라운드 페이지에 추가됩니다. MV3에서는 백그라운드가 서비스 워커로 변경됩니다.

FilenameOutput Path
entrypoints/background.[jt]s/background.js
entrypoints/background/index.[jt]s/background.js
ts
export default defineBackground(() => {
  // 백그라운드가 로드될 때 실행됨
});
ts
export default defineBackground({
  // 매니페스트 옵션 설정
  persistent: undefined | true | false,
  type: undefined | 'module',

  // 특정 빌드에서 백그라운드를 제거해야 할 경우 include/exclude 설정
  include: undefined | string[],
  exclude: undefined | string[],

  main() {
    // 백그라운드가 로드될 때 실행됨, 비동기로 사용 불가
  },
});

북마크

Chrome DocsFirefox Docs

FilenameOutput Path
entrypoints/bookmarks.html/bookmarks.html
entrypoints/bookmarks/index.html/bookmarks.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude를 설정하세요 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

콘텐츠 스크립트

Chrome DocsFirefox Docs

콘텐츠 스크립트에서 UI 생성 및 CSS 포함에 대한 자세한 내용은 콘텐츠 스크립트 UI를 참고하세요.

FilenameOutput Path
entrypoints/content.[jt]sx?/content-scripts/content.js
entrypoints/content/index.[jt]sx?/content-scripts/content.js
entrypoints/<name>.content.[jt]sx?/content-scripts/<name>.js
entrypoints/<name>.content/index.[jt]sx?/content-scripts/<name>.js
ts
export default defineContentScript({
  // 매니페스트 옵션 설정
  matches: string[],
  excludeMatches: undefined | [],
  includeGlobs: undefined | [],
  excludeGlobs: undefined | [],
  allFrames: undefined | true | false,
  runAt: undefined | 'document_start' | 'document_end' | 'document_idle',
  matchAboutBlank: undefined | true | false,
  matchOriginAsFallback: undefined | true | false,
  world: undefined | 'ISOLATED' | 'MAIN',

  // 특정 빌드에서 백그라운드를 제거할 경우 include/exclude 설정
  include: undefined | string[],
  exclude: undefined | string[],

  // 페이지에 CSS를 주입하는 방식 설정
  cssInjectionMode: undefined | "manifest" | "manual" | "ui",

  // 콘텐츠 스크립트가 등록되는 방식/시점 설정
  registration: undefined | "manifest" | "runtime",

  main(ctx: ContentScriptContext) {
    // 콘텐츠 스크립트가 로드될 때 실행되며, 비동기로 동작할 수 있음
  },
});

Devtools

Chrome DocsFirefox Docs

Devtools 예제를 따라 다양한 패널과 창을 추가할 수 있습니다.

FilenameOutput Path
entrypoints/devtools.html/devtools.html
entrypoints/devtools/index.html/devtools.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude를 설정하세요 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

History

Chrome DocsFirefox Docs

FilenameOutput Path
entrypoints/history.html/history.html
entrypoints/history/index.html/history.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude를 설정하세요 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

Newtab

Chrome DocsFirefox Docs

FilenameOutput Path
entrypoints/newtab.html/newtab.html
entrypoints/newtab/index.html/newtab.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>
    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude를 설정하세요 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

옵션

Chrome 문서Firefox 문서

FilenameOutput Path
entrypoints/options.html/options.html
entrypoints/options/index.html/options.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>옵션 제목</title>

    <!-- 매니페스트 옵션 커스터마이징 -->
    <meta name="manifest.open_in_tab" content="true|false" />
    <meta name="manifest.chrome_style" content="true|false" />
    <meta name="manifest.browser_style" content="true|false" />

    <!-- 특정 빌드에서 페이지를 제외하거나 포함할지 설정 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

팝업

Chrome DocsFirefox Docs

FilenameOutput Path
entrypoints/popup.html/popup.html
entrypoints/popup/index.html/popup.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <!-- manifest에서 `action.default_title` 설정 -->
    <title>기본 팝업 제목</title>

    <!-- manifest 옵션 커스터마이징 -->
    <meta
      name="manifest.default_icon"
      content="{
        16: '/icon-16.png',
        24: '/icon-24.png',
        ...
      }"
    />
    <meta name="manifest.type" content="page_action|browser_action" />
    <meta name="manifest.browser_style" content="true|false" />

    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude 설정 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

샌드박스

Chrome Docs

Chromium 전용

Firefox는 샌드박스 페이지를 지원하지 않습니다.

FilenameOutput Path
entrypoints/sandbox.html/sandbox.html
entrypoints/sandbox/index.html/sandbox.html
entrypoints/<name>.sandbox.html/<name>.html
entrypoints/<name>.sandbox/index.html/<name>.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>

    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude를 설정하세요 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

사이드 패널

Chrome DocsFirefox Docs

Chrome에서는 side_panel API를 사용하고, Firefox는 sidebar_action API를 사용합니다.

FilenameOutput Path
entrypoints/sidepanel.html/sidepanel.html
entrypoints/sidepanel/index.html/sidepanel.html
entrypoints/<name>.sidepanel.html/<name>.html`
entrypoints/<name>.sidepanel/index.html/<name>.html`
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>기본 사이드 패널 제목</title>

    <!-- 매니페스트 옵션 커스터마이징 -->
    <meta
      name="manifest.default_icon"
      content="{
        16: '/icon-16.png',
        24: '/icon-24.png',
        ...
      }"
    />
    <meta name="manifest.open_at_install" content="true|false" />
    <meta name="manifest.browser_style" content="true|false" />

    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude 설정 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

비공개 CSS

원하는 CSS 전처리기를 설정하려면 Vite 가이드를 참고하세요: https://vitejs.dev/guide/features.html#css-pre-processors

CSS 진입점은 항상 비공개로 처리됩니다. 콘텐츠 스크립트에 CSS를 추가하려면 콘텐츠 스크립트 문서를 참고하세요.

FilenameOutput Path
entrypoints/<name>.(css|scss|sass|less|styl|stylus)/<name>.css
entrypoints/<name>/index.(css|scss|sass|less|styl|stylus)/<name>.css
entrypoints/content.(css|scss|sass|less|styl|stylus)/content-scripts/content.css
entrypoints/content/index.(css|scss|sass|less|styl|stylus)/content-scripts/content.css
entrypoints/<name>.content.(css|scss|sass|less|styl|stylus)/content-scripts/<name>.css
entrypoints/<name>.content/index.(css|scss|sass|less|styl|stylus)/content-scripts/<name>.css
css
body {
  /* ... */
}

비공개 페이지

FilenameOutput Path
entrypoints/<name>.html/<name>.html
entrypoints/<name>/index.html/<name>.html
html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Title</title>

    <!-- 특정 빌드에서 페이지를 제외하거나 포함하려면 include/exclude 설정 -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

페이지는 /<name>.html에서 접근 가능합니다:

ts
const url = browser.runtime.getURL('/<name>.html');

console.log(url); // "chrome-extension://<id>/<name>.html"

비공개 스크립트

FilenameOutput Path
entrypoints/<name>.[jt]sx?/<name>.js
entrypoints/<name>/index.[jt]sx?/<name>.js
ts
export default defineUnlistedScript(() => {
  // 스크립트가 로드될 때 실행됨
});
ts
export default defineUnlistedScript({
  // 특정 빌드에서 스크립트를 제외하려면 include/exclude 설정
  include: undefined | string[],
  exclude: undefined | string[],

  main() {
    // 스크립트가 로드될 때 실행됨
  },
});

스크립트는 /<name>.js에서 접근 가능합니다:

ts
const url = browser.runtime.getURL('/<name>.js');

console.log(url); // "chrome-extension://<id>/<name>.js"

필요한 곳에서 스크립트를 로드하고 실행하는 것은 여러분의 책임입니다. 필요한 경우, 스크립트나 관련 스타일시트를 web_accessible_resources에 추가하는 것을 잊지 마세요.