문제 설명
vite + react + typescript 기반 프로젝트에서 scss를 도입하였다.
scss 파일은 vite에서 js 파일에 아래처럼 간단하게 import 하여 사용할 수 있다.
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import './index.css'
import App from "./App.tsx";
createRoot(document.getElementById("root")!).render(
<StrictMode>
<App />
</StrictMode>
);
문제는 scss 내에서 import를 할 때 발생했다.
아래처럼 scss 내에서 @import를 하니, 소스 코드 내 디렉토리 경로와 빌드된 파일 내 경로가 꼬였는지 모르겠는데, 파일을 이상한 경로에서 찾으며 에러가 표출되었다.
@import "../../css/token/tokens.css";
에러 코드
[plugin:vite:css] [postcss] ENOENT: no such file or directory,
open 'C:\Users\Desktop\my-project1\css\token\tokens.css'
해결 방법
경로 별칭(path alias) 추가
추측컨데, 번들 이전 경로를 번들링할 때 resolve에 문제가 생기는 것 같아서 경로 별칭을 이용한 절대 경로 선언을 만들었다.
이는 vite.config.js 를 이용해 만들 수 있다.
import react from "@vitejs/plugin-react";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
import { defineConfig } from "vite";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": resolve(__dirname, "src"),
"@krds": resolve(__dirname, "src/components/krds-uiux"),
},
},
});
.scss에서 절대 경로를 사용하는 예시
// index.scss
// 안되던 상대 경로 코드
// @import "../../css/token/tokens.css";
// 변경된 코드 : 절대 경로, path alias
@import "@/shared/styles/css/token/tokens.css";
// 혹은 아래처럼 더 간단하게도 가능
// @import "@styles/css/token/tokens.css";
typescript 설정 추가
vite에 경로 별칭을 추가한 것과 별개로 타입스크립트의 타입 검사 및 컴파일링을 위해 경로 별칭을 타입스크립트 설정 파일에 추가해야 한다.
{
"compilerOptions": {
// alias
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@styles/*": ["src/shared/ui/styles/*"]
}
},
"include": ["src"]
}
경로 자동 완성 기능: path Intellisense
vite 설정이나 타입스크립트 검사를 위한 경로 별칭 설정과 별개로, import 경로 설정 시 자동완성을 위해서는 vscode에서 추가적인 익스텐션을 많이 사용한다.
대표적으로 Path Intellisense(이하, 인텔리센스)와 Path Autocomplete가 있는데, 여기서는 전자를 설치하여 사용하고 있다.
인텔리센스를 설치하면 .js나 .ts파일에서 import 시 자동으로 경로 완성을 할 수 있다.
하지만, scss 나 css에서는 이러한 경로 완성 기능을 지원하지 않으므로 이 부분은 별도의 설정이 필요하다.
1. 프로젝트의 루트 위치에 /.vscode/settings.json 을 생성한다.
그리고 아래처럼 작성하여 인텔리센스에서 경로 별칭을 사용하도록 설정한다.
// .vscode/settings.json
{
"path-intellisense.mappings": {
"@src": "${workspaceRoot}/src",
"@krds": "${workspaceRoot}/src/components/krds-uiux"
},
"path-intellisense.extensionOnImport": true
}
그러나, 여기에는 버그가 있는 것으로 추측된다.
위에서 보다시피, 지금까지 설정한 경로는 @와 @krds 였는데, 위 설정은 그것과 다르다.
만약 @와 @krds로 설정하는 경우, .scss에서 import에 경로 별칭을 사용해보면 @는 자동완성이 되는데, @krds는 자동완성이 되지 않는다.
아마도 @krds는 @에 덮어씌워지는 어떤 판정이 뜨는 것 같다.
그래서 이 경로 별칭은 서로 간에 절대 include 관계, 즉, 한쪽이 어느 한쪽을 포함하는 관계가 되면 안된다. 그렇게 되면 번들링이나 타입 검사에는 문제가 없지만 경로 자동 완성을 쓸 수 없다.
따라서, vite와 typescript 설정 파일도 아래처럼 추가해주자
vite.config.js
import react from "@vitejs/plugin-react";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
import { defineConfig } from "vite";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
"@": resolve(__dirname, "src"),
"@src": resolve(__dirname, "src"),
"@krds": resolve(__dirname, "src/components/krds-uiux"),
},
},
});
ts.config.json
{
"compilerOptions": {
// alias
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@src/*": ["src/*"],
"@styles/*": ["src/shared/ui/styles/*"]
}
},
"include": ["src"]
}