Exported CommonJS package
seidelmartin opened this issue · comments
Hi @gullerya, first of all, thanks for this nice library I'm very happy that I found it but there's an issue that basically restricts me from using it.
Unfortunately, I'm not able to import that package into my codebase because I'm using CommonJS module resolution and your package is only compatible with ES modules.
Would it be possible to extend you build script so it also produces .cjs
file that uses module.exports = ...
rather than rely on ES export ...
?
I've found an article that can be useful in achieving this https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html
I've created PR that generates also commonjs module #122
Hi @seidelmartin, thanks for kudos, my pleasure!
Sorry for the delay too, has things on the table, work stuff :)
As per CJS here - I do have a couple of concerns about this one, let's talk through couple of them and see if we can find some common ground for this.
I'm generally quite opinionated advocating to leave the CJS behind, actually once I had that support and deliberately dropped it, so it brings few points that I'd like to work along:
- the current default flavor of the ESM including the relevant parts of
package.json
and folders structure to be kept as it is, it is also must to preserve the backward compatibility with the current consumers so that they do not required to change anything in the import paths or alike - I'd like to keep the dependencies at low as possible, and babel (with its dependencies of course) looks to me too bloated comparatively to other tools (probably
unbuild
), adding a dev times and maintenance much more than the worth it brings
I've found another article talking on this topic, this one and would like to see WDYT on this:
- building additional
cjs
distro files (one basic and one minified), namespaced under their own folder (withmin.js
andjs
extensions) - adding the
exports
entry topackage.json
to resolve the default stuff (the concern expressed in the article you've cited is not relevant toobject-observer
) - replacing the
export
statement of the code withmodule.exports
which I'd do myself, without bringing any further dependency
Would that work for you?
After reading a bit more in the formal docs, I think that what I'm suggesting maps well to what described as an Isolate State approach in NodeJS documentation.
Hi, so if I understand it correctly you wouldn't mind to include it back but I need to
- Keep the structure of the
dist
directory the same and on top of that build the CJS module - Build the module with
unbuild
rather thanbabel
Sounds good to me, I'll change it in my PR. :)
Yes, in general I'm okay this this.
And just as a suggestion - even before going for unbuild
can you please check if kind of snippet below can solve it without any tooling at all:
cjsCode = srcCode.replace(/^export/, 'module.exports =');
Replacing export
by module.exports
would in general work. The concern I have is that I would have to move the export statement as very last line of file otherwise Observable
is not initialized. It's also not very scalable if you decide to split index to multiple files.
So I've updated my PR and refactored the build-utils.js
module so it uses mkdir
instead of babel
. The mkdir
is internally used by unbuild
.
You can find the structure of dist
folder below. I think it matches what you've had before with the difference of ESModule build file has mjs
extension.
On top of that, I've also generated source maps since they're useful when debugging from minified file. But I can remove them if you find them useless.
Hi @seidelmartin sorry to bother post factum, but I'd like to make sure I'm not missing anything:
- I've pulled the code
- entered node and just did a simple
require('object-observer')
thing - it is trying correctly to bring
dist/cjs/object-observer.min.js
BUT
For this use case node complains with ERR_REQUIRE_ESM
since:
- the extension is
js
- the module's type is
module
So I think that given that I'd not like to give up on the module type, we need to make the extensions .cjs
for this to work.
WDYT?
And another, minor issue - I'd like to change the main
property of package json from pointing to dist/cjs/..
to the ESM's dist/..
, I can't see it poses any issues for the CJM support, do you?
Interesting, I've been testing it by copying those newly built files to my project's node_modules and it was working just fine. I'm using typescript so maybe it does some magic...
I've created a PR where I address those issues #124
Perfect, thanks!
@seidelmartin I've released 5.1.0 version that includes the CJS porting, also added a relevant portion about this in the readme (Install section) - let me know what you think and if anything is missing we can do a patch release round.
And if all is well from your side - please close this item!
Huge thanks for help!
@seidelmartin any feedback on this one?
Hi, yeah sorry I've been off for some time. It looks fine. I can confirm that latest version works in node with CJS module resolution. Thanks for help.
Sure thing and thanks to you actually, great contribution!!!
🚀