eventsource icon indicating copy to clipboard operation
eventsource copied to clipboard

possible incompatibility of export with Babel

Open eli-darkly opened this issue 5 years ago • 1 comments

I've got a Node project that's written in ES6 and uses Babel and Rollup. There's normally no problem in using imports from CommonJS packages (i.e. basically all Node packages). However, I found that when I did something like this--

import * as EventSource from 'eventsource';

const es = EventSource(url);

--it complained that "EventSource is not a constructor". So I added a try/catch and some debug output to see what it thinks EventSource is. And it turned out to be an ordinary object, with the properties OPEN, CLOSED, and CONNECTING. In other words, it had the same properties that the EventSource export should have, but it should have been a function too and it wasn't.

What I think is going on is that the Babel logic for translating CJS exports to ES6 imports is getting confused. When it sees that module.exports was set to something that looks like an object (i.e. has properties), it thinks that those are named exports. And whatever it does to handle those involves at some point copying the properties over into a new object, which would not make any difference if the original object had been just an object, but in this case it breaks everything. If I'm correct, that means it would have the same problem with any CJS module that had a default export that was a function with properties, but I think that is a pretty rare case.

What I ended up doing was to change the code in my fork to use a single named export instead:

module.exports = {
  EventSource: EventSource
};

That works fine— it treats it as a regular named export and doesn't transform the value of EventSource at all.

I don't know if this is sufficient reason to consider making a similar export change in eventsource (which would of course be a breaking change), but I just wanted to mention it in case anyone else has run into something similar.

eli-darkly avatar Nov 28 '18 18:11 eli-darkly

I imported the module like this, without any problem:

import { default as EventSource } from 'eventsource';

Then you can use it like this:

let source = new EventSource(url, { withCredentials: true });
source.addEventListener(...)

fthernan avatar Oct 02 '22 00:10 fthernan