如何修复 必须使用 import 加载 ES Module Discord.js

Cap*_*sst 10 javascript bots node.js discord.js

我正在开发一个机器人,我做了一个烘焙命令,我收到此错误

\n
internal/modules/cjs/loader.js:1089\n      throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);\n      ^\n\nError [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\\Users\\acer\\Documents\\test\\node_modules\\node-fetch\\src\\index.js\nrequire() of ES modules is not supported.\nrequire() of C:\\Users\\acer\\Documents\\test\\node_modules\\node-fetch\\src\\index.js from C:\\Users\\acer\\Documents\\test\\commands\\roast.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.\nInstead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from C:\\Users\\acer\\Documents\\test\\node_modules\\node-fetch\\package.json.\n\n\xe2\x86\x90[90m    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1089:13)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Module.load (internal/modules/cjs/loader.js:937:32)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Function.Module._load (internal/modules/cjs/loader.js:778:12)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Module.require (internal/modules/cjs/loader.js:961:19)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at require (internal/modules/cjs/helpers.js:92:18)\xe2\x86\x90[39m\n    at Object.<anonymous> (C:\\Users\\acer\\Documents\\test\\commands\\roast.js:3:15)\n\xe2\x86\x90[90m    at Module._compile (internal/modules/cjs/loader.js:1072:14)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Module.load (internal/modules/cjs/loader.js:937:32)\xe2\x86\x90[39m\n\xe2\x86\x90[90m    at Function.Module._load (internal/modules/cjs/loader.js:778:12)\xe2\x86\x90[39m {\n  code: \xe2\x86\x90[32m'ERR_REQUIRE_ESM'\xe2\x86\x90[39m\n
Run Code Online (Sandbox Code Playgroud)\n

这是我的roast.js

\n
const random = require("something-random-on-discord").Random\nconst oneLinerJoke = require('one-liner-joke');\nconst fetch = require('node-fetch')\nconst Discord = require('discord.js')\nmodule.exports = {\n    name : 'roast',\n    description : 'roasts a user',\n    \n  async execute(message, args){\n       if (!args[0]) return message.channel.send('Invalid Format')\n       const mentionedMember = message.guild.mentions.member.first();\n       if (!mentionedMember) return message.channel.send('User not found')\n        let msg = await message.channel.send('Setting a roast...')\n\n        fetch('http://evilinsult.com/generate_insult.php?lang=en&type=json')\n            .then(res => res.json())\n            .then(json => {\n                message.channel.send(json.insult)\n            });\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是我的 main.js

\n
// Import the discord.js module\nconst Discord = require('discord.js');\nconst fs = require('fs');\n// Create an instance of a Discord client\nconst client = new Discord.Client();\nclient.commands = new Discord.Collection();\nconst commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));\nconst prefix = "$"\n\n/**\n * The ready event is vital, it means that only _after_ this will your bot start reacting to information\n * received from Discord\n */\nclient.on('ready', () => {\n  console.log('I am ready!');\n});\n \nclient.on('message', message => {\n  if (!message.content.startsWith(prefix) || message.author.bot) return;\n\n  const args = message.content.slice(prefix.length).trim().split(/ +/);\n  const command = args.shift().toLowerCase();\n\n\n  if(command === 'pingg'){\n    client.commands.get('pingg').execute(message, args);\n  }\n  if(command === 'roast'){\n    client.commands.get('roast').execute(message, args);\n  }\n\n\n\n\n  if (!client.commands.has(command)) return;\n\n  try {\n      client.commands.get(command).execute(message, args);\n  } catch (error) {\n      console.error(error);\n      message.reply('there was an error trying to execute that command!');\n  }\n});\n \n\ncommandFiles.forEach(file => {\n  const command = file.split(/.js$/)[0];\n  client.commands.set(command, require(`./commands/${file}`));\n});\n\n\n\nclient.login('censored');\n
Run Code Online (Sandbox Code Playgroud)\n

End*_*ess 16

正如README.md中提到的...另一种实现 fetch@3 的方法是使用节点 v12.20 中支持的node-fetch异步进行导入import()

const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
Run Code Online (Sandbox Code Playgroud)

这也适用于 commonjs(下一个请求不会重新导入 node-fetch,因为模块被缓存)这可以使 Node 进程启动更快,并且仅在需要时延迟加载 node-fetch

这是预加载的另一种方法:

const fetchP = import('node-fetch').then(mod => mod.default)
const fetch = (...args) => fetchP.then(fn => fn(...args))
Run Code Online (Sandbox Code Playgroud)

您不必将孔项目转换为 ESM,因为我们已经做到了。您也可以继续使用 v2 分支 - 我们将不断更新 v2 的错误/安全问题。但新功能并没有那么多......

(还是推荐其他人改用ESM doe)

对于仅关注类型的 TypeScript 用户,您可以执行以下操作:( import type { Request } from 'node-fetch'这不会导入或转译任何内容 - 此类型注释将被丢弃)

有一个关于如何在 cjs 项目中导入/要求节点获取的漏洞部分,位于#1279


Rap*_*OLO 2

如错误所述:

package.json contains "type": "module" which defines all .js files in that package scope as ES modules
Run Code Online (Sandbox Code Playgroud)

你通常有 3 个选择:

  1. 尝试从 package.json 中删除此行以仅在代码中使用 require 。
  2. 或者保留此行并在应用程序中的任何地方使用 import 语句而不是 require 语句(ES6)。
  3. 将您的文件重命名为index.cjs,然后在此特定文件中允许要求,而您仍然必须在其他文件中使用导入。

在您的特定情况下,您使用的node-fetch现在只是esmodule(从版本3开始)。那么唯一可用的解决方案就是到处使用 import 。

要求应该变成这样:

import {Random} from 'something-random-on-discord';
import oneLinerJoke from 'one-liner-joke';
import fetch from 'node-fetch';
import Discord from 'discord.js';
Run Code Online (Sandbox Code Playgroud)

编辑:您还可以删除节点获取或恢复到分支 v2 以继续使用 require。