FAQ
WXT를 사용하는 방법이나 동작 방식에 대해 자주 묻는 질문들입니다.
왜 콘텐츠 스크립트가 매니페스트에 추가되지 않나요?
개발 중에는 WXT가 콘텐츠 스크립트를 동적으로 등록합니다. 이렇게 하면 파일을 저장할 때 전체 확장 프로그램을 다시 로드하지 않고도 개별적으로 스크립트를 다시 로드할 수 있습니다.
개발 중에 등록된 콘텐츠 스크립트 목록을 확인하려면 서비스 워커의 콘솔을 열고 다음 명령을 실행하세요:
await chrome.scripting.getRegisteredContentScripts();
개발 중 브라우저 자동 열림을 비활성화하려면 어떻게 해야 하나요?
자세한 내용은 https://wxt.dev/guide/essentials/config/browser-startup.html#disable-opening-browser 를 참고하세요.
개발 중에 웹사이트에 로그인 상태를 유지하려면 어떻게 해야 하나요?
자세한 내용은 https://wxt.dev/guide/essentials/config/browser-startup.html#persist-data 를 참고하세요.
내 컴포넌트 라이브러리가 콘텐츠 스크립트에서 작동하지 않아요!
createShadowRootUi
를 사용할 때 주로 두 가지 문제(또는 둘 다)로 인해 발생합니다:
스타일이
ShadowRoot
외부에 추가됨Details
일부 컴포넌트 라이브러리는
<style>
또는<link>
엘리먼트를 추가해 CSS를 페이지에 직접 삽입합니다. 이 엘리먼트는 기본적으로 문서의<head>
에 배치됩니다. 이로 인해 스타일이ShadowRoot
외부에 위치하게 되고,ShadowRoot
의 격리로 인해 스타일이 UI에 적용되지 않습니다.라이브러리가 이렇게 동작한다면, 스타일을 배치할 위치를 라이브러리에 알려줘야 합니다. 다음은 인기 있는 컴포넌트 라이브러리의 문서입니다:
- Ant Design:
StyleProvider
- Mantine:
MantineProvider#getRootElement
및MantineProvider#cssVariablesSelector
위에 나열되지 않은 라이브러리를 사용한다면, 문서나 이슈에서 "shadow root", "shadow dom", "css container"를 검색해 보세요. 모든 라이브러리가 shadow DOM을 지원하는 것은 아니므로, 이 기능을 요청하기 위해 이슈를 열어야 할 수도 있습니다.
Antd 스타일을 설정하는 예제입니다:
tsximport { StyleProvider } from '@ant-design/cssinjs'; import ReactDOM from 'react-dom/client'; import App from './App.tsx'; const ui = await create`ShadowRoot`Ui(ctx, { // ... onMount: (container, shadow) => { const cssContainer = shadow.querySelector('head')!; const root = ReactDOM.createRoot(container); root.render( <StyleProvider container={cssContainer}> <App /> </StyleProvider>, ); return root; }, });
- Ant Design:
UI 엘리먼트가
ShadowRoot
외부에 추가됨Details
이 문제는 주로
Teleport
나Portal
컴포넌트가 DOM의 다른 위치(보통 문서의<body>
)에 엘리먼트를 렌더링할 때 발생합니다. 이는 주로 다이얼로그나 팝오버 컴포넌트에서 사용됩니다. 이렇게 하면 엘리먼트가ShadowRoot
외부에 렌더링되므로 스타일이 적용되지 않습니다.이 문제를 해결하려면, 앱에 타겟을 제공하고
Teleport
/Portal
에 타겟을 전달해야 합니다.먼저,
ShadowRoot
의<body>
엘리먼트(문서의<body>
가 아님)에 대한 참조를 저장합니다:tsimport { createApp } from 'vue'; import App from './App.vue'; const ui = await create`ShadowRoot`Ui(ctx, { // ... onMount: (container, shadow) => { const teleportTarget = shadow.querySelector('body')!; const app = createApp(App) .provide('TeleportTarget', teleportTarget) .mount(container); return app; }, }); ui.mount();
tsx// hooks/PortalTargetContext.ts import { createContext } from 'react'; export const PortalTargetContext = createContext<HTMLElement>(); // entrypoints/example.content.ts import ReactDOM from 'react-dom/client'; import App from './App.tsx'; import PortalTargetContext from '~/hooks/PortalTargetContext'; const ui = await create`ShadowRoot`Ui(ctx, { // ... onMount: (container, shadow) => { const portalTarget = shadow.querySelector('body')!; const root = ReactDOM.createRoot(container); root.render( <PortalTargetContext.Provider value={portalTarget}> <App /> </PortalTargetContext.Provider>, ); return root; }, }); ui.mount();
그런 다음, UI의 일부를 DOM의 다른 위치로 이동시킬 때 이 참조를 사용합니다:
vue<script lang="ts" setup> import { Teleport } from 'vue'; const teleportTarget = inject('TeleportTarget'); </script> <template> <div> <Teleport :to="teleportTarget"> <dialog>My dialog</dialog> </Teleport> </div> </template>
tsximport { useContext } from 'react'; import { createPortal } from 'react-dom'; import PortalTargetContext from '~/hooks/PortalTargetContext'; const MyComponent = () => { const portalTarget = useContext(PortalTargetContext); return <div>{createPortal(<dialog>My dialog</dialog>, portalTarget)}</div>; };
두 문제는 동일한 원인에서 비롯됩니다: 라이브러리가 무언가를 ShadowRoot
외부에 배치하고, ShadowRoot
의 격리로 인해 CSS가 UI에 적용되지 않습니다.
두 문제는 동일한 해결책이 있습니다: 라이브러리가 엘리먼트를 ShadowRoot
외부가 아닌 내부에 배치하도록 지시하세요. 각 문제에 대한 자세한 정보와 예제 해결책은 위의 내용을 참고하세요.