developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
8.03k stars 362 forks source link

Expected package.json for modern ESM-only packages? #977

Closed donmccurdy closed 2 years ago

donmccurdy commented 2 years ago

I've been using microbundle for a while, to publish packages that include both CJS and ESM entrypoints, and are meant for use in both Node.js and Web. I'm trying to migrate most of these packages to include only ESM entrypoints — I understand this requires modern Node.js versions, and may break older bundlers. With those hazards acknowledged, I'm still having trouble figuring out the right configuration of microbundle. I found this guide to ESM-only packages which suggested dropping main and module entries entirely, adding "type": "module" and publishing only an exports entrypoint. I tried that, but I'm immediately seeing downstream issues, such as bundlephobia being unable to read the package (EntryPointError). I know Parcel doesn't support 'exports' yet. I'm also seeing here that "type": "module" should be used with exports, and may not work properly with main or module. Probably none of these are authoritative answers, but it's confusing taken all together.

tl;dr — Microbundle tends to be batteries-included and opinionated, which I appreciate. Do you have any recommendations for what 'package.json' should look like in a package that only includes an ESM entrypoint? Is this reasonable? Thanks!

"type": "module",
"sideEffects": false,
"source": "./src/index.ts",
"exports": "./dist/my-package.modern.js",
"types": "./dist/index.d.ts",
rschristian commented 2 years ago

I'm also seeing here that "type": "module" should be used with exports, and may not work properly with main or module.

Partially incorrect. Setting the package type does affect "main", but not "module". "module" long predates this system and was spec'd specifically as an ESM entry point for bundlers. "module" is always ESM and is ignored by Node.

But you ran into the crux of the issue here in that modern, ESM-only builds sounds great, but there's a whole ton of tools that just don't support that yet. If you're not taking a hardline, idealogical stance like Sindre did, and instead are willing to make concessions for usability (like supporting Bundlephobia or Parcel), then you may just want to stick with the config we've suggested.

{
  "type": "module",
  "sideEffects": false,
  "source": "./src/index.ts",
  "exports": "./dist/my-package.modern.js",
  "types": "./dist/index.d.ts"
}

This could be one way to achieve what you want (modern, ESM builds only), yes. Whether it's "reasonable" or not depends entirely on your usage and what you want to support.

FWIW, this is how I've published a fair number of my own packages, and works great for my needs. Your experience may vary.

Edit: Supporting "module" for older bundlers/build tools might get you a lot closer to compat though:

{
  "type": "module",
  "source": "./src/index.ts",
  "module": "./dist/my-package.esm.js"
  "exports": "./dist/my-package.modern.js"
}

Won't do anything for older versions of Node, but should work just fine for Parcel, Bundlephobia, and the like.

donmccurdy commented 2 years ago

Thanks @rschristian! I have my reasons for wanting ESM-only builds, only some of which are idealogical. 😉 Supporting the various build configurations has cost many hours of my time, as a package maintainer. It's awesome how easy microbundle makes it to include a main entry, but unfortunately this doesn't solve things like WASM and dynamic imports, which have been troublesome for years. I've already had to give up trying to provide end-user support for people having trouble with CJS and UMD builds — we get way too many of these requests, mostly from new developers. At a certain point as a maintainer it doesn't feel right publishing in formats I can't honestly recommend, or properly support.

The combination of module and exports looks like it will work, though I'm sure you're right that I'll bump into lots more tools that don't support this fully and will need to work through that and report bugs accordingly. I appreciate your help!