Skip to content

Build packages with unbuild to improve CJS support #2310

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 10, 2025
Merged

Build packages with unbuild to improve CJS support #2310

merged 1 commit into from
May 10, 2025

Conversation

drwpow
Copy link
Contributor

@drwpow drwpow commented May 10, 2025

Changes

Unbuild is a fantastic packaging system that is the best available in my opinion. Build all our packages with it to reduce maintenance and overhead, and improve support. It’s still ESM-first, so there should be no changes to runtime, client weight, or bundlesize downstream, and only improves stability and support.

This also aligns openapi-typescript, openapi-fetch, openapi-react-query, and swr-openapi to all be built the same way.

If this causes any issues, please file an issue! Anything that crops up is fixable with the Unbuild system because it’s based on Rollup.

How to Review

  • Tests cover existing usecases (we often test built code)!

Checklist

  • Unit tests updated
  • docs/ updated (if necessary)
  • pnpm run update:examples run (only applicable for openapi-typescript)

@drwpow drwpow requested a review from a team as a code owner May 10, 2025 16:33
@drwpow drwpow requested a review from htunnicliff May 10, 2025 16:33
Copy link

changeset-bot bot commented May 10, 2025

🦋 Changeset detected

Latest commit: a340c6d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
openapi-fetch Minor
openapi-react-query Major
openapi-typescript Minor
swr-openapi Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

netlify bot commented May 10, 2025

Deploy Preview for openapi-ts canceled.

Name Link
🔨 Latest commit a340c6d
🔍 Latest deploy log https://app.netlify.com/sites/openapi-ts/deploys/681fbba9dc4bc2000872e1c9

Copy link
Contributor

github-actions bot commented May 10, 2025

size-limit report 📦

Path Size
packages/openapi-fetch/dist/index.min.js 0 B (-100% 🔽)
packages/openapi-fetch/dist/index.mjs 6.7 KB (+100% 🔺)

@drwpow drwpow force-pushed the unbuild branch 7 times, most recently from 4799af3 to f375ba6 Compare May 10, 2025 20:26
"default": "./dist/index.js"
},
"require": {
"types": "./dist/cjs/index.d.cts",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With separate .d.cts and .d.mts declarations generated, we don’t need to declare types separately. This was a little bit of a hack from previous builds that stuck around. With unbuild’s better generation in general, TypeScript can automatically locate types.

@@ -8,19 +8,12 @@
},
"license": "MIT",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"module" has never been standardized, but was just a common community convention—common enough it started to sneak into some bundle setups. All Node LTS versions and all bundlers I’m aware of now respect "exports", which means this is no longer needed.

"main" is still standard. And technically it’s superceded by exports, but we’ll just keep it around for safety. But "module" is safe to remove at this point.

@@ -8,19 +8,12 @@
},
"license": "MIT",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for "types"—at this point TypeScript can now just locate the types due to unbuild’s careful handling

},
"./*.js": "./*.mjs",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unbuild intentionally ships .mjs so there’s no ambiguity about the .js files being ESM, and there’s no way to opt out of this behavior. While in our case we’ve been shipping ESM for a while, I still agree in general—.js files is a bit of a clusterfuck trying to sniff out package.jsons to know how to parse it.

This is encroaching on a breaking change for this library, but I’m just considering it a minor version because:

  • Deep imports have never had a strict guarantee they’ll be preserved perfectly
  • This extension rewriting should preserve .js imports as-authored
  • We’re still building files 1:1 to their original versions, just with .mjs extensions, so even if a setup does break it’s a mild annoyance not a show-stopper

@drwpow drwpow force-pushed the unbuild branch 3 times, most recently from cef463a to 5772987 Compare May 10, 2025 20:39
"test:js": "vitest run",
"test:ts": "tsc --noEmit",
"test:ts-no-strict": "tsc --noEmit -p test/no-strict-null-checks/tsconfig.json",
"test:exports": "pnpm run build && attw --pack .",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like the “are the types wrong” type tests, so added to all packages. We were also able to remove the cjs-resolves-to-esm rule 😎

@@ -1,4 +1,5 @@
.turbo
*.config.*
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore build.config.ts configs for unbuild in package publishing

// Ship CommonJS-compatible bundle
emitCJS: true,
// Don’t bundle .js files together to more closely match old exports (can remove in next major)
output: { preserveModules: true },
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

openapi-metadata was already using unbuild! But adding this config just shores it up more closely with the other packages without changing output too much.

@drwpow
Copy link
Contributor Author

drwpow commented May 10, 2025

Merging this not to bulldoze anyone; this is just a very unopinionated PR that is just package maintenance. The change does require a version-bump just to guard against accidental regressions, but anything that crops up is fixable/changeable.

Overall this should be a net win for everybody, improving CJS support and build quality.

@drwpow drwpow merged commit e66b5ce into main May 10, 2025
14 checks passed
@drwpow drwpow deleted the unbuild branch May 10, 2025 21:00
@openapi-ts-bot openapi-ts-bot mentioned this pull request May 10, 2025
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.

1 participant