Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

What's wrong with TypeScript? Last time I checked all WASM stuff was slower and much heavier than TS/JS.


Did anyone say that something was wrong with typescript? It’s my preferred language these days, in non-tech enterprise you’ll basically have to use it and since it’s good enough for everything, it’s easy to have small teams that can all work together in one language. This means the frontend developer gets to go on vacation (or call in sick) without bringing a laptop. It also means you can easily share in-house libraries and ask each other for ideas/troubleshooting more easily. And so on, there are obviously downsides as well but over all it’s a joy to work with.

That doesn’t mean I don’t want Rust “people” to work on frontend stuff for Rust. Typescript is good, I like using it, but I’d like to have options. If not for anything else, then for Typescript to take the best parts of Rust and use them.

I don’t personally think we’re going to see a massive shift away from a JavaScript world until someone like Microsoft starts driving the change. The amount of resources they pour into Typescript means it’s not likely to leave my world any time soon. But if it did, and something better came along then I’d be happy, not sad.


Slower - not really now Rust client web frameworks have improved. Don't have refs handy, but Leptos, Dioxus etc are on a par with Solid.

Larger bundle sizes - yes that's still true.

And not all GUIs are web GUIs, so WASM isn't the whole story.


Yeah played with some Leptos wasm and i believe something simple like their book tutorial was like 335kb or so. Not that shocking and for me personally totally acceptable. I do wish browsers would ship with their std lib for wasm. So wasm is can become more competitive on bundle sizes with Javascript which has its std lib shipped with browsers.


Yeah also note that 335kb of wasm isn't as bad as 335kb of javascript.

Its true that large javascript bundles are bad because big files take longer to download. But the arguably larger problem is that parsing javascript is really slow. This isn't as big an issue with wasm - the browser can parse wasm many times faster than it parses javascript. If I recall correctly, wasm parsing speed is about on par with the speed of parsing pngs.

So having 335kb of wasm is similar to having a 335kb image on your landing page. Its not ideal, but its not a showstopper.


My understanding that WASM has a heavier load time, however actual benchmarks after the initial load are more impressive.


It’s not WASMs fault. Rust produces large binaries for whatever reason and people like to write their WASM in Rust. I’ve ported Rust to equivalent C and it was 25% of the size and similarly for loading times.


it is rather simple, JS tooling cares A LOT about the size of their dependency tree. Statically compiled languages do not (except if they focus on embedded programming). Having a binary be 2mb vs 30mb is not a big deal for a desktop application

Just for reference I was testing this the other day and compiled some simple C++ to WASM and adding:

std::cout << "some text";

to the code increased the binary size by like 5mb. Turns out std:cout pulls ALL currency-formating, date-formating and i18n code in the c++ standard library into your binary

ansi C printf does not meaningfully increase your WASM binary size

If you want your code to be able to be loaded on-the-fly and fast you need bundling tools, just like JS does. Bundling is a really hard problem, game devs struggle a lot with it as well (although their problem is usually bundling assets, not code itself)


Exactly, WASM was designed to be very very lightweight... you can put a lot of logic into a very small amount of WASM, but you need a good compiler to do that, or write WASM by hand to really feel the benefit. If you just compile Go to WASM, with its GC, runtime and stdlib included in the binary, yeah it's going to be pretty heavy... Rust doesn't have a runtime but as you said, for some reason, produces relatively large binaries (not the case only in WASM by the way). Probably, the best ways to create small WASM binaries is to compile from C or from a WASM-native language like AssemblySCript (https://www.assemblyscript.org).


Rust doesn't have to output more code than a C compiler. But it tends to because most rust programs are stuffed full of bounds checks. And bounds checks aren't small. As well as the conditional itself, every bounds check also includes:

- A custom panic message (so you know which line of code crashed)

- Some monomorphized formatting code to output that message

- The infrastructure to generate a stack trace after a panic

- Logic to free all the allocated objects all the way up the stack

If you compile this 1 line function:

    pub fn read_arr(arr: &[usize], i: usize) -> usize {
        arr[i] // (equivalent to 'return arr[i];')
    }
... You produce 20 hairy lines of assembler: https://rust.godbolt.org/z/dhz34KEvj

In contrast, the equivalent C function is this rust code:

    pub fn read_arr_unchecked(arr: &[usize], i: usize) -> usize {
        unsafe { *arr.get_unchecked(i) }
    }
And predictably, the result is this gem - identical to what the C compiler outputs:

    example::read_arr_unchecked:
        mov     rax, qword ptr [rdi + 8*rdx]
        ret
But nobody writes rust code like that (for good reason). You can get a lot of the way there by leaning heavily using rust's iterator types and such. But its really difficult to learn what patterns will make the rust compiler lose its mind. There's no feedback on this at compile time, at all.


I'd appreciate any more tips or resources you might have about reducing Rust code bloat. I want my library [1] to be acceptable to the most strident anti-bloat curmudgeons, so they'll make their UIs accessible.

[1]: https://github.com/AccessKit/accesskit


I don’t know many good resources to learn this stuff unfortunately.

The things I reach for in practice are godbolt and cargo asm[1] - which can show me the actual generated assembler for functions in my codebase. And twiggy[2], which can tell you which functions are the biggest in your compiled binary and point out where monomorphization is expensive.

When I’m developing, I regularly run a script which compiles my code to wasm and tells me how the wasm file size has changed since the last time I compiled it.

Some tips:

Try to avoid array lookups with an index when you can. When looping, use slice iterators and when making custom iterators, wrap the slice iterator rather than storing a usize index yourself.

Be careful of monomorphization. If you’re optimising for size, it can be better to take a dyn Trait rather than making a function generic.

And play around with your wasm API surface area. It takes a lot more code to pass complex objects & strings back and forth to javascript than other types.

But otherwise, good luck! Love the project.

[1] https://github.com/gnzlbg/cargo-asm

[2] https://github.com/rustwasm/twiggy


Great project - this is important! Love your clear motivation statement at the top. I do wish there were some code/data examples within the README, but clearly that's not holding people back from using it.


Rust can be the same size if you put the same code into the binary, sometimes even smaller.

The problem is that it's real easy to just add a bunch of crates to an application, similar to the nodejs/Python approach.

Most people slso don't seem to turn off many parts of the standard library they don't, even for platforms like WASM. Maybe it's useful to have a stack unrolling panic handler during debug but in release you can just abort and save up to megabytes of space.

There's also a lot to be gained by tweaking the compiler optimisers. By default the optimizer is multithreaded, which makes compiles quite a lot faster, but reduce that to a single thread and suddenly a lot of optimizations can happen that wouldn't happen by default.

I wouldn't write code like described here in C, but I imagine Go and C# are better choices here. Maybe even that Java library the name of which I can never remember, or that Kotlin project that compiles Kotlin to Javascript with super easy interaction between frontend and backend.

I love Rust but if you're going to pick a systems programming language for your frontend, just make desktop supplications. Web is a nice fallback but if it's your primary target, there are so many better options out there.


And since everyone likes to talk about how great and magic the WASM sandbox happens to be, who cares if C is being used.


When you ship javascript, the Browser already has a lot of the bigger libraries built in. When you ship rust/wasm, you need to ship all of the basic types like Strings, Vecs, + a lot of the std


> What's wrong with TypeScript.

I love typescript, but, from my PoV, what I miss in typescript is:

- An actually sound type system: This is a big one. Can you figure out why this[0] is unsound?

- I regularly have to do `as ` assertions, and I know it's not because I'm bad at typescript because it's often the recommended solution from cream-of-the-crop tS libraries for certain issues.

- Traits

- new-types

- Algebraic data types: Option and Result. 'nuff said.

- Pattern matching: :cheff's kiss:

[0]

    export function useSetter<T, K extends keyof T>(
      state: T,
      setState: (n: T) => void,
      key: K
    ) {
      return useCallback(
        (val: T[K]) => setState({ ...state, [key]: val }),
        [key, setState, state]
      );
    }


Where did you check that?

If you're talking about Wasm with Emscripten, yes there's a cost of loading the runtime because Emscripten comes bundled with a lot of stuff.

I'm skeptical that just wasm itself was slower or heavier.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: