cloudflare / cloudflare/workers-rs
`url` crate accounts for ~⅔ of a minimal worker binary — remove for next major
- Dominant language
- Rust
- Stars
- 3.7k
- Forks
- 429
- Avg merge
- 20h 28m
- Merged PRs (30d)
- 7
Description
A size analysis of the final optimized wasm output shows the `url` crate and its `idna`/ICU4X dependency stack dominate the binary of even a minimal worker:
| Hello-world `#[event(fetch)]` worker | raw wasm | gzip |
|---|---|---|
| workers-rs today | 231.9 KB | 98.9 KB |
| with `idna_adapter` pinned to 1.0 (no ICU) | 125.0 KB | 53.5 KB |
| with `url` removed entirely | 76.5 KB | 32.5 KB |
(Methodology: `opt-level = "z"`, `lto = true`, `codegen-units = 1`, wasm-bindgen 0.2.127, `wasm-opt -O` per worker-build defaults, gzip -9. Router-based worker shows the same ~155 KB delta: 256.8 KB → 102.2 KB.)
That's ~107 KB of ICU4X Unicode tables (pulled in via `idna` since url 2.5) plus ~48 KB of parser/punycode code — to reimplement in wasm a WHATWG URL parser the runtime already provides natively.
Worse, every worker pays this even if it never names a `Url`: the `From` conversion eagerly parses the URL of every incoming request just to precompute the `path` field, so the parser is always retained:
```rs
path: Url::parse(&req.url())
.map(|u| u.path().into())
```
`req.url()` is produced by the runtime's own URL parser, so this is a redundant reparse — the path can be extracted with simple string slicing (verified: doing so strips all 95 url/idna/icu symbols from the binary).
Proposal:
* **Minor (now):** compute `Request::path` without `Url::parse`, making the url stack dead-code-eliminable for workers that never use `Url`. Document the `idna_adapter = 1.0` pin for users who parse URLs but don't need non-ASCII IDNA.
* **Major (next):** remove `url::Url` from the public API (`Request::url`, `Fetch::Url`, `RequestInit`, router) in favor of a platform-backed URL type wrapping the runtime's native parser, eliminating the dependency entirely.
Related: #380, #1033 (re-exports that further entrench the `url` public API surface).
Contributor guide
Research direction
Start by tracing the From conversion and the Request::path, Request::url, Fetch::Url, RequestInit, and router entry points mentioned in the issue. Review related issues #380 and #1033 before deciding whether the scope is the minor path change or the next-major public API removal. Done means the agreed scope is implemented and the stated wasm size and URL-parsing behavior are verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- api, performance
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100