Vite + Electron + React 환경에서 svgr 사용하기
electron-vite
Vite를 한 번 쓴 뒤로는 Webpack으로 돌아가지 못하는 몸이 되었다. 압도적인 빌드 및 HMR 속도를 한 번 겪어보니 도저히 돌아갈 엄두가 나지 않는다.
이번에 진행하고 있는 프로젝트에서 처음에는 닷넷/WPF로 작성하려다가 이것 저것 조건을 따져보니 일렉트론을 쓰는 게 낫다 판단되어 일렉트론으로 전환하였고, 기본 일렉트론 가이드대로 따라보니 웹팩의 느려터진 빌드 속도가 짜증나서 electron-vite를 사용하게 되었다.
SVG Component
이번 프로젝트에는 마치 포토샵마냥 도구 툴바를 구현해야 하는 부분이 있다. 대부분은 heroicons이나 @mui/icons-material로 해결이 되었지만 안 되는 부분 역시 있었기에 이러한 부분은 직접 제작한 SVG나 무료 라이센스의 SVG를 받아서 쓰려 했다.
문제는, SVG 컴포넌트를 사용하려 하니 자꾸 에러가 났다는 것이다.
vite-plugin-svgr
SVG 컴포넌트를 사용하기 위해 vite-plugin-svgr을 패키지에 추가했다. 설정하라는 대로 env.d.ts도 수정하고, electron.vite.config.ts도 수정했지만 정상적으로 작동하지 않았다.
SyntaxError: The requested module '/[CENSORED]/move-arrows.svg?t=1699422381493&import' does not provide an export named 'ReactComponent' (at [CENSORED].tsx?t=1699422908031:26:10)
import문은 다음과 같다.
import { ReactComponent as MoveArrows } from "@assets/move-arrows.svg";
문제 파악 및 해결
일단, 문제는 오래된 글이었다. 말 그대로 너무 오래된 글이라 이전 버전의 라이브러리 또는 vite에 대한 내용이 적혀있던 것 같다. 어떤 글인지 정확히 특정해 밝히진 않겠지만, 내가 본 세 개의 국내 블로그 글들은 모두 위처럼 import문을 작성하라고 알리고 있었다.
그러나, 그게 아니었다. **공식 문서**에 따르면 컴포넌트를 쓰려면 단순히 ?react
쿼리를 import 할 svg 대상 끝에 추가하라 한다.
import MoveArrows from "@assets/move-arrows.svg?react";
(또한 default를 import하기 때문에 중괄호로 묶지 말아야 한다.)
위처럼 작성하니 아무 문제 없이 정상적으로 import됨을 확인할 수 있었다.
electron-vite 환경에서 vite-plugin-svgr 사용법 요약
- 일단 vite-plugin-svgr을 설치한다. 내 경우 pnpm을 사용했다.
pnpm i -D vite-plugin-svgr
renderer/src/env.d.ts
에 다음 줄을 추가한다.
/// <reference types="vite-plugin-svgr/client" />
- (옵션) 원하는 경로에
원하는_이름.d.ts
파일을 만들고 이를tsconfig.web.json
의 includes에 추가한다.
옵션인 이유는 모든 블로그 글에서 이를 진행해야 타입스크립트에서 정상적으로 사용할 수 있다 하였으나, 테스트 결과 없어도 잘 작동했다.
d.ts 파일의 내용은 다음과 같다.
declare module "*.svg" {
import React = require("react");
export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}
electron.vite.config.ts
에서renderer
의pugins
에svgr()
을 추가한다.
// ...
import svgr from "vite-plugin-svgr";
// ...
export default defineConfig({
main: {
plugins: [externalizeDepsPlugin(), svgr()],
},
preload: {
plugins: [externalizeDepsPlugin(), svgr()],
},
renderer: {
/* ... */
plugins: [react(), svgr()],
},
});
- (사용) 원하는 svg 파일을 임포트하되, 컴포넌트로 사용하려면 끝에
?react
쿼리를 붙여준다.
// 올바른 컴포넌트 임포트
import MySvgNameBlahBlah from "@assets/icons/cursor.svg?react";
// 올바르지 않은 컴포넌트 임포트
import ThisIsPathImport from "@assets/icons/cursor.svg";
import { ReactComponent as MySvgNameBlahBlah2 } from "@assets/icons/cursor.svg";
Your post was a joy to read. Thank you for sharing your wisdom!
답글삭제I'm glad to hear you enjoyed reading it. I hope the information was helpful.
삭제