You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在tsconfig中包含Server目录时出现.ts文件扩展名未知错误

全TS项目中Vite导入server目录TS文件出现ERR_UNKNOWN_FILE_EXTENSION错误

我用Vite搭建了React前端+Node.js+Express后端的全TypeScript项目,当在tsconfig.json中包含server目录并导入该目录下的文件时,出现以下错误:

node:internal/errors:490
    ErrorCaptureStackTrace(err);
    ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/**name**/projects/**project-name**/server/database/models/problem.ts
    at new NodeError (node:internal/errors:399:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:79:11)
    at defaultGetFormat (node:internal/modules/esm/get_format:121:38)
    at defaultLoad (node:internal/modules/esm/load:81:20)
    at nextLoad (node:internal/modules/esm/loader:163:28)
    at ESMLoader.load (node:internal/modules/esm/loader:605:26)
    at ESMLoader.moduleProvider (node:internal/modules/esm/loader:457:22)
    at new ModuleJob (node:internal/modules/esm/module_job:64:26)
    at #createModuleJob (node:internal/modules/esm/loader:480:17)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:434:34) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

不包含server目录时项目可正常运行,不确定该问题是否与TypeScript或Vite的底层机制有关。

我的tsconfig.json配置:

{
  "compilerOptions": {
    "target": "ESNext",
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "module": "ESNext",
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "allowJs": true,
    "outDir": "./build",
    "esModuleInterop": true,

    /* Bundler mode */
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src", "server"],
  "exclude": ["node_modules"]
}

package.json配置:

{
  "name": "**project-name**",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "start": "PORT=$PORT npm run dev:seed",
    "dev": "vite",
    "dev:seed": "SEED=true npm run dev",
    "build": "tsc && vite build",
    "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview",
    "test": "vitest",
    "test-ui": "vitest --ui"
  },
  "dependencies": {
    "@emotion/react": "^11.11.0",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.11.16",
    "@mui/material": "^5.13.0",
    "@reduxjs/toolkit": "^1.9.5",
    "axios": "^1.4.0",
    "cookie-parser": "^1.4.6",
    "dotenv": "^16.0.3",
    "express": "^4.18.2",
    "googleapis": "^118.0.0",
    "konva": "^9.2.0",
    "nodemon": "^3.0.1",
    "pg": "^8.11.0",
    "pg-hstore": "^2.3.4",
    "react": "^18.2.0",
    "react-color": "^2.19.3",
    "react-dom": "^18.2.0",
    "react-icons": "^4.10.1",
    "react-konva": "^18.2.10",
    "react-redux": "^8.0.5",
    "react-router-dom": "^6.11.2",
    "sequelize": "^6.31.1",
    "socket.io": "^4.7.2",
    "socket.io-client": "^4.7.2",
    "uuid": "^9.0.0"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/cookie-parser": "^1.4.3",
    "@types/express": "^4.17.17",
    "@types/react": "^18.0.28",
    "@types/react-dom": "^18.0.11",
    "@types/testing-library__jest-dom": "^5.14.5",
    "@types/uuid": "^9.0.1",
    "@typescript-eslint/eslint-plugin": "^5.57.1",
    "@typescript-eslint/parser": "^5.57.1",
    "@vitejs/plugin-react-swc": "^3.0.0",
    "@vitest/ui": "^0.31.1",
    "eslint": "^8.38.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.3.4",
    "jsdom": "^22.0.0",
    "msw": "^1.2.1",
    "sequelize-cli": "^6.6.0",
    "ts-node": "^10.9.1",
    "ts-node-dev": "^2.0.0",
    "typescript": "^5.0.2",
    "vite": "^4.3.2",
    "vitest": "^0.31.0"
  }
}

问题原因与解决办法

核心原因

项目package.json中设置了"type": "module"启用ES模块,但Node本身不支持直接导入.ts文件;同时Vite作为前端构建工具,仅默认处理src目录下的前端代码,不会编译server目录的后端TS文件。当前端代码导入server目录的TS文件时,Vite会将路径直接交给Node处理,导致Node无法识别.ts扩展名报错。

解决办法

1. 拆分前后端TS配置(推荐)

  • 根目录tsconfig.json仅用于前端,修改include为["src"]
  • 在server目录下新建tsconfig.server.json,配置后端TS编译:
    {
      "compilerOptions": {
        "target": "ESNext",
        "module": "ESNext",
        "moduleResolution": "node",
        "outDir": "../build/server",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "resolveJsonModule": true
      },
      "include": ["."],
      "exclude": ["node_modules"]
    }
    
  • 更新package.json的scripts,添加后端启动命令(需先安装concurrently:npm i -D concurrently):
    "scripts": {
      "dev:server": "ts-node-dev --respawn --transpile-only server/index.ts",
      "dev": "concurrently \"npm run dev:server\" \"vite\"",
      "build": "tsc && tsc -p server/tsconfig.server.json && vite build",
      // 其他命令保留
    }
    
  • 前端不要直接导入后端代码,通过API请求与后端交互。

2. 单独管理共享类型(若需前后端共享类型)

  • 新建shared目录存放前后端共享的类型定义文件
  • 根目录tsconfig.json的include添加"shared",这样Vite能正确处理共享TS文件,同时避免引入后端业务代码

3. 临时修复(不推荐生产环境)

  • 若临时需要在前端导入后端代码,可先用ts-node或esbuild预编译server目录的TS文件,前端导入编译后的.js文件,但这种方式会混淆前后端边界,不建议长期使用

内容的提问来源于stack exchange,提问作者Jiayu Zhang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:24:54