felladrin/typed-event-dispatcher

Parcel builds are not usable with webpack

Closed this issue · 4 comments

It looks like versions 1.10.0 and up are no longer usable from an application that is bundled with Webpack.

When I try to create a webpack bundle, it fails with following error:

WARNING in ../node_modules/typed-event-dispatcher/dist/typed-event-dispatcher.js 18:46-50
Critical dependency: the request of a dependency is an expression
 @ ../node_modules/finder-xenit/index.js
 @ ./index.tsx

The cause of this issue is that calls to require() in the published NPM module must be static and not calculated dynamically for webpack to work. Since this library does not have any dependencies, calls to require() are not actually used, but some wrapping that contains it is added by Parcel.

I took a look at Parcel, and it seems that it is a web application bundler, which iI don't think is suitable for bundling libraries. The main problem being that it wraps the code and tries to handle imports and exports internally.

I see that you moved away from tsc for building this library (9bc47e1), did you encounter issues with it so you had to replace it?
Modifying the build to work with tsc does work, but I guess that breaks some of your usage.

I can help with fixing this issue if you want.

Hi, @vierbergenlars. Thanks for bringing this up! I was not aware about this issue with Webpack.

The reason for changing the build to UMD format was to have single build (to keep the package lightweight) that works for node and the browsers (via https://unpkg.com). Parcel was included just because it was the simplest way to get a UMD bundle.

One solution is to keep the two builds separated in the distributed package.json (like one in 'dist/cjs' (common js) and another in 'dist/umd'), this way I the backward compatibility is maintained, it will be able to be bundled in Webpack, and the package size will increate just a few bytes.

What do you think?

[Side note: I'm using TypedEventDispatcher in another project (which is bundled with Parcel), and didn't have this problem. Maybe it could be solved on Webpack-side with some config? If so I could add a comment on Readme about it.]

I took a look at your other project, according to package-lock.json, you're still using 1.9.0 there. I tried to upgrade the package, and it still seems to work there. Your parcel build there seems to wrap your whole package without attempting to resolve calls to require(). Webpack is a bit more strict in that all require() calls should be static, because you can use different loaders for different kinds of files.

When making this change, you should take the following into account:

  • The main field of package.json shound point to the commonjs build.
  • An additional unpkg field can be added that points to the UMD build. According to the documentation, that's the file that unpkg.com will prefer when referencing your package directly.

For libraries, I use TSDX (it's one of the tools recommended by typescript. It can build your library in a bunch of formats at once (cjs, umd and esm), and without any additional configuration required (similar to using parcel).
A single command will build all three variants: tsdx build --format cjs,esm,umd --name typed-event-dispatcher. At this point, you can also have the ESM build that you can add under the module field of package.json.

I can send you a PR with the change, and you can see if you're happy with it.

Sure! Thanks for taking the time to analyse it!
Your PR is welcome! I'd be happy to use it!

Version 1.11.0 was published with the fix!
Thank you!