Assets
/assets
디렉토리
<srcDir>/assets/
디렉토리 안에서 가져오거나 참조된 모든 리소스는 WXT의 번들러에 의해 처리됩니다.
다음은 이 리소스에 접근하는 방법입니다:
import imageUrl from '~/assets/image.png';
const img = document.createElement('img');
img.src = imageUrl;
<img src="~/assets/image.png" />
.bg-image {
background-image: url(~/assets/image.png);
}
/public
디렉토리
<srcDir>/public/
안에 있는 파일들은 WXT의 번들러를 거치지 않고 그대로 출력 폴더로 복사됩니다.
이 파일들에 접근하는 방법은 다음과 같습니다:
import imageUrl from '/image.png';
const img = document.createElement('img');
img.src = imageUrl;
<img src="/image.png" />
.bg-image {
background-image: url(/image.png);
}
콘텐츠 스크립트 내부
콘텐츠 스크립트 내부의 에셋은 약간 다르게 동작합니다. 기본적으로 에셋을 임포트하면, Vite는 해당 에셋의 경로만 반환합니다. 이는 Vite가 동일한 호스트명에서 에셋을 로드한다고 가정하기 때문입니다.
하지만 콘텐츠 스크립트 내부에서는 호스트명이 탭에 설정된 값이 됩니다. 따라서 에셋을 수동으로 가져오거나 <img>
태그의 src
로 사용하려고 하면, 확장 프로그램이 아닌 탭의 웹사이트에서 로드됩니다.
이 문제를 해결하려면 browser.runtime.getURL
을 사용하여 이미지를 전체 URL로 변환해야 합니다:
// entrypoints/content.ts
import iconUrl from '/icon/128.png';
export default defineContentScript({
matches: ['*://*.google.com/*'],
main() {
console.log(iconUrl); // "/icon/128.png"
console.log(browser.runtime.getURL(iconUrl)); // "chrome-extension://<id>/icon/128.png"
},
});
WASM
.wasm
파일을 로드하는 방법은 패키지마다 크게 다르지만, 대부분 기본적인 설정을 따릅니다: JS API를 사용하여 .wasm
파일을 로드하고 실행합니다.
확장 프로그램의 경우, 이는 두 가지를 의미합니다:
.wasm
파일이 로드될 수 있도록 출력 폴더에 존재해야 합니다.- 보통 NPM 패키지에서 제공하는 JS API를 가져와
.wasm
파일을 로드하고 초기화해야 합니다.
예를 들어, 콘텐츠 스크립트가 TS 코드를 AST로 파싱해야 한다고 가정해 봅시다. 이를 위해 @oxc-parser/wasm
을 사용할 것입니다!
먼저, .wasm
파일을 출력 디렉토리로 복사해야 합니다. WXT 모듈을 사용하여 이를 수행합니다:
// modules/oxc-parser-wasm.ts
import { resolve } from 'node:path';
export default defineWxtModule((wxt) => {
wxt.hook('build:publicAssets', (_, assets) => {
assets.push({
absoluteSrc: resolve(
'node_modules/@oxc-parser/wasm/web/oxc_parser_wasm_bg.wasm',
),
relativeDest: 'oxc_parser_wasm_bg.wasm',
});
});
});
wxt build
를 실행하면, WASM 파일이 .output/chrome-mv3
폴더에 복사된 것을 확인할 수 있습니다!
다음으로, 이 파일이 콘텐츠 스크립트에 있고 네트워크를 통해 WASM 파일을 가져와 로드할 것이므로, web_accessible_resources
에 파일을 추가해야 합니다:
// wxt.config.ts
export default defineConfig({
manifest: {
web_accessible_resources: [
{
// 콘텐츠 스크립트에서도 이 매칭을 사용할 것입니다.
matches: ['*://*.github.com/*'],
// WXT 모듈의 `relativeDest`와 동일한 경로를 사용합니다.
resources: ['/oxc_parser_wasm_bg.wasm'],
},
],
},
});
마지막으로, 콘텐츠 스크립트 내에서 .wasm
파일을 로드하고 초기화하여 사용해야 합니다:
// entrypoints/content.ts
import initWasm, { parseSync } from '@oxc-parser/wasm';
export default defineContentScript({
matches: '*://*.github.com/*',
async main(ctx) {
if (!location.pathname.endsWith('.ts')) return;
// GitHub에서 텍스트를 가져옵니다.
const code = document.getElementById(
'read-only-cursor-text-area',
)?.textContent;
if (!code) return;
const sourceFilename = document.getElementById('file-name-id')?.textContent;
if (!sourceFilename) return;
// WASM 파일을 로드합니다:
await initWasm({
module_or_path: browser.runtime.getURL('/oxc_parser_wasm_bg.wasm'),
});
// 로드가 완료되면 `parseSync`를 사용할 수 있습니다!
const ast = parseSync(code, { sourceFilename });
console.log(ast);
},
});
이 코드는 @oxc-parser/wasm
문서에서 직접 가져온 것이며, 한 가지 예외가 있습니다: 파일 경로를 수동으로 전달합니다. 일반적인 NodeJS 또는 웹 프로젝트에서는 기본 경로가 잘 작동하므로 아무것도 전달할 필요가 없습니다. 그러나 확장 프로그램은 다릅니다. 항상 출력 디렉토리의 WASM 파일에 대한 전체 URL을 명시적으로 전달해야 하며, 이는 browser.runtime.getURL
이 반환하는 값입니다.
확장 프로그램을 실행하면, OXC가 TS 파일을 파싱하는 것을 확인할 수 있습니다!