build: replace webpack with Vite and ship a real ESM/CJS package - #204
Conversation
The webpack build emitted a single UMD bundle and pointed both "main" and "module" at it. UMD cannot be tree-shaken, so every consumer paid for the whole library no matter what they imported (#118). Build: - vite.config.mts replaces webpack.config.js and webpack.libConfig.js - emits ESM, CJS and UMD; UMD is kept so existing script-tag users are unaffected - declarations are bundled into one flat index.d.ts via vite-plugin-dts, and copied to .d.mts/.d.cts so both exports conditions resolve correctly - adds an "exports" map with per-condition types - src is now published so the shipped sourcemaps actually resolve Two things had to be set explicitly, both of which failed silently by default: - JSX is pinned to the classic runtime. The bundler does not inherit "jsx" from tsconfig.json and defaults to the automatic runtime, which inlined the whole of react/jsx-runtime into the bundle and emitted a require("react") that threw on import from ESM. It would also have broken the declared react >=16.8 peer. - Target moves from ES5 to ES2015, because esbuild cannot emit ES5. browserslist already excluded IE11, so nothing supported is lost. Sizes, production build: UMD 25,866 -> 18,874 raw 7,873 -> 6,880 gzip import { useXarrow } only 26,661 -> 16,408 raw 8,847 -> 6,349 gzip CI now loads both entry points from the packed tarball and runs @arethetypeswrong/cli. A filename check would not have caught the broken ESM output above. Drops webpack, webpack-cli, webpack-node-externals, babel-loader, ts-loader, file-loader, the five @babel packages, .babelrc and ts-node. Version is deliberately left at 2.0.2; this is consumer-visible and wants a minor bump, but publishing is blocked until the npm Trusted Publisher is registered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
|
Warning Review limit reached
Next review available in: 46 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe package replaces Webpack and Babel library builds with Vite. It publishes ESM, CJS, UMD, and declaration outputs, defines conditional exports, and adds CI checks for packed-package contents and consumer resolution. ChangesLibrary build and publishing
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Developer
participant Vite
participant Package
participant CI
participant Consumer
Developer->>Vite: run build
Vite->>Package: emit ESM, CJS, UMD, and declaration files
CI->>Package: inspect packed contents
CI->>Consumer: install packed package
Consumer->>Package: import or require entry point
Package-->>Consumer: provide default and named exports
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/ci.yml:
- Around line 70-71: Add a reviewed, pinned `@arethetypeswrong/cli` version to
devDependencies and regenerate the lockfile. Update the “Verify type resolution”
workflow step to invoke the installed pinned dependency rather than npx with the
latest tag.
In `@vite.config.mts`:
- Around line 50-57: Update the Rollup configuration around external and output
handling so lodash remains bundled in the UMD build instead of requiring
window._, while preserving the existing externalization for other formats. Add a
UMD smoke test that loads the generated bundle with React dependencies but
without lodash and verifies it initializes successfully.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 213f8752-916b-4052-b7ee-f88fc13ef70d
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (7)
.babelrc.github/workflows/ci.ymlpackage.jsontsconfig.jsonvite.config.mtswebpack.config.jswebpack.libConfig.js
💤 Files with no reviewable changes (3)
- webpack.config.js
- .babelrc
- webpack.libConfig.js
Review feedback on this PR. - @arethetypeswrong/cli was invoked as npx ...@latest, so CI silently tracked whatever release was current. Pin it in devDependencies and run it via pnpm exec. - Nothing exercised the UMD output. Load it against real React, lodash and prop-types globals and assert the exports, since a wrong global name yields a bundle that loads fine and only fails on first use. Also documents why lodash is read as `_`. The webpack build asked for `root["lodash"]`, a global lodash never defines, so the script-tag path was already broken. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Closes #118.
Why
The webpack build emitted one UMD bundle and pointed both
mainandmoduleat it. UMD cannot be tree-shaken, so every consumer paid for the whole library regardless of what they imported. That is the root cause of #118, and it is why #175 and #154 (trimming lodash imports) could never have fixed it on their own.What
vite.config.mtsreplaceswebpack.config.js+webpack.libConfig.jsunpkg/jsdelivr, so existing script-tag users are unaffectedindex.d.ts, copied to.d.mts/.d.ctsso bothexportsconditions resolveexportsmap with per-conditiontypessrcis now published, so the shipped sourcemaps actually resolveTwo silent failures worth knowing about
JSX runtime. The bundler does not inherit
jsxfromtsconfig.json, and defaults to the automatic runtime. That inlined the entirety ofreact/jsx-runtimeinto the bundle and emitted arequire("react")that threw the moment the ESM entry was imported. It would also have broken the declaredreact >=16.8peer, sincereact/jsx-runtimedoes not exist before React 17. Now pinned to the classic runtime explicitly.bundleTypes.vite-plugin-dtsrenamedrollupTypestobundleTypesin v5 and ignores the old key without warning, so declarations stayed unbundled and looked fine.Both produced a build that passed lint, type-check, tests and a filename check on the tarball. Only actually importing the artifact caught them, which is why CI now does that.
Target
ES5 to ES2015. esbuild cannot emit ES5, and
browserslistalready excluded IE11, so nothing supported is lost.Results
import { useXarrow }beforeimport { useXarrow }after@arethetypeswrong/cli: no problems found, green on node10 / node16-CJS / node16-ESM / bundler.CI
Two new steps, both of which would have caught the JSX bug:
@arethetypeswrong/cliRemoved
webpack, webpack-cli, webpack-node-externals, babel-loader, ts-loader, file-loader, the five
@babel/*packages,.babelrc, andts-node.ts-nodewas only ever there to load the webpack config, so #198 (bump ts-node) can be closed rather than merged.Not in this PR
Version stays at 2.0.2. This is consumer-visible and wants a minor bump to 2.1.0, but publishing is blocked until the npm Trusted Publisher is registered on npmjs.com.
🤖 Generated with Claude Code
Summary by CodeRabbit
Build & Packaging
Quality Assurance
Maintenance