Typescript 构建 "Cannot find module",但仅在 ubuntu 服务器上

Typescript build "Cannot find module", but only on a ubuntu server

我正在研究节点脚本并用打字稿编写它。我在笔记本电脑 (mac) 或 raspberry pi 运行ning raspbian.

上构建 运行ning 没有遇到任何问题

我已经到了想要在 运行ning ubuntu 的数字海洋服务器上设置代码库的地步。我向上移动了代码库和 运行 我的构建脚本。构建成功完成,但是当我启动节点进程时出现错误:

node dist/server/source-server/index.js
internal/modules/cjs/loader.js:883
  throw err;
  ^

Error: Cannot find module 'express'
Require stack:
- /var/www/binary-operations-presentation/multi-player-server/dist/server/source-server/index.js
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:880:15)
    at Function.Module._load (internal/modules/cjs/loader.js:725:27)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (/var/www/binary-operations-presentation/multi-player-server/dist/server/source-server/index.js:6:35)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/var/www/binary-operations-presentation/multi-player-server/dist/server/source-server/index.js'
  ]
}

这很奇怪。我在多个服务器上 运行 这个代码库并且 none 有这个问题。我四处搜索了一下,但我找到的所有答案都是“运行 npm install express”或“运行 npm install @types/express”,这两个我都有:

此外,如果我没有安装它们,typescript 编译器构建将会失败。

我将 ubuntu 服务器上的文件结构与我的 raspberry pi 服务器进行了比较,除了代码库实际 运行 时生成的文件外,目录是相同的:

两个服务器都有相同的tsconfig.json文件:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "sourceMap": true,
    "outDir": "../dist/server",
    "rootDirs": ["./", "../project-common/"],
    "strict": true,
    "moduleResolution": "node",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "resolveJsonModule": true
  }
}

并且两者具有相同的依赖版本:

// from package.json
{
  ...
  "devDependencies": {
    "@types/uuid": "^8.3.0",
    "@types/ws": "^7.4.0",
    "killport": "^1.0.1",
    "nodemon": "^2.0.7",
    "tsc-watch": "^4.2.9",
    "tslint": "^6.1.3",
    "typescript": "^4.1.3"
  },
  "dependencies": {
    "@types/express": "^4.17.11",
    "@types/lodash.clonedeep": "^4.5.6",
    "@types/websocket": "^1.0.1",
    "express": "^4.17.1",
    "lodash.clonedeep": "^4.5.0",
    "uuid": "^8.3.2",
    "ws": "^7.4.2"
  }
}

dist 文件夹都没有 node_modules 文件夹,当我查看服务器的 t运行spiled index.js 文件时,它们都导入表示同样的方法:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const http_1 = __importDefault(require("http"));

并且两个 index.js.map 文件引用相同的相对源目录:

{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../source-server/index.ts"]

所以我不确定为什么一台服务器能够返回到 node_modules 文件夹,而另一台服务器却不能。

我看到的唯一大区别(除了OS版本,服务器是运行ning Ubuntu 20.04)是我的raspberry pi是运行ning 节点 15.x 而 ubuntu 是 运行ning 节点 14.x,虽然我不知道那一定会导致这个问题。

有什么想法吗?


更新:相同版本的节点

我试过让node的版本一样。我在 raspberry pi 上安装了 nvm,引入了 14.6.0(与数字海洋服务器相同的版本),重建了项目,并启动了服务器 -> 工作正常。

所以节点版本似乎不是一个因素:/

所以这是障碍和解决方案:

要点是索引文件的编译版本正在触发一个常规节点 require() 函数来拉入模块:

这意味着它要经过很多步骤才能找到模块。 When it comes to possible node_modules modules,它在当前目录中寻找node_modules文件夹。如果 node 没有找到它,node 将步进到父目录并在那里查找,如果找不到 node_modules 个目录,则继续步回到根目录。

就我而言,我之前将所有服务器和客户端代码都放在同一目录级别(新子文件夹现在所在的目录)。当我将代码分成子文件夹时,我忘记在本地吹走旧的 node_modules 文件夹,这就是为什么 dist 文件夹仍然找到现在位于父目录的 node_modules 文件夹的原因dist 个。当我在我的 raspberry pi 上执行 git pull 时,文件夹更新了,但是因为 node_modules 是我的 .gitignore 的一部分,父级别的文件夹并没有被吹走。

但是,在较新的存储库克隆中,当然不会在该父目录或任何其他父目录中有 node_modules,因此它们被炸毁了。

在与@cefn 交谈时,我意识到我确实想让 dist 成为“运行 这个项目所需的一切”目录,所以我在我的 npm build 脚本:

"scripts": {
    "build": "tsc --build tsconfig.json && npm run build:move-indexes && npm run build:move-node_modules",
    "build:move-indexes": "rsync -avz indexes ../dist/server/source-server",
    "build:move-node_modules": "rsync -avz node_modules ../dist/server/source-server",

这样,每次我重新构建源代码时,服务器都会将 dist 目录中的 node_modules 与我的源目录中的 node_modules 同步。

试过了,很有效:)