错误 [ERR_UNSUPPORTED_DIR_IMPORT]:尝试在本地启动 Nodejs 应用程序时导入目录

bri*_*one 6 javascript heroku node.js express sequelize.js

我在尝试将我的应用程序部署到 Heroku 时陷入了一些循环。import cors from 'cors'由于“无法在通用 JS 中加载 ES6 模块”错误,我的导入语句(例如)似乎阻止了应用程序在生产中启动。在本地它运行得很好。

但是,当我尝试通过添加"type": "module"到我的来解决上述错误时,package.json我得到了一组全新的错误,并且该应用程序将不再在本地运行。我相信这个错误是由于我初始化 sequelize 和关联模型的方式造成的,但我不确定。我想解决这个错误,但需要一个新的导入语法的手......我想。

错误,package.jsonindex.js包括在下面。

错误文本

[nodemon] starting `babel-node src/index.js`
internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_UNSUPPORTED_DIR_IMPORT]: Directory import '/Users/jeff/Clients/Bummer/Code/Server/src/models' is not supported resolving ES modules imported from /Users/jeff/Clients/Bummer/Code/Server/src/index.js
    at finalizeResolution (internal/modules/esm/resolve.js:272:17)
    at moduleResolve (internal/modules/esm/resolve.js:699:10)
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:810:11)
    at Loader.resolve (internal/modules/esm/loader.js:85:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:229:28)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:51:40)
    at link (internal/modules/esm/module_job.js:50:36) {
  code: 'ERR_UNSUPPORTED_DIR_IMPORT',
  url: 'file:///Users/jeff/Clients/Bummer/Code/Server/src/models'
}
[nodemon] app crashed - waiting for file changes before starting...
Run Code Online (Sandbox Code Playgroud)

包.JSON

{
  "name": "bummer",
  "type": "module",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node src/index.js",
    "dev": "nodemon --exec babel-node src/index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.9.6",
    "@babel/node": "^7.8.7",
    "@babel/preset-env": "^7.9.6",
    "nodemon": "^2.0.4",
    "sequelize-cli": "^6.2.0"
  },
  "dependencies": {
    "cookie-parser": "^1.4.5",
    "cors": "^2.8.5",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "pg": "^8.2.1",
    "querystring": "^0.2.0",
    "request": "^2.88.2",
    "sequelize": "^6.3.5",
    "sequelize-auto-migrations": "^1.0.3",
    "uuid": "^8.0.0"
  }
}
Run Code Online (Sandbox Code Playgroud)

索引.js

import cors from 'cors';
import express from 'express';
import models, { sequelize } from './models';
// import routes from './routes';

//Initiaze Express
const app = express();
const routes = require('./routes');


//Helpers for Spotify oAuth
const cookieParser = require('cookie-parser')


// Include Middleware
app.use(express.static(__dirname + '/public'))
   .use(cors())
   .use(cookieParser())
   .use(express.json())
   .use(express.urlencoded({ extended: true }))
   require('dotenv').config()

   

// Include all Models
app.use((req, res, next) => {
  req.context = {
    models,
  };
  next();
});



// Load Routes from Router Index
app.use('/', routes);

sequelize.sync().then(() => {
  app.listen(process.env.PORT, () => {
    console.log(`Example app listening on port ${process.env.PORT}!`)
  });
});
Run Code Online (Sandbox Code Playgroud)

想法或指示?谢谢!

Mir*_*ili 70

明确地指向您的主文件(通常index.js)。例如

\n
import ... from \'./models\'          // \xe2\x9d\x8c\nimport ... from \'./models/index.js\' // \xe2\x9c\x85\n
Run Code Online (Sandbox Code Playgroud)\n
\n

替代方法(请参阅下面的更新):

\n

使用--experimental-specifier-resolution=node标志。例如:

\n
node --experimental-specifier-resolution=node main.js\n
Run Code Online (Sandbox Code Playgroud)\n

请参阅:\n https://nodejs.org/api/esm.html#esm_customizing_esm_specifier_resolution_algorithm

\n
\n

更新(Node.js v19+):

\n
\n

Node.js 已删除该--experimental-specifier-resolution标志。现在可以通过自定义加载器来实现其功能。

\n
\n

https://nodejs.org/en/blog/announcements/v19-release-announce/#custom-esm-分辨率-调整

\n

最简单的加载器(仅.js在需要时附加扩展)类似于:

\n
import {isBuiltin} from \'node:module\'\n\n// noinspection JSUnusedGlobalSymbols\nexport const resolve = (specifier, context, nextResolve) => // This function can be `async` too\n  nextResolve(isBuiltin(specifier) || specifier.endsWith(\'.js\') ? specifier : `${specifier}.js`, context)\n
Run Code Online (Sandbox Code Playgroud)\n

为其命名loader.js(或者loader.mjs如果您尚未"type": "module"在 中设置package.json)。

\n

然后,如果您使用此加载程序运行脚本(例如./some-script.js):

\n
node --loader ./loader.js some-script.js\n
Run Code Online (Sandbox Code Playgroud)\n

import其中的 s (some-script.js以及其中导入的文件)可以省略.js扩展名。

\n

查看更复杂的示例: https: //github.com/nodejs/loaders-test

\n
\n

更新(Node.js v20.8+):register()/ --import

\n

使用register()函数(来自内置node:module包),然后--import使用标志(而不是--loader):

\n

在我的另一个答案中有一个ts-loader例子,使用(来自):ts-node/esmts-node

\n
\n
import {register} from \'node:module\'\nimport {pathToFileURL} from \'node:url\'\n\nregister(\'ts-node/esm\', pathToFileURL(\'./\'))\n
Run Code Online (Sandbox Code Playgroud)\n

进而:

\n
node --import ./ts-loader.js my-script.ts\n
Run Code Online (Sandbox Code Playgroud)\n
\n

它最初用于使用 Node.js 执行 TypeScript 文件。但它也适用于当前问题的目的。这意味着您可以通过以下方式执行您的models/index.js(或):models/index.ts

\n
node --import ./ts-loader.js models\n
Run Code Online (Sandbox Code Playgroud)\n

此外,使用它,您可以运行js/不带扩展ts名的文件+运行带扩展名的文件(就像您可以使用扩展名在另一个文件中运行文件一样)!tsjsimport tstsjs

\n

  • 谢谢!使用“node --experimental-specifier-resolution=node”效果很好! (4认同)

小智 7

在 Node.js 中,仅允许在 ES 模块中使用 import 语句。因此,目录导入在 Node.js 中不起作用。阅读 Node.js文档

  • 我不确定这是否很有帮助 - Node.js 在本地运行时可以很好地处理这些导入,但在 Heroku 上却遇到了麻烦。也许需要在 Heroku 上设置一些配置。或者你能解释一下为什么情况并非如此吗? (3认同)

dan*_*674 7

尝试将--experimental-specifier-resolution=node标志添加到 中的start脚本中package.json,特别是如果您在本地运行时使用此标志 - 这是 Heroku 将用来启动服务器的脚本。

scripts": {
    "start": "node --experimental-specifier-resolution=node index",
    ...
},
Run Code Online (Sandbox Code Playgroud)