cloudflare / cloudflare/workers-rs

`url` crate accounts for ~⅔ of a minimal worker binary — remove for next major

Open
#1,044 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.