跪拜 Guibai
← All articles
Frontend · Backend · Developer

Bun 1.4 Absorbs Image Processing, Browser Automation, and Cron Into the Runtime

By 前端之虎陈随易 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Every dependency removed from `package.json` is one less supply-chain surface, one less native-addon build failure, and one less version-conflict headache. Bun 1.4 makes the runtime absorb enough of the ecosystem that a new project’s dependency tree can shrink by a dozen packages before writing a single line of application code.

Summary

Bun 1.4 continues collapsing the JavaScript toolchain into a single binary. New built-in APIs replace `sharp` for image resizing, `Playwright` for browser automation, `node-cron` for scheduled tasks, and `node-pty` for terminal emulation. Configuration parsers for JSON5, JSONL, JSONC, XML, and TOML are now native, and `Bun.serve()` can serve a static directory with automatic ETag and Range handling — no `express.static` needed. The package manager gains `bun pm diff` for inspecting dependency changes before upgrading, nested overrides for surgical version pinning, and an opt-in isolated linker that can make installs up to 7× faster in CI.

Testing gets parallel workers, per-file isolation, sharding with timing-based balancing, and `--changed` to run only tests affected by Git diffs. The bundler now includes the React Compiler, build-time feature flags via `bun:bundle`, in-memory file inputs, and single-file HTML output. Code splitting link time drops from 4.65 seconds to 320 milliseconds on a 20,000-module diamond graph.

Under the hood, Bun 1.4 is the first release after a full Rust rewrite. Official benchmarks show Claude Code’s CPU p99 falling from 24% to 10%, HTTP service memory dropping 13–48%, and Linux startup time halving to 5.1 ms. Security tightens with certificate pinning hooks that execute before any request bytes leave the socket, default `rejectUnauthorized` enforcement, and tar path-traversal protection. Windows ARM64 and FreeBSD gain native builds, while Android remains experimental.

Takeaways
`Bun.Image` decodes, resizes, rotates, and re-encodes JPEG, PNG, WebP, GIF, and BMP without `sharp`; official benchmarks show 1.38× faster 1080p-to-400px scaling.
`Bun.WebView` drives a headless browser with real user-level clicks (`event.isTrusted === true`) and works with system WebKit on macOS or installed Chrome/Edge on Linux and Windows.
`Bun.cron` registers OS-level scheduled tasks (crontab, launchd, Task Scheduler) from a file path or an inline function; the inline form runs inside the event loop without system registration.
`Bun.Terminal` provides a built-in PTY that can drive `bash`, `vim`, or `htop` across Linux, macOS, and Windows, replacing `node-pty`.
`Bun.serve()` now maps a route directly to a static directory, handling `Content-Type`, `ETag`, `Last-Modified`, `304`, and `Range` automatically.
Streaming response backpressure pauses the source when a slow client’s send buffer fills; Bun 1.3 would accumulate unsent data in memory until the process collapsed.
`fetch()` gains request-body compression (`gzip`, `deflate`, `br`, `zstd`), proxy authentication via a `proxy` object, and TLS session reuse that cuts one round-trip on repeat connections.
`bun pm diff` shows file changes, install scripts, and dangerous Node.js imports between two package versions before an upgrade.
Nested overrides pin a transitive dependency only under a specific parent (`"express": { "qs": "6.13.0" }`), and version-qualified overrides (`"lodash@<4.17.21"`) are supported.
`bun test --parallel` distributes files across workers; `--isolate` gives each file a fresh global and module registry; `--shard` splits tests across CI runners; `--timings` balances shards by historical duration.
The bundler includes the React Compiler (`--react-compiler`), build-time dead-code elimination via `bun:bundle` feature flags, and single-file HTML output that works from `file://`.
Code splitting link time for a 20,000-module diamond graph fell from 4.65 s to 320 ms after switching reachability traversal to breadth-first.
The Rust rewrite cut Claude Code’s CPU p99 from 24% to 10%, Linux startup from 10.9 ms to 5.1 ms, and peak Linux memory from 33 MB to 14.6 MB.
`fetch()` certificate pinning via `checkServerIdentity` now runs after the TLS handshake but before any request bytes are sent, and re-executes on every redirect.
Windows ARM64 and FreeBSD (x86_64, aarch64) get native builds; Android aarch64/x64 remain experimental; minimum Linux glibc drops to 2.17.
Breaking changes: `writeHeader()` is now `writeHead()`, `.env` is no longer auto-loaded when Bun runs as `node`, and compiled executables stop reading `tsconfig.json` and `package.json` from the run directory.
Conclusions

Bun’s strategy is not to beat every tool on performance but to make the tool disappear — when image processing, cron, and a PTY ship in the binary, the install step and the native-addon build step both vanish.

The backpressure fix is the kind of unglamorous change that determines whether a runtime survives production: Bun 1.3 would silently accumulate memory until OOM, and 1.4 turns that into a proper pause.

Certificate pinning that executes before the first request byte leaves the socket is a stronger primitive than most Node.js TLS setups offer out of the box; it closes the window where a compromised CA could intercept a payload.

Making the isolated linker opt-in rather than default is a pragmatic choice — it avoids breaking every existing `node_modules` layout on upgrade, but it also means the 7× install speedup only reaches teams that read the changelog.

The breadth-first code-splitting rewrite is a reminder that algorithmic complexity still matters in bundlers: a 14× speedup came from changing the traversal order, not from adding cache layers or parallelism.

Bun’s growing list of built-in parsers (JSON5, JSONL, JSONC, XML, TOML) signals that the runtime sees configuration and log processing as core infrastructure, not as userland concerns to be left to npm.

The `--changed` test flag tracing imports backward from Git diffs is a more accurate “affected tests” strategy than file-name matching, but it still has a blind spot for dynamic imports and runtime dependency injection.

Concepts & terms
PTY (Pseudo-Terminal)
A pair of virtual character devices that emulate a physical terminal. A process like `bash` or `vim` writes to the slave side; the controlling program reads from the master side and can send input back, enabling interactive command-line tools to run programmatically.
TLS session reuse
A mechanism where a client caches the cryptographic parameters from a previous TLS handshake and resumes them on a subsequent connection to the same server, skipping certificate exchange and key negotiation. This reduces connection setup from two round-trips to one.
Backpressure (streaming)
A flow-control mechanism where a writable stream signals to its source that it cannot accept more data until the consumer catches up. Without backpressure, a fast producer will buffer data indefinitely in memory, eventually causing an out-of-memory crash.
Certificate pinning
A security practice where an application trusts only a specific certificate or public key fingerprint for a given host, rather than trusting any certificate issued by a CA in the system trust store. It protects against CA compromise but breaks when certificates rotate.
Isolated linker (Bun)
A package installation mode where dependencies are extracted once to a global cache and symlinked into each project’s `node_modules/.bun/` directory, rather than copied or hoisted. It avoids duplicate disk usage across projects and speeds up installs when the cache is warm.
Barrel import optimization
A bundler technique that analyzes re-export files (barrel modules) and eliminates imports of symbols that are never used, reducing the final bundle size. It requires the package to declare `sideEffects: false` so the bundler knows unused exports are safe to drop.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗