Vue + vue-facing-decorator + Vite 5 사용 시 빌드 오류 해결

TL;DR

tsconfig.app.json에 experimentalDecorators: true 추가했는지 확인!!!

오류 발생 환경

오류 로그

Vite 5로 빌드 시도 시 Expression expected (Note that you need plugins to import files that are not JavaScript) 오류 발생

...

vite v5.0.11 building for production...
✓ 33 modules transformed.
Expression expected (Note that you need plugins to import files that are not JavaScript)
file: P:/~~~/App.vue?vue&type=script&lang.ts:6:0 
4: import { useStore } from "./store";
5:
6: @Component({})
   ^
7: export default class App extends Vue {
error during build:
RollupError: Expression expected

...

문제점 분석 & 해결 과정

  • Vite v4로는 빌드가 되던게 Vite v5로 버전을 올렸더니 빌드 오류가 발생한다?!
  • 빌드를 몇 번이고 시도해봐도 vue-facing-decorator의 데코레이터 구문에서 오류가 발생
  • 이 오류를 구글링을 아무리 해봐도 동일한 증상을 가지고 작성된 글이나 이슈를 전혀 찾아볼 수 없었음(...)
    오류 로그를 힌트로 Vite v5, Rollup, vue-facing-decorator 등등 패키지를 키워드로 검색해봤지만 동일한 이슈를 다룬 글을 찾을 수 없었음
  • 그러다가 vue-facing-decorator의 Nuxt 3 호환과 관련하여 올려진 이슈에 달린 대화를 보고 힌트를 얻음
Compatibility with Nuxt 3 · Issue #93 · facing-dev/vue-facing-decorator
The package seems not compatible with a Nuxt 3 project It is working with the “dev” script but the build script fails wih the error [nuxt:composable-keys] Unexpected character ‘@’ which refers to t…
  • 위 이슈에서 제안된 대로 vite.config.ts 내의 defineConfig() 안에 esbuild: { tsconfigRaw: { } } 를 추가해봤지만 해결되진 않았고, 대신 다음 코드를 넣어봤는데 빌드에 성공함
export default defineConfig({
  ...
  esbuild: {
    tsconfigRaw: {
      experimentalDecorators: true,
    },
  },
  ...
});
  • 결국 TypeScript 구성에 experimentalDecorators: true 가 설정되어야 하는건 알겠는데,
    "이미 설정 되어있으니깐 Vite v4에서 빌드됐던거 아님??"
    그런데 tsconfig.json 에 해당 설정이 없었음...
  • create-vue로 생성했던 프로젝트에서 tsconfig.json 은 세 파일로 나뉘어져 있음. tsconfig.json, tsconfig.app.json, tsconfig.node.json.

    tsconfig.app.jsonexperimentalDecorators: true가 설정되어 있는지 확인할 것. 명시적으로 설정해두면 빌드가 잘 됨.
    tsconfig 파일에다가 설정했다면 위의 Vite 구성 파일에다가 tsconfigRaw 설정 안해도 됨.

    나머지 두 tsconfig 파일에 추가해봤자 무용지물이였음.
    (당연함... tsconfig.app.json 쪽이 include가 프로젝트의 소스코드로 설정되어 있으니)

결론 & 여담

  • 패키지/라이브러리에서 제공하는 tsconfig 프리셋을 맹신하지 말자.
  • vue-facing-decorator를 사용할 때는 그냥 잔말 말고 experimentalDecorators: true 설정할 것. (빨리 데코레이터가 stable이 되서 이런 삽질 안하게 됐음 좋겠...)
    ... 공식 문서에서 하라고 하면 그냥 하자.
  • ...그런데 실험적 데코레이터 사용 설정을 하지 않은 상태에서 Vite 4에서는 어떻게 빌드된거지...? 🤔🫤
  • 사실 이번이 Vite 5 적용을 위한 두 번째 시도임... 첫 번째 시도 때도 동일한 오류였는데 감이 잡히지도 않아서 적용 포기하고 롤백했었음...
  • 여담이지만 나는 Vue 프로그래밍할 때 클래스 컴포넌트 방식을 매우 선호하고 좋아함...
    Options API 문법이든 Composition API 문법이든 알기는 알지만 그래도 클래스 컴포넌트 문법이 TypeScript의 강점을 잘 살리고 객체지향에 찌든 내 눈에는 더 가독성이 좋다고 생각하기 때문.
    Vue 3 넘어오면서 공식적으로 클래스 컴포넌트를 지양하는 분위기라 매우 아쉬웠음... 그래서 이런 삽질을 하면서까지도 vue-class-component 패키지의 후속이나 마찬가지인 vue-facing-decorator 만큼은 사용을 포기하지 않는 중.