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

使用TypeScript的Express服务器导入本地模块时出错

本地模块导入导出失败,陷入循环困境

我现在陷入了死循环,解决一个问题就会触发另一个问题。核心问题是本地文件的导出与导入功能完全失效,运行时抛出如下错误:

node:internal/process/esm_loader:40
      internalBinding('errors').triggerUncaughtException(
                                ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'C:\Users\[FULL PATH]\project\database' imported from C:\Users\[FULL PATH]\project\server.js
Did you mean to import ../database.js?
    at new NodeError (node:internal/errors:406:5)
    at finalizeResolution (node:internal/modules/esm/resolve:233:11)
    at moduleResolve (node:internal/modules/esm/resolve:845:10)
    at defaultResolve (node:internal/modules/esm/resolve:1043:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:383:12)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:352:25)
    at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:228:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:85:39)
    at link (node:internal/modules/esm/module_job:84:36) {
  url: 'file:///C:/Users/[FULL PATH]/project/database',
  code: 'ERR_MODULE_NOT_FOUND'
}

我试过用module.exports = db2导出,导入时分别试过import * as db2 from './database'和const db2 = require('./database'),但每种方式都会出现对应的错误。

注意:这不是MySQL相关问题,测试其他本地模块也有同样问题,和async/await也无关。

运行环境:Node.js v20.9.0

相关代码文件

server.ts

import express from 'express'
import dotenv from 'dotenv'

/* EXPRESS */
const app = express()

/* DOTENV */
dotenv.config()

/* MYSQL */
//////////// THIS WORKS ////////////
import mysql from 'mysql2/promise'
const db1 = await mysql.createConnection({
    host: process.env.MYSQL_HOST,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
})
console.log({db1: await db1.query('SELECT * FROM table')})

//////////// THIS DOES NOT WORK ////////////
import db2 from './database'
console.log({db2: db2.query('SELECT * FROM table')}) // BREAKS ON THIS LINE

/* ROUTES */
app.get("/", (req, res) => {
    res.send("Hello, world!")
})

/* START SERVER */
const PORT = process.env.PORT

app.listen(PORT, () => {
    console.log(`App listening on port ${PORT}`)
})

database.ts

import mysql from 'mysql2/promise'

const db2 = await mysql.createConnection({
    host: process.env.MYSQL_HOST,
    user: process.env.MYSQL_USER,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
})

export default db2

package.json

{
  "main": "server.js",
  "scripts": {
    "build": "tsc -p . -w",
    "start": "nodemon server.js"
  },
  "type": "module",
  "dependencies": {
    "@types/express": "^4.17.21",
    "dotenv": "^16.3.1",
    "express": "^4.18.2",
    "mysql2": "^3.6.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es2022",
    "module": "ES2022",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

解决方案

1. 修复导入路径的扩展名问题

Node.js ES模块要求本地模块导入必须指定完整文件扩展名。当前server.ts中导入./database,编译为server.js后,Node会尝试寻找无扩展名的database文件,但实际编译后的文件是database.js,因此修改导入语句为:

import db2 from './database.js'

如果希望在TS中直接使用.ts扩展名,可以在tsconfig.json的compilerOptions中添加:

"allowImportingTsExtensions": true,
"resolveJsonModule": true

此时导入路径可以写./database.ts,但编译后仍需确保扩展名正确,推荐直接使用.js扩展名更稳妥。

2. 统一模块语法,避免混用

由于package.json已设置"type": "module",全程使用ES模块的import/export语法,不要混用CommonJS的require/module.exports,避免模块系统冲突。

3. 优化顶层await的使用(可选)

虽然你的Node版本支持顶层await,但将数据库连接包装为异步函数可以提升代码灵活性,避免潜在的模块加载问题:

修改database.ts:

import mysql from 'mysql2/promise'

export default async function getDbConnection() {
    return mysql.createConnection({
        host: process.env.MYSQL_HOST,
        user: process.env.MYSQL_USER,
        password: process.env.MYSQL_PASSWORD,
        database: process.env.MYSQL_DATABASE,
    })
}

在server.ts中调用:

import getDbConnection from './database.js'
const db2 = await getDbConnection()
console.log({db2: await db2.query('SELECT * FROM table')})

4. 检查编译输出

确认tsc编译后,database.js与server.js处于同一目录。若tsconfig.json未设置outDir,默认会将编译产物生成在源文件同目录,无需额外配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 14:15:55