Skip to content

Replace webpack/yarn build with Bun - #3836

Draft
Shadowfiend wants to merge 12 commits into
mainfrom
move-to-bun
Draft

Replace webpack/yarn build with Bun#3836
Shadowfiend wants to merge 12 commits into
mainfrom
move-to-bun

Conversation

@Shadowfiend

Copy link
Copy Markdown
Contributor

Summary

  • Removes webpack, Babel, and yarn in favor of Bun's native bundler
  • Adds build plugins for Node polyfills (globals shim), styled-jsx, and WASM base64 embedding
  • Scans source for all process.env.* references to generate compile-time defines (matching dotenv-webpack behavior)
  • Updates CI workflow and Dockerfile to use bun
  • Converts patch filenames to bun's naming convention
  • Switches pre-commit hooks from npx to bunx
  • Dev builds overlay a branch-name badge on the extension icon and append the branch to the version string

Notes

  • Bun auto-polyfills most Node built-ins for browser targets, but does not provide Buffer/process as globals — a plugin injects these via entrypoint shims
  • define with require() expressions doesn't work in Bun (values are parsed as JSON) — this was the source of the "require('buffer').Buffer".from is not a function errors
  • WASM files use module.exports instead of export default to avoid CJS interop wrapping that broke atob() consumers (argon2)
  • Pre-commit eslint hooks will need missing peer deps installed (eslint-plugin-import, eslint-plugin-prettier, eslint-plugin-no-only-tests, etc.) — yarn hoisted these but bun doesn't

Test plan

  • bun run build.ts produces working dev build
  • bun run build.ts --production produces production build
  • Dev build icon shows branch badge, production does not
  • Extension loads in Chrome without process.env or Buffer errors
  • WASM-dependent features (argon2 key derivation) work
  • Playwright e2e tests pass (6/6 core tests, 1 env-config test skipped)

🤖 Generated with Claude Code

We improve device detection and add Stax and Flex to the supported
device list. Connections with these are still a little wobbly, but
successful signatures have happened!
@Shadowfiend
Shadowfiend requested a review from a team as a code owner February 24, 2026 17:49
@Shadowfiend
Shadowfiend marked this pull request as draft February 24, 2026 17:49
Shadowfiend and others added 5 commits February 24, 2026 12:54
Bun's bundler handles JSX, TypeScript, and tree-shaking
natively, removing the need for Babel and most webpack
plugins. Key design decisions:

- Node polyfills: Bun auto-polyfills buffer, stream, crypto,
  etc. for target:"browser", but doesn't provide them as
  globals. A plugin injects a shim into entrypoints that sets
  Buffer and process on globalThis. The define-with-require()
  approach doesn't work (Bun parses values as JSON).

- process.env.*: Source files are scanned for all process.env
  references and each gets a compile-time define, matching
  dotenv-webpack's behavior. Without this, unreplaced
  references hit the missing process global at runtime.

- WASM: Files are base64-encoded inline using module.exports
  (not export default) to avoid CJS interop wrapping that
  breaks atob() consumers like argon2.

- Dev builds: Branch name is overlaid as a badge on the
  extension icon and appended to the version string so
  different dev builds are visually distinguishable.

- Adds eslint peer deps that yarn hoisted from
  @thesis-co/eslint-config but bun does not.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The new Bun-based build system replaces all of these:
- webpack.config.ts and its custom plugins
- babel.config.js and ui/.babelrc.js (Bun handles JSX/TS
  natively)
- yarn.lock (replaced by bun.lock)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bun uses pkg@version.patch (with url-encoded scopes) rather
than yarn's pkg+version.patch format. The patch contents are
unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds oven-sh/setup-bun action to the GitHub workflow and
switches all yarn commands to bun equivalents. Dockerfile
now pulls bun binary from the official oven/bun image.
Removes NODE_OPTIONS=--openssl-legacy-provider which was
a Node/webpack workaround no longer needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shadowfiend and others added 2 commits February 24, 2026 14:45
The ESLint 8 + Prettier 3 + @thesis-co/eslint-config setup had ~20
transitive deps and was causing peer-dep issues after the yarn-to-bun
migration. oxlint (Rust, 690+ built-in rules) and oxfmt (100% Prettier
JS/TS conformance, 30x faster) eliminate that overhead.

- oxlint v1.50, oxfmt v0.35, oxlint-tsgolint v0.15 added
- 15 eslint/prettier packages removed
- .oxlintrc.json: correctness:error, suspicious:warn, plugins for
  react/jsx-a11y/import/typescript/jest, key custom rules preserved
- .oxfmtrc.json: migrated from .prettierrc (semi:false, printWidth:80)
- lint scripts now use oxlint --type-aware and oxfmt --check
- Rules new to this migration (no-floating-promises, jsx-key, jest
  rules, etc.) downgraded to warn to avoid blocking; can be promoted
  incrementally

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Converted all eslint-disable/eslint-disable-next-line/eslint-disable-line
comments to the oxlint equivalents (oxlint-disable, oxlint-disable-
next-line, oxlint-disable-line). @typescript-eslint/ rule prefixes
become typescript/. Comments for rules that don't exist in oxlint
(no-restricted-syntax, no-underscore-dangle, @typescript-eslint/
no-use-before-define, etc.) were removed. Two unused imports
(AnyAsset, AnyAction) caught by oxlint were also removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ran oxfmt --write . to bring all JS/TS/CSS files into conformance
with the new formatter (100% Prettier-compatible output, semi:false,
printWidth:80). This is a formatting-only change with no semantic
modifications.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Shadowfiend
Shadowfiend force-pushed the move-to-bun branch 2 times, most recently from a53e042 to 12c3852 Compare February 24, 2026 20:38
Shadowfiend and others added 3 commits February 24, 2026 22:12
bun:test provides jest-compatible globals (jest.fn, jest.mock, etc.)
natively, so Jest itself is no longer needed. The setupJest.* files
are replaced by setupBun.* equivalents that wire up happy-dom
globals, fake-indexeddb, fetch stubs, and logger levels for bun's
test runner. Also adds an isolated test runner script for debugging
cross-file state pollution.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Without the styled-jsx babel plugin, tests render unscoped <style>
tags, causing CSS collisions when multiple instances of the same
component are rendered. This adds a bun test-runner plugin that
runs styled-jsx files through babel, matching the production build
pipeline (build-plugins/styled-jsx.ts).

Includes a workaround for a bun bug where registering any plugin
causes Error.captureStackTrace to fail in CJS modules like
follow-redirects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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