slothis · ไทย

วิธีแก้ Error Cannot find module '#q-app/wrappers' ใน Vue + Quasar

2025-03-20 · ต้นฉบับ (ภาษาเกาหลี)

บทความนี้แปลจากต้นฉบับภาษาเกาหลีโดยใช้ AI ช่วย ราคาในวงเล็บเป็นการแปลงโดยประมาณ อ่านต้นฉบับภาษาเกาหลี →
อ๊ากกกกกกกกกกกก


บางทีอาจจะเจอ Error แบบนี้ หรือแบบด้านล่างนี้ครับ
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" 
หรือ
 ERROR(vue-tsc)  Cannot find module '#q-app/wrappers' or its corresponding type declarations.

สภาพแวดล้อมที่ใช้งานอยู่ตอนนี้
  • vue 3.4.18
  • quasar 2.16.0
  • quasar/app-vite 2.1.4
ไม่รู้เหมือนกันว่า Quasar เปลี่ยนวิธีใช้งานตั้งแต่เมื่อไหร่ แต่ในเวอร์ชันที่ผมใช้อยู่ตอนนี้ มันไม่เหมือนเดิมแล้วครับ โดยเฉพาะถ้าใช้ CLI ร่วมกับ Vite ยังไงก็ต้องเจอปัญหานี้แน่นอน อ้างอิง

import { defineConfig } from "@quasar/app-vite";

ถ้าอันนี้คือวิธีเดิมที่เคยใช้ ตอนนี้ต้องเปลี่ยนเป็น
import { defineConfig } from '#q-app/wrappers'

ต้อง import แบบนี้ครับ แต่ทีนี้มันจะแจ้ง Error ว่าไม่สามารถ import #q-app ได้ พอไปถาม ChatGPT หรือ Cursor.ai ก็จะบอกให้ลบ node_modules ทิ้งให้หมดแล้ว npm install ใหม่ หรือไม่ก็ให้ลองรัน quasar clean --qconf หรือให้กลับไป import แบบเดิม น่าจะเป็นเพราะเพิ่งมีการเปลี่ยนแปลงเมื่อเร็วๆ นี้ AI เลยยังไม่ได้เรียนรู้ครับ

ปัญหาที่แท้จริงเกิดจากบั๊กครับ ถึงจะมีแพตช์ออกมาแล้ว แต่ดูเหมือนจะเป็นแค่การแก้ปัญหาเฉพาะหน้ามากกว่าที่จะสมบูรณ์แบบ

ถ้ามีการกำหนดค่า baseUrl ใน tsconfig.json มันจะไปชนกับ tsconfig.json ที่ Quasar สร้างขึ้นมาใช้เอง (ไฟล์ที่ Quasar ใช้คือ /.quasar/tsconfig.json ซึ่งถูกกำหนดไว้ในคีย์ extends)
Issue ที่เกี่ยวข้องบน GitHub

วิธีแก้ไข

ลบ baseUrl และ path ออกจาก tsconfig.json ครับ

ด้านล่างนี้คือไฟล์ tsconfig.json ที่แนะนำครับ
{
  "extends": "./.quasar/tsconfig.json",
  "compilerOptions": {
    "esModuleInterop": true,
    "skipLibCheck": true,
    "target": "esnext",
    "allowJs": true,
    "resolveJsonModule": true,
    "moduleDetection": "force",
    "isolatedModules": true,
    "module": "preserve",
    "noEmit": true,
    "lib": [
      "esnext",
      "dom",
      "dom.iterable"
    ]
  },
ในส่วนของ vite.config.js ก็มีการตั้งค่าที่คล้ายกัน แต่เราสามารถมองข้ามไปได้เลยครับ เพราะมันเป็นแค่ alias path ที่ Vite ใช้สำหรับอ้างอิงเท่านั้น ปัญหาการชนกันเกิดขึ้นแค่กับ tsconfig อย่างเดียวครับ