discordjs / voice

Implementation of the Discord Voice API for discord.js and other JS/TS libraries
Apache License 2.0
328 stars 112 forks source link

Doesn't find libraries when using ES modules #227

Closed codetheweb closed 2 years ago

codetheweb commented 2 years ago

Issue description

What the title says. When using ES modules, this package can't seem to find the supporting libraries.

i.e.

Discord.js client is ready!
--------------------------------------------------
Core Dependencies
- @discordjs/voice: 0.7.2
- prism-media: not found

Opus Libraries
- @discordjs/opus: not found
- opusscript: not found

Encryption Libraries
- sodium: not found
- libsodium-wrappers: not found
- tweetnacl: not found

FFmpeg
- version: 4.4
- libopus: yes
--------------------------------------------------

even though @discordjs/opus is installed.

See repro.

Code sample

No response

@discordjs/voice version

0.7.2

Node.js version

v16.6.1, TS 4.4.4

Operating system

macOS

Priority this issue should have

Medium (should be fixed soon)

MrPropre commented 2 years ago

This is related to this issue with esbuild https://github.com/evanw/esbuild/issues/946

Affected files are: https://github.com/discordjs/voice/blob/main/src/util/generateDependencyReport.ts https://github.com/discordjs/voice/blob/main/src/util/Secretbox.ts These files use require which is not defined in es module scope. But esbuild should have created the require function in this case.

There is a workaround described in the esbuild issue but maybe we should consider migrating to dynamic import syntax or reading and parsing json files manually

RealAlphabet commented 2 years ago

Same here on Linux (Debian 10 Buster).

codetheweb commented 2 years ago

Since it seems several other people are having this issue as well, would it be possible to add a workaround for now and then perhaps look at other options later (I assume those would take longer than adding a few config lines)?

fredkilbourn commented 2 years ago

Is this a workaround in your build or a workaround we're expected to run in our environment?

RealAlphabet commented 2 years ago

I found a rather elegant solution to avoid modifying all your code to CJS. This way NodeJS will load the CJS version of @discordjs/voice instead of ESM.

import { createRequire } from "module";

const {
    joinVoiceChannel,
    createAudioPlayer,
    createAudioResource,
    entersState,
    VoiceConnectionStatus,
    NoSubscriberBehavior,
} = createRequire(import.meta.url)("@discordjs/voice");

@codetheweb

RealAlphabet commented 2 years ago

Let me reopen this issue to notify of a strange behavior that may occur when using createRequire. https://nodejs.org/api/packages.html#dual-package-hazard

Just to be sure, this should remain a temporary solution until the problem is fixed on esbuild. Otherwise we should find another solution to load the dependencies.