Skip to content

[问题/Issue] 章节13:旅行助手前端npm run build失败 #652

Description

@veyva

1. 遇到问题的章节 / Affected Chapter

Chapter13

2. 问题类型 / Issue Type

代码错误 / Code Error

3. 具体问题描述 / Problem Description

13章节旅行助手前端npm run build失败,npm run dev正常。

4. 问题重现材料 / Reproduction Materials

错误信息:

% npm run build

> helloagents-trip-planner-frontend@1.0.0 build
> vue-tsc && vite build

src/main.ts:4:8 - error TS2307: Cannot find module 'ant-design-vue/dist/reset.css' or its corresponding type declarations.

4 import 'ant-design-vue/dist/reset.css'
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

src/services/api.ts:4:34 - error TS2339: Property 'env' does not exist on type 'ImportMeta'.

4 const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
                                   ~~~

src/views/Home.vue:221:3 - error TS2322: Type 'null' is not assignable to type 'string & Dayjs'.
  Type 'null' is not assignable to type 'string'.

221   start_date: null,
      ~~~~~~~~~~

  src/types/index.ts:81:3
    81   start_date: string
         ~~~~~~~~~~
    The expected type comes from property 'start_date' which is declared here on type 'TripFormData & { start_date: Dayjs | null; end_date: Dayjs | null; }'

src/views/Home.vue:222:3 - error TS2322: Type 'null' is not assignable to type 'string & Dayjs'.
  Type 'null' is not assignable to type 'string'.

222   end_date: null,
      ~~~~~~~~

  src/types/index.ts:82:3
    82   end_date: string
         ~~~~~~~~
    The expected type comes from property 'end_date' which is declared here on type 'TripFormData & { start_date: Dayjs | null; end_date: Dayjs | null; }'

src/views/Home.vue:238:7 - error TS2322: Type 'null' is not assignable to type 'string & Dayjs'.
  Type 'null' is not assignable to type 'string'.

238       formData.end_date = null
          ~~~~~~~~~~~~~~~~~

src/views/Home.vue:241:7 - error TS2322: Type 'null' is not assignable to type 'string & Dayjs'.
  Type 'null' is not assignable to type 'string'.

241       formData.end_date = null
          ~~~~~~~~~~~~~~~~~

src/views/Result.vue:790:7 - error TS6133: 'captureMapImage' is declared but its value is never read.

790 const captureMapImage = async () => {
          ~~~~~~~~~~~~~~~

src/views/Result.vue:819:7 - error TS6133: 'restoreMap' is declared but its value is never read.

819 const restoreMap = () => {
          ~~~~~~~~~~

src/views/Result.vue:836:24 - error TS2339: Property 'env' does not exist on type 'ImportMeta'.

836       key: import.meta.env.VITE_AMAP_WEB_JS_KEY,  // 高德地图Web端(JS API) Key
                           ~~~


Found 9 errors in 4 files.

Errors  Files
     1  src/main.ts:4
     1  src/services/api.ts:4
     4  src/views/Home.vue:221
     3  src/views/Result.vue:790

环境信息:

  • Node v24.15.0
  • Npm 11.12.1
  • macOS Sequoia 15.3.1

5. 补充信息 / Additional Information

已解决,下述问题分析和解决方案由AI提供,供参考。

主要原因:
npm run build 里会先执行 vue-tsc 做严格类型检查,开发模式下没有触发这些 TS 错误。

  1. src/main.ts 中导入了 ant-design-vue/dist/reset.css
    • 这个 CSS 导入在 TypeScript 里没有声明模块类型
    • dev 模式能跑,但 vue-tsc 会报 Cannot find module '*.css'
  2. src/services/api.ts / src/views/Result.vue 使用了 import.meta.env
    • 没有 ImportMetaEnv 的类型声明
    • 所以 vue-tsc 报 Property 'env' does not exist on type 'ImportMeta'
  3. src/views/Home.vue 的表单状态类型写成
    • TripFormData & { start_date: Dayjs | null; end_date: Dayjs | null }
    • 这会把 string 和 Dayjs 的同名字段冲突成 string & Dayjs
    • 所以 null 不能赋值给它
  4. src/views/Result.vue 有两个声明但未使用的函数
    • captureMapImage
    • restoreMap
    • 因为 tsconfig 开启了 noUnusedLocals,build 阶段会报错

修复方案:

  1. 新增 src/env.d.ts
/// <reference types="vite/client" />

declare module '*.css'
declare module '*.less'

declare interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string
  readonly VITE_AMAP_WEB_JS_KEY: string
  readonly [key: string]: string | undefined
}

declare interface ImportMeta {
  readonly env: ImportMetaEnv
}
  1. 修改 tsconfig.json, include 中加入 src/**/*.d.ts
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/**/*.d.ts"]
  1. 修改 src/views/Home.vue中的表单类型
const formData = reactive<Omit<TripFormData, 'start_date' | 'end_date'> & { start_date: Dayjs | null; end_date: Dayjs | null }>({
  1. 删除 Result.vue 中未使用的两个函数
// 截取地图图片
const captureMapImage = async () => {
  if (!map) return

  try {
    // 获取地图容器
    const mapContainer = document.getElementById('amap-container')
    if (!mapContainer) return

    // 使用高德地图的截图功能
    const mapCanvas = mapContainer.querySelector('canvas')
    if (mapCanvas) {
      // 创建一个img元素替换地图容器
      const img = document.createElement('img')
      img.src = mapCanvas.toDataURL('image/png')
      img.style.width = '100%'
      img.style.height = '500px'
      img.style.objectFit = 'cover'
      img.id = 'map-snapshot'

      // 隐藏原地图,显示截图
      mapContainer.style.display = 'none'
      mapContainer.parentElement?.appendChild(img)
    }
  } catch (error) {
    console.error('截取地图失败:', error)
  }
}

// 恢复地图
const restoreMap = () => {
  const mapContainer = document.getElementById('amap-container')
  const snapshot = document.getElementById('map-snapshot')

  if (mapContainer) {
    mapContainer.style.display = 'block'
  }

  if (snapshot) {
    snapshot.remove()
  }
}

调整后效果

% npm run build

> helloagents-trip-planner-frontend@1.0.0 build
> vue-tsc && vite build

vite v6.3.6 building for production...
✓ 3478 modules transformed.
dist/index.html                        0.48 kB │ gzip:   0.33 kB
dist/assets/index-BeHBHT8z.css        15.20 kB │ gzip:   3.67 kB
dist/assets/purify.es-aGzT-_H7.js     22.15 kB │ gzip:   8.67 kB
dist/assets/index.es-Dw2on3lk.js     158.92 kB │ gzip:  53.23 kB
dist/assets/index-57miryDT.js      2,188.58 kB │ gzip: 673.95 kB

(!) Some chunks are larger than 500 kB after minification. Consider:
- Using dynamic import() to code-split the application
- Use build.rollupOptions.output.manualChunks to improve chunking: https://rollupjs.org/configuration-options/#output-manualchunks
- Adjust chunk size limit for this warning via build.chunkSizeWarningLimit.
✓ built in 3.79s

确认事项 / Verification

  • 我已阅读过相关章节的文档 / I have read the relevant chapter documentation
  • 我已搜索过现有的Issues,确认此问题未被报告 / I have searched existing Issues and confirmed this hasn't been reported
  • 我已尝试过基本的故障排除(如重启、重新安装依赖等) / I have tried basic troubleshooting (restart, reinstall dependencies, etc.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions