chai: ERR_REQUIRE_ESM in v5
Hi there,
I don’t have all the details, as I don’t have access to my workstation right now, but our CI is failing with this error for all our projects using chai when trying an upgrade to chai@5. These projects are commonjs modules using require('chai') everywhere in tests, running under Node 20.
Is chai now ESM-only?
I can gather more details if required, feel free to ask.
Thanks, David
About this issue
- Original URL
- State: closed
- Created 6 months ago
- Reactions: 5
- Comments: 41 (16 by maintainers)
Commits related to this issue
- Updated dependencies and lock file - Held back Chai due to breaking change requiring ESM https://github.com/chaijs/chai/issues/1561 - Updated date-fns and react-datepicker both working — committed to FamilySearch/pewpew by tkmcmaster 6 months ago
- Update Dependencies 2023-12-28 (#189) * Updated dependencies and lock file - Held back Chai due to breaking change requiring ESM https://github.com/chaijs/chai/issues/1561 - Updated date-fns and ... — committed to FamilySearch/pewpew by tkmcmaster 6 months ago
- Update Dependencies 2023-12-28 Scripting (#190) * Update readme (#187) * Moved the pewpew README under the src folder since it's pewpew binary specific * Added new README for overarching design... — committed to FamilySearch/pewpew by tkmcmaster 6 months ago
- Change only tests to `mjs` https://github.com/chaijs/chai/issues/1561#issuecomment-1874073866 > As of 5.0.0, chai only ships with ES modules going forward (no longer commonjs). — committed to abetomo/nroonga by abetomo 6 months ago
- Change only tests to `mjs` https://github.com/chaijs/chai/issues/1561#issuecomment-1874073866 > As of 5.0.0, chai only ships with ES modules going forward (no longer commonjs). — committed to abetomo/nroonga by abetomo 6 months ago
- Remove `chai` dev dependency There is no plan to convert this module to ESM Rel: https://github.com/chaijs/chai/issues/1561 Rel: https://github.com/Dintero/njs-tfso-xml/pull/13 — committed to Dintero/njs-tfso-xml by frodeaa 5 months ago
- Remove `chai` dev dependency There is no plan to convert this module to ESM Rel: https://github.com/chaijs/chai/issues/1561 Rel: https://github.com/Dintero/njs-tfso-xml/pull/13 — committed to Dintero/njs-tfso-xml by frodeaa 5 months ago
- Remove `chai` dev dependency (#15) There is no plan to convert this module to ESM Rel: https://github.com/chaijs/chai/issues/1561 Rel: https://github.com/Dintero/njs-tfso-xml/pull/13 — committed to Dintero/njs-tfso-xml by frodeaa 5 months ago
- Remove `chai` dev dependency (#15) There is no plan to convert this module to ESM Rel: https://github.com/chaijs/chai/issues/1561 Rel: https://github.com/Dintero/njs-tfso-xml/pull/13 — committed to Dintero/njs-tfso-xml by frodeaa 5 months ago
- Remove `chai` dev dependency (#15) There is no plan to convert this module to ESM Rel: https://github.com/chaijs/chai/issues/1561 Rel: https://github.com/Dintero/njs-tfso-xml/pull/13 — committed to Dintero/njs-tfso-xml by frodeaa 5 months ago
- Stick to chai v4 for now See https://github.com/chaijs/chai/issues/1561#issuecomment-1874073866 — committed to NCI-Agency/anet by gjvoosten 3 months ago
chaicould have waited until Node 22 released. Because it’s going to get the support of interoperability between CJS and ESM at runtime. (I ranted about it here.)Otherwise, chai v5 is going to break a lot of CI/CD pipelines out there.
To clarify some points:
package.jsonis not using^or~prefixes, you may want to address that as you’ll likely encounter issues from many packages in the ecosystem which adhere to the semver contract.To talk about the motivation for this change, especially from the lens of the ecosystem of available build tools: there is a complexity trade off for libraries like Chai to support each of these build tools, and it becomes somewhat of an N*M problem. Standards allow us to target a single syntax to reach the broadest support, and will be an inevitable shift in the JS ecosystem, it is just a matter of “when”. Version 5 is chai’s “when”. Certainly if we are the first to support ESM it would cause undue friction, but if we were last it would also cause undue friction. Packages like
@esm-bundle/chaialready exist which demonstrate the friction is there today. There is no time we could have made this change that would satisfy all users. The Chai team is very confident we’ve made the right decision so support ESM only, and Chai >5 will continue to support only ESM (or whatever module system the EcmaScript standardises) indefinitely.OK.
That’s clearly sad news and something I personally don’t understand considering the plethora of build tools (from the top of my mind https://github.com/egoist/tsup and https://github.com/unjs/unbuild at least) that can double-build at near 0 cost… Lots of very large projects are still commonjs, Node still has first class support for commonjs, etc.
Anyway, thanks for confirming and long live to Chai 👍
Cheers, David
Probably should have removed all the references to
require('chai')from the documentation as part of this change!It is esm only in 5.x
You can still use a dynamic import to import it in node at least afaik, but should probably just stick to 4.x until you can migrate to esm (feature set shouldn’t be much different)
In case anyone else comes to this thread trying to use
mochaandchaitogether, using cjs modules;For me,
await import('chai')broke tests due to its asynchronous nature - none of the tests ran. This was regardless of whether I used async/await on mydescribe()andit()calls. I had to make use of mocha’sbefore()for this:I hope from this issue it’s apparent how this change may have potentially cost many hours of human effort on part of all the developers who use this module in their unit tests. The issues surrounding ESM and CJS are known, plentiful, and widespread; IMO all of the very popular node.js modules should be responsible for ensuring things go smoothly with both systems, regardless of the opinions of the maintainers on ESM vs CJS.
This is an open source project and so it is up to the contributors we have to resolve issues and add features. The core maintainers (which is a group that changes over time) may raise PRs and make changes, but they can also mentor and guide contributors to do the same. This is to say if you are aware of a security fix that needs to be back-ported to
4.x.xyou can raise a PR for it, against the4.x.xbranch, and a core maintainer will steer it in the right direction.All the while the
4.x.xbranch is open I’m happy to approve/merge PRs and cut releases for Chai 4. I can’t give a definitive answer on when we’ll delete that branch because ultimately it’ll be “when it feels right”. Certainly the majority of feature development will be done in Chai@5.We typically get about 9MM downloads a week. Last week was particularly low because of the holidays but we saw about 4MM downloads. Of that 4MM, 100k of that is chai@5 (2.5%), about 300k for chai@3 (7.5%), and 3.6MM for chai@4 (87.5%). We do not get issues for Chai@3 and I don’t think we’d cut a new release for the 3.x series, so one heuristic you could look at is this. Should Chai@4 reach 7.5% of our version distribution, I could foresee it being EOL then, but that’s not the case today.
you are right, i’ll close this.
for anyone bumping into this error
As of 5.0.0, chai only ships with ES modules going forward (no longer commonjs).
For those of you with ES module packages
Everything should work as you’d expect. You’re probably in this category if:
"type": "module"in yourpackage.json(i.e. it is an ESM project)For those of you with CJS packages
You’re in this category if you don’t follow any of the previous structures, and/or you use typescript with
"module": "commonjs".In this case, you have a couple of options:
const chai = await import('chai'))If you can’t use a bundler at that point in your project, it is probably best to stay on chai 4.x until you move to ES modules one day (if ever).
ts-node
If you’re using ts-node, it has support for ES modules and more information here.
Keep in mind, you would have to migrate your own project to use ES modules to use this. So please just refer to the previous 2 sections above (CJS, ESM) for whichever you’ve chosen to use right now.
notes
Migrating to ESM is no simple task, so i’m sure many of us will still be stuck with commonjs for the near future at least.
In those cases, my personal opinion (not speaking for chai), is that i’d use 4.x with the aim of one day performing the ESM migration.
the feature sets between 4.x and 5.x are near identical. it is perfectly fine to stay on 4.x for now
discussion still needs to happen around security fixes etc, but i’m sure we won’t be leaving those of you on 4.x still behind.
Amazing answer @keithamus This great communication skill is the reason why I am one of your followers on Twitter.
My questions are all sorted. I am happy to see much professionalism and community focused project governance.
Cheers people!
Have a great year. 😃 🎄
ah i see now
yeah unfortunately just because of how standard import syntax works in JS, we can’t really chain it that way anymore. so it means you’d just have to do something like this:
how did you use it before?
i suspect you need to do something like this:
or
Not really a minimal reproduction 😅
I can’t install the dependencies and get it up and running. A minimal reproduction should be the least amount of code and build setup in order to reproduce the error in question.
As far as I can tell with the information given this seems to be some sort of configuration issue in TypeScript? The code is using native JavaScript modules but maybe the
tsconfig.jsonis set to output CommonJS? The quick solve here would be to dynamically import chai as that should work in a CommonJS environment.Might be worth looking into your TypeScript setup but I don’t think this is a issue with Chai.
They don’t build at zero cost, nothing does. Inevitably, you need to publish a CJS entry point and an ESM entry point.
On top of that, to work in browsers, you need to purge cjs entirely from the tree - this means publishing an entire cjs version and an entire esm version (no wrappers).
There’s so many reasons to do this, that have been discussed.
People on very old node can continue to use 4.x, the feature set is near enough the same.
I agree, I wasn’t aware a 5.0 was being published today. @koddsson if you’re already digging around the repo, maybe you could update the docs too?
we still haven’t had chance to discuss it as a group yet, i’ll try get hold of the others soon so we can answer you
my personal preference (not speaking for chai) would be to do security fixes for some time, until more people move (which could be a long time)
Another option is to put it into mocha global setup so its only there and you don’t need to worry about it in any other test file
You should avoid using wildcard dependencies versions like
"chai": "*". If the tutorial told you to do that then the tutorial is giving you bad advice and it should be corrected to say something like"chai": "^4.3.10".The reason for this is exactly what you’re discovering: a new major version of
chaican contain breaking changes.presumably your project is commonjs? if that’s the case, you’d have to use a dynamic import to import chai 5.x. but in those cases, i’d just stick to 4.x until you can migrate your own project to use ESM.
if you can show a reproduction somewhere, i can take a look.
in ESM projects, mocha needs a loader instead of a require hook (
"loader": "ts-node/esm").i’m happy to help as it is important for all of us and many other packages to move the ecosystem forward to a standardised module system like this. i do understand it isn’t a quick job to move to ESM, though, so i have no doubt we will still be supporting 4.x in some way.
why do you think this?
v5 is ESM only, following the standard module system node and browsers are aligning on going forward
v4 still exists for those who, for whatever reason, can’t use dynamic import or can’t migrate to ESM.
i’m sure in terms of security, we could continue updating a v4 branch meanwhile. needs some discussion but that seems to be the sole reason we need to keep 4.x around, since we’re not changing feature set.
no, it was an active decision to move towards using the standard module system all platforms are aligning to. it isn’t a misconfiguration
it would be good to understand what your concerns drill down to, as there’s absolutely no reason to be moving off chai just because you can’t yet upgrade to 5.x.