错误 TS2307:找不到模块"路径"或其相应的类型声明。尝试使用 Knex 在 Heroku 应用程序中迁移时



我想迁移一个SQlite数据库:

knex --knexfile knexfile.ts migrate:latest

但是这会导致以下打字错误:

⨯ Unable to compile TypeScript:
knexfile.ts:1:18 - error TS2307: Cannot find module 'path' or its corresponding type declarations.
1 import path from 'path';
                   ~~~~~~
knexfile.ts:4:1 - error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
4 module.exports = {
  ~~~~~~
knexfile.ts:7:28 - error TS2304: Cannot find name '__dirname'.
7     filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
                             ~~~~~~~~~
knexfile.ts:10:29 - error TS2304: Cannot find name '__dirname'.
10     directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
                               ~~~~~~~~~
knexfile.ts:13:29 - error TS2304: Cannot find name '__dirname'.
13     directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
                               ~~~~~~~~~
TSError: ⨯ Unable to compile TypeScript:
knexfile.ts:1:18 - error TS2307: Cannot find module 'path' or its corresponding type declarations.
1 import path from 'path';
                   ~~~~~~
knexfile.ts:4:1 - error TS2580: Cannot find name 'module'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
4 module.exports = {
  ~~~~~~
knexfile.ts:7:28 - error TS2304: Cannot find name '__dirname'.
7     filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
                             ~~~~~~~~~
knexfile.ts:10:29 - error TS2304: Cannot find name '__dirname'.
10     directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
                               ~~~~~~~~~
knexfile.ts:13:29 - error TS2304: Cannot find name '__dirname'.
13     directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
                               ~~~~~~~~~

下面是我的knexfile:

import path from 'path';
import 'dotenv/config';
module.exports = {
  client: 'sqlite3',
  connection: {
    filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite'),
  },
  migrations: {
    directory: path.resolve(__dirname, 'src', 'database', 'migrations'),
  },
  seeds: {
    directory: path.resolve(__dirname, 'src', 'database', 'seeds'),
  },
  useNullAsDefault: true,
};

我该如何解决这个问题?我使用以下依赖项:

tbody> <<tr>
dependencies
"@types/bcryptjs":"^ 2.4.2", "@vscode/sqlite3":"^ 5.0.8"
"@types/cors":"^ 2.8.7", "bcryptjs":"^ 2.4.3"
"@types/express":"^ 4.17.7", "cors":"^ 2.8.5"
"@types/jsonwebtoken":"^ 8.5.8" "dotenv":"^ 8.2.0"
"@types/node":"^ 17.0.24" "express":"^ 4.17.1"
"knex-types"^ 0.3.2" "jsonwebtoken":"^ 8.5.1"
"ts-node-dev"^ 1.0.0-pre.56" "knex":"^ 1.0.7"
"typescript"^ 4.6.3" "ts-node":"^ 8.10.2"
"sqlite3":"^ 5.0.3"

TypeScript

这里的直接问题是你试图在运行时使用TypeScript,但你已经将@types/node定义为开发依赖项。默认情况下,Heroku在构建项目后将devDependencies从项目中剥离。

一种选择是跳过修剪步骤,这将使您的devDependencies保持原位,但这可能不是正确的选择。通常情况下,您希望剥离这些依赖项。除其他原因外,这减少了应用程序块的大小。

另一个选择是将@types/nodedevDependencies移动到dependencies。但我也不认为这是正确的做法。我的直觉告诉我,你根本不应该在生产环境中使用TypeScript。

因为你的build脚本只是运行tsc,我想知道它是否已经编译了你的knexfile.tsknexfile.js。如果是这样,您可以尝试直接运行JavaScript文件:

knex --knexfile knexfile.js migrate:latest

由于这是Knex查找的默认文件,因此实际上可以完全跳过参数:

knex migrate:latest

SQLite

这将使您的迁移开始,但是您将遇到另一个问题:Heroku的短暂文件系统使SQLite成为一个糟糕的数据库选择。

您对数据库所做的任何更改,包括迁移引入的模式更改,将在您的dyno重新启动时丢失。这种情况经常发生(每天至少一次)。

要解决这个问题,您需要从SQLite切换到客户机-服务器数据库。Heroku自己的Postgres服务是一个合理的起点,但如果您喜欢,还有其他数据库插件。你也可以在云上的其他地方托管你自己的数据库,例如在Microsoft Azure或AWS上。

我与另一个模块有同样的问题,我试图在文件中导入@mui/x-data-grid,但得到了同样的错误。我发现@Chris上面提到的库在依赖对象中而不是在devDependencies中,所以我只需要删除它并在devDependencies上再次安装它,现在错误信息消失了。似乎@types/node必须在相同的依赖对象(dev或not)作为你试图使用的模块。