node.js - MODULE_NOT_FOUND 尝试在 Node JS/TypeScript 项目中通过目录在模块之间共享代码
我已经建立了一个示例项目来演示这个问题:
https://github.com/garethrbrown/node-share-code
在这个例子中有两个项目,example-api(一个迷你 Express 项目)和 example-shared(一个类库),两者都使用 Node JS/TypeScript。我希望 example-api 能够使用 example-shared 中的类,以避免代码重复。按照这个例子操作后,我已经在 example-api 的 package.json 中引用了 example-shared 项目。
"dependencies": {
"example-shared": "file:..\\example-shared",
"express": "^4.17.1"
}
完成此操作后,并运行 npm install,VSCode 中的智能感知可以看到 example-shared 项目中的 ApiClass 并协助导入。
然后我可以通过 NPM 运行我的构建命令 tsc --build,并且成功。
我还可以看到在 example-api 的 node_modules 目录中已经创建了符号链接。
然而,当我尝试在 example-api 下使用 npm start 脚本运行 example-api 项目时,我会遇到类似如下的错误:
Error: Cannot find module 'example-shared/apiClass'
Require stack:
...
code: 'MODULE_NOT_FOUND',
requireStack: [
...
]
我已经尝试过从这里描述的不同位置运行命令,但到目前为止都没有成功。
我正在使用当前稳定版本的 Node (14+) 和 NPM (7+)。
我不想通过 NPM 或 git 仓库分享,因为我觉得这会减慢开发速度。
我哪里做错了?
答案#1
看起来这是一个被讨论过的问题,见这篇文章 Typescript: 如何为 node.js 解析绝对模块路径?
我没有进一步调查,但在 example-shared 文件夹中,你可以从 example-shared/tsconfig.json 中移除 "outDir",然后运行 npm run build。不幸的是,这将会在 TypeScript 文件旁边生成 JavaScript 文件,而不是把它们放在一个单独的目录中。
最后,在 example-api 中运行 npm i、npm run build 和 npm start。
现在,Express 将会运行,因为 Node 正在使用 JavaScript 文件而不是 TypeScript 文件。
答案#2
根据 @mtbno 的回答,在没有 "outDir" 的情况下,标准的行为是所有的 js 和 map 文件都会直接创建在每个 TypeScript 文件旁边,这非常糟糕。
在不使用额外的 npm 包、webpack 或类似工具的情况下,你可以通过在 tsconfig 中添加 "outDir" 来解决这个问题,然后对你的 package.json 做一些调整。
为了论证起见,假设你的根 TypeScript 文件叫做 app.ts,你的 outDir 文件夹是 lib。
你 package.json 中的相关部分可以如下所示:
"scripts": {
"build": "tsc --build",
"clean": "tsc --build --clean",
"start": "npm run build && node ./lib/app"
},
和
"main": "./lib/app",
这里是一个 tsconfig.json 示例
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"lib": ["es6"],
"sourceMap": true,
"outDir": "./lib",
},
"exclude": [
"node_modules"
]
}
在更新这两个文件之后,运行 npm run start 应该会将你的 lib 文件夹构建出编译后的 JavaScript,并且你的服务器应该能够成功启动。请注意,如果你之前曾进行过构建,并且你的 TypeScript 文件旁边有“旧的” .js 和 .map 文件,你可能需要手动删除它们,因为 npm run clean 不会为你删除这些文件。

