Closed bschlenk closed 3 months ago
Thank you so much for the PR and the explanations! Do you think we should do that in v9 or is it safe to ship as is? Is there any import that could potentially break when setting this up?
@bschlenk Hello! đ
Iâm finally getting back to this PR after so long.
I tried it as is, and this is the error I got (both using require
in a .js
file and using import
in a .mjs
file):
Error [ERR_INVALID_PACKAGE_CONFIG]: Invalid package config /Users/kitty/Sites/a11y-dialog-bschlenk-test/node_modules/a11y-dialog/package.json. "exports" cannot contain some keys starting with '.' and some not. The exports object must either be an object of package subpath keys or an object of main entry condition name keys only.
Following the content of the error, I tried updating the configuration to look like this (basically just removing the "."
layer):
"exports": {
"import": "./dist/a11y-dialog.esm.js",
"require": "./dist/a11y-dialog.js",
"types": "./dist/a11y-dialog.d.ts",
"dist/*.esm.js": "./dist/*.esm.js",
"dist/*.js": "./dist/*.js",
"dist/*": {
"import": "./dist/*.esm.js",
"require": "./dist/*.js",
"types": "./dist/*.d.ts"
},
"package.json": "./package.json"
},
This did fix the case of using import
in a .mjs
file (yay!), but when using require
in a .js
file, I got the following error:
Error [ERR_REQUIRE_ESM]: require() of ES Module /Users/kitty/Sites/a11y-dialog-bschlenk-test/node_modules/a11y-dialog/dist/a11y-dialog.js from /Users/kitty/Sites/a11y-dialog-bschlenk-test/index.js not supported. a11y-dialog.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules. Instead either rename a11y-dialog.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /Users/kitty/Sites/a11y-dialog-bschlenk-test/node_modules/a11y-dialog/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).
My understanding is that we should either remove "type": "module"
from the package.json, but I donât know if we want thatâŠ? Or we should spit out .cjs
files when building CJS/UMD, instead of .js
files. We could do that, but then that would be a breaking change, right?
đđ» Hi! (I work with @bschlenk and heâs out for a while)
My understanding is that we should either remove "type": "module" from the package.json, but I donât know if we want thatâŠ?
Right itâs better to keep "type": "module"
in packages. This is the ânewâ way that works universally in browsers and Node. Not having this keeps it in âlegacyâ CommonJS mode. The only reason Node hasnât made "type": "module"
the default is itâs taking a lot of time for legacy packages to update.
Or we should spit out
.cjs
files when building CJS/UMD, instead of.js
files. We could do that, but then that would be a breaking change, right?
It wonât necessarily be a breaking change! As long as itâs set up correctly. But yes all CommonJS output should be in .cjs
files because this package is in âESMÂ modeâ ("type": "module"
). However, having TS definition files in the mix makes it slightly-annoyingâ.cjs
files have to have matching *.d.cts
files (not *.d.ts
).
Whether ESM and CJS lives in the same folder or separate folders is a matter of preference, and doesnât matter.
How we prevent breaking changes is what @bschlenk added in his comment aboveâyou can actually remap exact filepaths to different files in the dist
folder with the exports
object. So you can keep all the old paths for backwards compatibility, while ensuring they work for ESM and CJS (you can think of them like âaliases,â basicallyâto a user they will work exactly the same, but underneath the hood you can rename the package contents).
@drwpow-figma Hello and thank you very much for getting back to me with some very valuable information! I issued a few commits to update the pull-request based on the information I understood. Would you mind doing a code review to see if I didnât mess up anything? Itâs mostly important that we donât cause any breaking change. đ
Would you mind doing a code review to see if I didnât mess up anything? Itâs mostly important that we donât cause any breaking change. đ
Oh so on closer inspection, renaming UMD files to .cjs
is bad, and weâd be breaking users that are using UNPKG, since package.json
is ignored completely by browsers. As a general rule:
.js
(since this is an ESM package with type: "module"
).cjs
.js
or .mjs
(but definitely NOT .cjs
, because browsers will reject that)Sorry I didnât catch this earlier; I was still orienting myself to the package. So your question about the Cypress changes was in fact spot-on: those shouldnât have changed. Let me spend a little time on an improvement for what youâve done to fix the issues in a backwards-compatible way (this is tricky because I donât think the tests comprehensively test all the scenarios that could break for people).
What we can also do if thatâs easier is to assume this change cannot safely be done in a minor, and plan it for v9. And therefore come up with the state-of-the-art setup for all cases.
Opened a PR here: https://github.com/KittyGiraudel/a11y-dialog/pull/701 because I donât know how to open a PR against this one. But you get the gist (you can just cherry-pick the commit; I donât care about attribution).
In my PR, I leave the .js
files as UMD so we donât break backwards-compat with existing installations. But I added building true .cjs
files so that Node is happy, too. This should be a backwards-compatible upgrade, where newer versions of Node get served better files. And everyone already using this library still consumes it 100% the same way.
As I mentioned in one of my messages, it fails if we use both "." and defined paths:
Ah rightâyou know that syntax may be valid too now that I think of it; Iâm just far more used to the dot-preceder. I followed that syntax in my PR, but it may just be personal preference (may not matter).
Closing in favor of #702. Thank you for the super insightful comments here!
What we can also do if thatâs easier is to assume this change cannot safely be done in a minor, and plan it for v9.
Oh also just FYI: in package.json
, module
and types
are deprecated (module
was technically never supported by Node.js; it was just a webpack-ism that spread). Well, types
isnât technically deprecated, but TS now recommends just having types
inside exports
since that will take priority if using that (and all current versions of Node now support this, and probably most people are on recent-enough versions of TS that support this too, so types
is probably just being ignored most of the time by users but it can be kept for backwards compat; see docs).
fixes https://github.com/KittyGiraudel/a11y-dialog/issues/646
Left some inline comments on what each part is for. Mostly I'm being defensive, so that if any of these import patterns are already in use, they'll still work and this can be a minor version bump.
I'd recommend at some point locking this down to just the
.
and thepackage.json
entries and making that a major version bump.