Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ES Module (ESM) support to the factory #2270

Closed
codingjoe opened this issue Feb 1, 2024 · 21 comments · Fixed by #2428
Closed

Add ES Module (ESM) support to the factory #2270

codingjoe opened this issue Feb 1, 2024 · 21 comments · Fixed by #2428

Comments

@codingjoe
Copy link

Hi there 👋,

Currently, the factory supports AMD, CJS and browser environments.
However, modern websites and browsers have proper module (ESM) support.

Let's say you want to do something like this:

<!DOCTYPE html>
<html lang="en">
<head>
<title>HTMX via ESM</title>
</head>
<body>
<script type="module">
import htmx from 'https://unpkg.com/htmx.org'
htmx.logAll()
</script>
</body>
</html>

Your browser will tell you that htmx.org doesn't export a default. Similarly, something like this also does not work:

import { logAll } from 'https://unpkg.com/htmx.org'
logAll()

Both are completely valid use cases and have, as of writing this, over 97% browser support.

I think adoption would be rather simple. Everything already works in NodeJS or rather CommonJS (CJS). All that's needed would be to extend the factory to export ESM modules in a browser.

If you want to take this one step further, we could also consider to properly defining entry points via NodeJS' exports. This would be particularly helpful if you wish to load extensions.

I would be happy to contribute a small patch.

Cheers!
Joe

@Telroshan
Copy link
Collaborator

Hey, it seems (I know nothing about all this so you tell me 😆) we have esm support in v2 alpha, if you're willing to take a look and test if things work as expected?

@codingjoe
Copy link
Author

Hey, it seems (I know nothing about all this so you tell me 😆) we have esm support in v2 alpha, if you're willing to take a look and test if things work as expected?

Nope, no luck. 2.0 doesn't export anything. And the extensions are not declared in the package.json file, either.

I happen to know a thing or two about ESM, I am happy to help. Just say the word and I will gladly submit a patch.

@1cg
Copy link
Contributor

1cg commented Feb 26, 2024

in v2.0 we have a .esm.js file that does export htmx:

export { htmx }

@codingjoe
Copy link
Author

in v2.0 we have a .esm.js file that does export htmx:

export { htmx }

Yes, I saw that, but that's not how you export an ESM module ;)

@andryyy
Copy link

andryyy commented Feb 26, 2024

I must have missed what export stands for. ;)

And for the sake of everyone’s sanity, let’s not overcomplicate it for nothing.

@alexpetros
Copy link
Collaborator

in v2.0 we have a .esm.js file that does export htmx:

export { htmx }

Yes, I saw that, but that's not how you export an ESM module ;)

Would you like to elaborate on this...? I too have been laboring under the delusion that one exported ECMAScript modules with the export command.

@codingjoe
Copy link
Author

codingjoe commented Feb 26, 2024

Please excuse my previous response. I didn't explain it well. Let me try again:

Yes, export is used to export in ESM, but nothing is ever simple in JavaScript. htmx is an anonymous function. Anonymous functions may only be exported as a default. So, you either name the export, name the function, or export it as a default. Defaults don't need to be named.

Again, super happy to provide a patch, with tests. If my help is still welcome ❤️‍🩹

@1cg
Copy link
Contributor

1cg commented Feb 26, 2024

is it an anonymous function? I thought it was a plain javascript object returned by the IIFE...

@codingjoe
Copy link
Author

is it an anonymous function? I thought it was a plain javascript object returned by the IIFE...

var htmx = (function() {

It's exporting the outer wrapper, not the object. Both would not be leading to the desired result. The latter would allow at least something like import * as htmx from 'htmx.org'. But that's maybe not the way to go here. A default export might be the most elegant and intuitive solution for most.

@alexpetros
Copy link
Collaborator

Please excuse my previous response. I didn't explain it well. Let me try again:

Appreciated! And don't worry about it.

The latter would allow at least something like import * as htmx from 'htmx.org'.

Correct me if I'm wrong, but the current export { htmx } statement we have in the the esm wrapper supports this, right?

@codingjoe
Copy link
Author

codingjoe commented Feb 26, 2024

The latter would allow at least something like import * as htmx from 'htmx.org'.

Correct me if I'm wrong, but the current export { htmx } statement we have in the the esm wrapper supports this, right?

No, it does not. export htmx without the breakets might work… I would need to check.

But again, whether there is a bug, this is fairy easy to reproduce:

Here is HTMX.org 2.0-alpha2
Screenshot 2024-02-26 at 21 41 22

Here is Lit, just to show how a module should look like in a browser.
Screenshot 2024-02-26 at 21 41 45

@alexpetros
Copy link
Collaborator

Oh, I know exactly what you're talking about—you can't export anonymous objects from an export statement i.e. the export {} just doesn't work. I completely forgot about that. Okay so the existing factory is bugged—we can fix that.

Is the change you were going to suggest just export default htmx?

@gedw99
Copy link

gedw99 commented Feb 29, 2024

I am adding myself to this as I also need ESM exports to allow reuse.

there are some hacks to overcome it....

https://github.com/terrablue/htmx-esm btw, is used by

https://github.com/primatejs/primate
https://primatejs.com/modules/htmx

@terrablue
Copy link

If this is implemented, it would be nice to add deep exports in package.json for the extensions such that it's possible to do something like export * from "htmx.org/client-side-templates/handlebars"; to be picked up by the bundler, see https://github.com/terrablue/htmx-esm/blob/master/package.json#L11-L38

I would be more than happy to get rid of the needless vendoring, seeing as I need to update it every time a new HTMX version comes out.

@codingjoe
Copy link
Author

If this is implemented, it would be nice to add deep exports in package.json for the extensions such that it's possible to do something like export * from "htmx.org/client-side-templates/handlebars"; to be picked up by the bundler, see https://github.com/terrablue/htmx-esm/blob/master/package.json#L11-L38

I would be more than happy to get rid of the needless vendoring, seeing as I need to update it every time a new HTMX version comes out.

Yes, I mentioned that in the original ticket report. I will submit a patch for that.

@codingjoe
Copy link
Author

Is the change you were going to suggest just export default htmx?

Yes, I believe this would be most consistent with the docs, where you call htmx.someFunction. Be it on a window or module scope. I will be easy copy and paste for most people.

@codingjoe
Copy link
Author

codingjoe commented Mar 1, 2024

Since there seems to be plenty of traffic on this issue, I will submit a patch targeting the 2.0 release.

codingjoe added a commit to codingjoe/htmx that referenced this issue Mar 1, 2024
codingjoe added a commit to codingjoe/htmx that referenced this issue Mar 1, 2024
@codingjoe
Copy link
Author

I looked at the code for 2.0 and decided to discontinue using HTMX. Maybe someone else will pick this up someday.

@codingjoe codingjoe closed this as not planned Won't fix, can't repro, duplicate, stale Mar 23, 2024
@alexpetros
Copy link
Collaborator

alexpetros commented Mar 23, 2024

I looked at the code for 2.0 and decided to discontinue using HTMX. Maybe someone else will pick this up someday.

Would you like to share what it was about the 2.0 code that discouraged you? It's really not that different

@codingjoe
Copy link
Author

codingjoe commented Mar 24, 2024

I looked at the code for 2.0 and decided to discontinue using HTMX. Maybe someone else will pick this up someday.

Would you like to share what it was about the 2.0 code that discouraged you? It's really not that different

Hi @alexpetros, I would rather not discourage anyone. I know how much work goes into a project this size. Thus, will stick to errors:

  1. extensions are not built in 2.0
  2. test suite wasn't fully working (some files were renamed, but not their references)
  3. extension are neither CSJ or ESM compatible

As a personal note: Tools like Wireit and Rollup or ESbuild might make the build processes more smooth. Lifting browser support to Baseline 2023 might also simplify things.

I appreciate the effort put into this package <3 We use mostly Web Components and are fairly happy writing JavaScript code and have maybe not the ideal user profile.

@alexpetros
Copy link
Collaborator

Ok! Well, anyway, we're going to switch to default exports for htmx 2.0: #2428

@alexpetros alexpetros reopened this Mar 24, 2024
@alexpetros alexpetros linked a pull request Mar 24, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants