react-focus-lock icon indicating copy to clipboard operation
react-focus-lock copied to clipboard

Fix module resolution issues in dual CJS/ESM setup

Open wojtekmaj opened this issue 8 months ago • 6 comments

This PR:

  • Marks the package as ESM-first
  • Ensures backwards compatibility by keeping all CJS files, keeping UI and sidecar pseudo-packages for Node.js 10 compatibility, and adding package.json in dist/cjs to override the above change
  • Uses package.json's exports to ensure all entry points are still valid - in all modes
  • Moves all types to /src, so that they sit alongside the modules they belong to, and so that they are copied separately to /dist/cjs and /dist/es2015 directories.

arethetypeswrong CLI shows a clear improvement:

Before (excl. cjs-only-exports-default):

image Note how every resolution ultimately ends up as CJS.

Before (all rules):

image

After (excl. cjs-only-exports-default):

image Note how Node in ESM mode now correctly resolves ESM modules.

After (all rules):

image Note how while CJS is still kinda-wrong (although it shouldn't probably be an issue), ESM is all green!

Fixes #257

wojtekmaj avatar Oct 12 '23 11:10 wojtekmaj

Give me some time to test integratons.

theKashey avatar Oct 13 '23 05:10 theKashey

One improvement that comes to my mind is that .d.ts files sitting in pseudorepo /sidecar and /UI directories could reexport type definitions from /dist/cjs instead.

wojtekmaj avatar Oct 13 '23 08:10 wojtekmaj

I would really like to rewrite focus-lock in TS and don't worry about manual type declarations. So, don't worry about them 😉

theKashey avatar Oct 14 '23 22:10 theKashey

Oh, time flies and I am still buried in work. Sorry, should become more free closer to the new year.

theKashey avatar Dec 13 '23 02:12 theKashey

Don't worry mate. No one has the right to expect anything from you for $0.

wojtekmaj avatar Dec 13 '23 07:12 wojtekmaj

This issue has been marked as "stale" because there has been no activity for 2 months. If you have any new information or would like to continue the discussion, please feel free to do so. If this issue got buried among other tasks, maybe this message will reignite the conversation. Otherwise, this issue will be closed in 7 days. Thank you for your contributions so far.

stale[bot] avatar Feb 13 '24 02:02 stale[bot]

This issue has been marked as "stale" because there has been no activity for 2 months. If you have any new information or would like to continue the discussion, please feel free to do so. If this issue got buried among other tasks, maybe this message will reignite the conversation. Otherwise, this issue will be closed in 7 days. Thank you for your contributions so far.

stale[bot] avatar Apr 14 '24 11:04 stale[bot]

Bad bot!

wojtekmaj avatar Apr 14 '24 13:04 wojtekmaj

I am a little hesitant to move forward due to the problem highlighted at https://github.com/gregberge/loadable-components/pull/1003

  • single package expected to be a "singleton"
  • being imported from ESM and CJS
  • ending as two different packages imported and not knowing about each other

This moves change from "just here" to "all consumers".

The "safe" way forward lies in refactoring of react-clientside-effect in order to make it "duplication aware", for example via tracking singletons via stable(string) keys.


The question I dont have an answer for - what is required from downstream packages in order to make this one ESM-compatible. Ie, do I need to esm react-clientside-effect, potentially causing the same "duplication" to it, or can keep it as is, making it easier to track references.

@wojtekmaj - I really hope you have some answers for the questions above, well the one question - managing "singleton" in ESM packages.

theKashey avatar Apr 15 '24 00:04 theKashey

@theKashey - The approach I took with dual ESM/CJS config presented here was battle tested in React-PDF, React-Calendar, React-Date-Picker and many other packages I maintain.

I do understand your concerns though.

react-clientside-effect looks like a fairly simple module ESM should have no issues with. It might be converted to dual CJS/ESM, but doesn't need to be. I confirmed this by running an ESM version of react-focus-lock from this PR in pure Node.js, and checked that withSideEffect is still a function and not e.g. { default: [Function: withSideEffect] }.

wojtekmaj avatar Apr 15 '24 08:04 wojtekmaj

I rebased the PR off latest master, and edited the first comment, since now the PR is making everything green, not just ESM module resolution!

wojtekmaj avatar Apr 15 '24 08:04 wojtekmaj

and checked that withSideEffect is still a function

More about there is a possibility to reach withSideEffect via require path and then via import path, resulting in two different worlds, not one singlenton.

Could affect only cases with multiple modals being open using different ways to open them. Not sure how "real" this case is, but it's the only moment that separates this package from others.

theKashey avatar Apr 15 '24 09:04 theKashey

Not sure how "real" this case is

Most bundlers will probably use ESM, because they are capable of resolving ESM. Even if the modules are CJS, they are "wrapped" so that they could all talk to each other seamlessly. If you don't use any bundler at all, you're forced to use ESM, because CJS doesn't work outside of Node. I may be missing something here, but I don't see how you'd end up with two versions of react-focus-lock. Perhaps in a Node.js-only application, where you could actually use both import in ESM and require in CJS, but that's not a realistic scenario for a front-end package, and also, if you write both ESM and CJS in one Node.js project, you really should reconsider your life choices.

wojtekmaj avatar Apr 15 '24 09:04 wojtekmaj

I tend to agree - the problem with loadable-components happened at the server side and FocusLock is a purely front-end component, including the "dangerous part" being named as react-CLIENTSIDE-effect

theKashey avatar Apr 16 '24 01:04 theKashey

It will take a few days to test it as deeply as I possibly could...

@wojtekmaj+++ and 🙇 for all your effort and impact.

theKashey avatar Apr 16 '24 01:04 theKashey