djipco / webmidi

Tame the Web MIDI API. Send and receive MIDI messages with ease. Control instruments with user-friendly functions (playNote, sendPitchBend, etc.). React to MIDI input with simple event listeners (noteon, pitchbend, controlchange, etc.).
Apache License 2.0
1.53k stars 115 forks source link

import {WebMidi} from "webmidi" not working in node #269

Closed abulka closed 2 years ago

abulka commented 2 years ago

Description import {WebMidi} from "webmidi" is not working in node, despite what the official documentation says. I get an error about Named export 'WebMidi' not found.

To reproduce, simply create a new directory

run with node main.js and I get

$ node main.js 
file:///private/tmp/wwww/main.js:1
import {WebMidi} from "webmidi";
        ^^^^^^^
SyntaxError: Named export 'WebMidi' not found. The requested module 'webmidi' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'webmidi';
const {WebMidi} = pkg;

my package.json is

{
  "type": "module",
  "dependencies": {
    "webmidi": "^3.0.19"
  }
}

Environment:

Seems also to be related to issues #89 and #82

Details Add any other information, context or details that could help track down the problem.

Trying an alternative import syntax

import * as WebMidi from "webmidi"

instead changes the error to:

$ node main.js 
(node:53862) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/private/tmp/wwww/node_modules/webmidi/dist/esm/webmidi.esm.min.js:395
 */const u=new class extends ................. WebMidi};

SyntaxError: Unexpected token 'export'
    at Object.compileFunction (node:vm:352:18)
    at wrapSafe (node:internal/modules/cjs/loader:1031:15)
    at Module._compile (node:internal/modules/cjs/loader:1065:27)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:190:29)
    at ModuleJob.run (node:internal/modules/esm/module_job:185:25)
    at async Promise.all (index 0)
    at async ESMLoader.import (node:internal/modules/esm/loader:281:24)

Taking node's advice and changing the import to

import pkg from 'webmidi';
const { WebMidi } = pkg;

fails with the same Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.... SyntaxError: Unexpected token 'export' error.

Discussion

Interestingly, the simple module example given in #252

import {WebMidi} from "webmidi";

WebMidi
  .enable()
  .then(onEnabled)
  .catch(err => console.log(err));

function onEnabled() {
  console.log('WebMIDI enabled!');
  const output = WebMidi.outputs[0]
  const channel = output.channels[1];
  console.log(channel);
  channel.playNote('C5', {duration: 5000})
}

supposedly works for @djipco - but I can't get past the import problem mentioned above.

djipco commented 2 years ago

You are very right. As I explain here, PR #254 introduced a regression problem that prevented Node.js from correctly identifying the type of module to load (ESM or CommonJS)

The problem has been fixed in release 3.0.20 and is now available on NPM.

This highlights the need for plaftorm-targeted unit tests going forward. Thanks a lot for reporting.