Skip to content

Conversation

@IvanKarpan
Copy link

This MR supports dual package publishing, allowing the package to be consumed by ESM and CommonJS projects without any breaking changes.

Changes

  • Added CommonJS output format to the build process (with .cjs extension)
  • Updated package.json exports field to include both ESM and CommonJS entry points
  • Added "main" field for CommonJS compatibility
  • Updated the README to document CommonJS usage
  • Added tests to verify both ESM and CommonJS imports work correctly
  • Sorted package.json 🙈

Benefits

  • Broader compatibility with different project types and configurations
  • Existing ESM imports continue to work without changes
  • CommonJS users can now use the package with require()
  • No breaking changes for existing projects

@slevithan
Copy link
Owner

I appreciate the high quality PR, but I'm not sure I want to support/maintain CJS. Are you not able to use it as ESM?

Also, I believe this will not correctly solve type resolution for CJS projects. See slevithan/regex#29

Sorted package.json 🙈

You went from one non-obvious but opinionated and intentional sort to a different non-obvious, opinionated sort. 🤷🏻‍♂️ What's the thinking behind it?

…format

revert to original package.json formatting
@IvanKarpan
Copy link
Author

Are you not able to use it as ESM?

My colleague has struggled to make our particular NodeJS, TypeScript, and Jest combo work with your package for a few hours. We tried all the typical tricks found on Stack Overflow and hallucinated by LLMs, but no luck. 🤷🏻‍♂️

Forking your repo, adding CJS support, and switching to this version made my colleague happy immediately. 😅

Also, I believe this will not correctly solve type resolution for CJS projects. See slevithan/regex#29

You are correct. This is something I overlooked.

In my initial MR, there was a problem:

❯ attw --pack

regex-recursion v6.0.2

Build tools:
- typescript@^5.7.3
- esbuild@^0.24.2

👺 Import resolved to an ESM type declaration file, but a CommonJS JavaScript file. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md


┌───────────────────┬────────────────────────┐
│                   │ "regex-recursion"      │
├───────────────────┼────────────────────────┤
│ node10            │ 🟢                     │
├───────────────────┼────────────────────────┤
│ node16 (from CJS) │ 👺 Masquerading as ESM │
├───────────────────┼────────────────────────┤
│ node16 (from ESM) │ 🟢 (ESM)               │
├───────────────────┼────────────────────────┤
│ bundler           │ 🟢                     │
└───────────────────┴────────────────────────┘

I committed a fix for this, and now it looks like so:

❯ attw --pack

regex-recursion v6.0.2

Build tools:
- typescript@^5.7.3
- esbuild@^0.24.2

 No problems found 🌟


┌───────────────────┬───────────────────┐
│                   │ "regex-recursion" │
├───────────────────┼───────────────────┤
│ node10            │ 🟢                │
├───────────────────┼───────────────────┤
│ node16 (from CJS) │ 🟢 (CJS)          │
├───────────────────┼───────────────────┤
│ node16 (from ESM) │ 🟢 (ESM)          │
├───────────────────┼───────────────────┤
│ bundler           │ 🟢                │
└───────────────────┴───────────────────┘

attw is an excellent tool. Thank you for giving me a chance to learn about it.

You went from one non-obvious but opinionated and intentional sort to a different non-obvious, opinionated sort. 🤷🏻‍♂️ What's the thinking behind it?

Since my opinions on what a good-looking package.json is changing quickly and drastically with time and my mood, I decided to put my mind to rest and outsource this to the Sort package.json extension. It is just as opinionated and non-obvious but is automatic (on save), and that's why it impacted my commit, which I noticed after pushing.

In my latest commit, I've reverted to your format.

I'm not sure I want to support/maintain CJS.

That is, of course, for you to decide. We can live with a fork, no problem.

It does look like this comes up from time to time. 😅

Again, up to you.

@slevithan
Copy link
Owner

I'm not sure I want to support/maintain CJS.

That is, of course, for you to decide. We can live with a fork, no problem.

You can probably avoid forking.

I'm not super knowledgeable about CJS and build tools, but what I'd recommend is creating your own CJS bundle. That should be straightforward using e.g. esbuild. E.g. you could add a script to your package.json called "build:regex-recursion" with the value "esbuild node_modules/regex-recursion/src/index.js --format=cjs --bundle --outfile=src/regex-recursion.js" or wherever you want the bundle to go. Add && npm run build:regex-recursion to your build script, then you could require the module from src/regex-recursion.js after building. I haven't tested this, but I think it should work, at least if you're using npm as your package manager (there might be issues with working directly with files in node_modules/ with some other package managers). I do the reverse of this in babel-plugin-transform-regex, converting a CJS only module to ESM.

If that doesn't work, one thing that definitely should is the following:

  • Create a new repo that will be used just to publish a CJS bundle (not a fork).
  • In your new library's JS file, simply export * from "regex-recursion";
  • Use any bundler (such as esbuild) to create a CJS bundle.
    • Don't externalize dependencies. This also means that regex-recursion can optionally be in devDependencies (rather than dependencies) in your package.json.
  • Publish your bundle to npm as e.g. regex-recursion-cjs.

You should then be able to require your regex-recursion-cjs package from any CJS project. You'd need to do a version bump for new versions of the library, but updating package.json and publishing should just take a few seconds.

@IvanKarpan
Copy link
Author

Makes sense. 🙌🏻

Thank you for taking the time. 🙇🏻‍♂️

https://www.npmjs.com/package/regex-recursion-cjs

@IvanKarpan IvanKarpan closed this Apr 4, 2025
@slevithan
Copy link
Owner

Looks great! Nice readme.

Glad that it's working for you now 😊

@slevithan
Copy link
Owner

I've added a link to your wrapper library in the readme: 0396ff3.

@IvanKarpan
Copy link
Author

Thank you! 🙌🏻

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 this pull request may close these issues.

2 participants