zustand: Importing in a `type=module` project fails
First: thanks for the simplified version of state management. So glad I found it, so sad it took me so long đ.
I created a small project, where the package.json
sets it to be a ESM project, by type=module
.
See https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/package.json#L4
I ran into two issues, that are somehow related to #201 but I am not sure exactly whatâs the root cause.
The Problem(s)
I wanted to get zustand to be testable with mocha in an ESM setup. But I ran into:
- When using
type=module
and importingzustand/vanilla
mocha says there is no such file. No idea what that might be. This is the JS file and the error it throws: https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/src/vanilla.test.js - When importing
zustand/vanilla.js
the default export is somehow broken. A change ofexports.default = create;
to
module.exports = create;
inzustand/vanilla.js
would fix it. This sounds like a packager problem in zustand? https://codeberg.org/wolframkriesing/bug-exploration-zustand-and-esm/src/branch/main/src/vanilla-js.test.js
Is the ESM setup just not there yet, and not recommended? I had hoped to go there gradually. How do others solve this issue?
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 33 (15 by maintainers)
Sounds like a tricky one, not fun. What about a (challenging) suggestion: Why not ship ESM only? One file, only import/export, pure ESM. Why?
Sounds more like a major version thing, and it might prevent more compat work?
I donât know of a pattern that would allow you to get rid of the preceding require. Nodeâs the limiting factor there in the keys it has implemented.
As for the dual hazard, I suppose the only way to tell is to test. Iâll try a few things out, see if I can get something to break.
#357 adds ânodeâ only. So, without ârequireâ node with require() breaks. Hmmm.
Why doesnât it work with pointing at
esm/index.js
? I see it doesnât know if itâs mjs or cjs.Yeah, there are some 3rd party zustand packages and a few jotai packages (the library use is a big selling point in jotai.)
I originally thought that too and tried, but it breaks old bundlers which donât understand
exports
or something like that. We should keep .js and do things inexports
.The âworkaroundâ requires using the
default
key on the exported object, i.e.,import create from 'zustand/vanilla';
returnscreate: { default: <create function> }
, socreate.default()
is needed.Edit: Might just be something that needs to be hashed out next major. Altering
exports
in any way really causes breaking changes, so itâd be easier to figure this out going forward on a v4@wolframkriesing Yeah, like @rschristian mentioned, the current v3.4.1 config only uses cjs even if you have
type=module
. This is regretful, but intentional for some reasons mentioned above.We would like to have better ideas in the future.
My question for now is if the original issue with
type-module
is solved (as workaround) with v3.4.1 with CJS, that was not solved in v3.3.3.@rschristian I forgot to mention that specifying
import
incurs dual package hazard. https://nodejs.org/api/packages.html#packages_dual_package_hazardThis is a real issue with valtio. For zustand, it might not be important because right now we donât have such exports. (but we plan to add a new feature which impacts on it.) We also want to keep the configs consistent as much as possible among zustand/jotai/valtio for maintainability.
So far, I donât find any good configs to allow mjs in node. Letâs keep research on it.
As mentioned in the above comments, the current setup only supports Webpack v5. The key used in
exports
(module
) is not implemented by anything else as far as I know. Definitely not standard, though I suppose something out there could also support it.As far as I can tell, webpack esm and nodejs mjs is not 100% equal.
@wolframkriesing We releaseed v3.4.1 lately and it ended up with something like what you suggested in #336 originally. Would you see how it works or not in your use case?