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<web_sys::Request> conversion eagerly parses the URL of every incoming request just to precompute the path field, so the parser is always retained:
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).
A size analysis of the final optimized wasm output shows the
urlcrate and itsidna/ICU4X dependency stack dominate the binary of even a minimal worker:#[event(fetch)]workeridna_adapterpinned to 1.0 (no ICU)urlremoved entirely(Methodology:
opt-level = "z",lto = true,codegen-units = 1, wasm-bindgen 0.2.127,wasm-opt -Oper 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
idnasince 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: theFrom<web_sys::Request>conversion eagerly parses the URL of every incoming request just to precompute thepathfield, so the parser is always retained: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:
Request::pathwithoutUrl::parse, making the url stack dead-code-eliminable for workers that never useUrl. Document theidna_adapter = 1.0pin for users who parse URLs but don't need non-ASCII IDNA.url::Urlfrom 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
urlpublic API surface).