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

Node.js提示找不到模块但路径存在:自研npm包测试问题

问题

我正在开发一款基于TypeScript的npm包,创建了独立测试项目从npm下载该包测试。包通过主文件导入其他模块的类后统一导出,但测试项目运行时Node.js提示找不到实际存在的子模块。

代码片段

主文件(编译后的lib/index.js)

import { EventBus } from "./modules/eventbus/eventbus";
import { EventHandler } from "./modules/eventbus/eventhandler";
import { EventType } from "./modules/eventbus/eventtype";
import { Event } from "./modules/eventbus/event";
import { SemVer } from "./modules/semver";
export { SemVer, Event, EventBus, EventHandler, EventType };

错误信息

Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/workspaces/epic-engine-testing/node_modules/epic-engine/lib/modules/eventbus/eventbus' imported from /workspaces/epic-engine-testing/node_modules/epic-engine/lib/index.js

测试文件

import { EventBus, EventHandler, EventType, Event } from "epic-engine";

class SomeType extends EventType {
    constructor() {
        super();
    }
}

const eventbus = new EventBus();
const handler = new EventHandler<SomeType>(eventbus, "type", () => {});
eventbus.createHandler(handler);
const event = new Event<SomeType>(eventbus, new SomeType(), "type");

包的package.json

{
  "devDependencies": {
    "@tsconfig/esm": "^1.0.2",
    "@types/jest": "^29.2.3",
    "jest": "^29.3.1",
    "ts-jest": "^29.0.3",
    "tslint": "^6.1.3",
    "typescript": "^4.9.3"
  },
  "name": "epic-engine",
  "description": "Pure TS engine developed by EpicPuppy613",
  "version": "0.1.0-dev.5",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "type": "module",
  "scripts": {
    "test": "jest --config jestconfig.json",
    "build": "tsc",
    "prepare": "npm run build",
    "lint": "tslint -p tsconfig.json",
    "prepublishOnly": "npm test && npm run lint",
    "preversion": "npm run lint",
    "version": "git add -A src",
    "postversion": "git push && git push --tags"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/EpicPuppy613/epic-engine.git"
  },
  "author": "EpicPuppy613",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/EpicPuppy613/epic-engine/issues"
  },
  "homepage": "https://github.com/EpicPuppy613/epic-engine#readme",
  "files": [
    "lib/**/*"
  ]
}

已尝试添加.js后缀、使用绝对路径、修改tsconfig.json等操作仍未解决,想知道Node.js找不到子模块的原因,以及是否有更优的模块导出方式。


解决方案

核心原因

Node.js的ES模块系统要求导入路径必须包含完整文件扩展名(如.js),若TypeScript编译配置不当,不会自动为导入路径添加后缀;另外需确认编译后的子模块文件确实存在于lib/modules目录,且未被package.json的files字段排除。

具体修复步骤

  1. 配置TypeScript自动添加.js后缀
    修改tsconfig.json,确保关键配置项正确:

    {
      "compilerOptions": {
        "module": "ESNext",
        "moduleResolution": "NodeNext",
        "target": "ES2020",
        "outDir": "./lib",
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "declaration": true
      },
      "include": ["src/**/*"],
      "exclude": ["node_modules", "lib"]
    }
    

    其中moduleResolution: "NodeNext"会让TypeScript遵循Node.js的ES模块规则处理导入路径,编译后自动补充.js后缀。

  2. 验证编译后的文件结构
    执行npm run build后,检查lib/modules目录下是否存在所有子模块的.js和.d.ts文件,比如lib/modules/eventbus/eventbus.js必须存在。

  3. 手动补全导入路径后缀(配置未生效时)
    在TypeScript源码的主文件中,直接为导入路径添加.js后缀(编译后会保留该后缀):

    // src/index.ts
    import { EventBus } from "./modules/eventbus/eventbus.js";
    import { EventHandler } from "./modules/eventbus/eventhandler.js";
    import { EventType } from "./modules/eventbus/eventtype.js";
    import { Event } from "./modules/eventbus/event.js";
    import { SemVer } from "./modules/semver.js";
    export { SemVer, Event, EventBus, EventHandler, EventType };
    

更优的模块导出方式

  1. 子模块统一入口
    在src/modules/eventbus目录下创建index.ts,统一导出该目录内的所有模块:

    // src/modules/eventbus/index.ts
    export { EventBus } from "./eventbus";
    export { EventHandler } from "./eventhandler";
    export { EventType } from "./eventtype";
    export { Event } from "./event";
    

    主文件可简化导入逻辑:

    // src/index.ts
    import * as EventBusModule from "./modules/eventbus/index.js";
    import { SemVer } from "./modules/semver.js";
    export { SemVer, ...EventBusModule };
    

    这种方式让模块结构更清晰,便于后续扩展维护。

  2. 使用exports字段定义导出规则
    在包的package.json中添加exports字段,明确模块导出路径,同时兼容CommonJS和ES模块:

    {
      "exports": {
        ".": "./lib/index.js",
        "./eventbus": "./lib/modules/eventbus/index.js"
      }
    }
    

    用户不仅可以从包根导入,还能直接导入子模块:import { EventBus } from "epic-engine/eventbus"。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:20:22