Dependency solver for Elm, made in WebAssembly

Overview

Dependency solver for Elm, made in WebAssembly

This repo holds a dependency solver for the elm ecosystem compiled to a WebAssembly module. The wasm module is published on npm, so you can easily use it in your JS projects with:

let wasm = require("elm-solve-deps-wasm");
wasm.init();
let use_test = false; // solve for normal dependencies, not test dependencies
let additional_constraints = {}; // no additional package needed
let solution = wasm.solve_deps(
  elm_json_config, // the elm.json that we have to solve
  use_test,
  additional_constraints,
  fetchElmJson, // user defined (cf example/dependency-provider-offline.js)
  listAvailableVersions // user defined (cf example/dependency-provider-offline.js)
);

Shrinking the .wasm size

Shrinking the generated WebAssembly package to the smallest size possible will benefit everyone using it as a dependency, so here is an attempt at doing it. Most of the info required to shrink the wasm size is available in the rustwasm reference book. Here is a summary of the different techniques we use here.

  • Compile with link time optimization (lto). In theory, this gives LLVM more opportunities to inline and prune functions.
  • Use opt-level = "z" to optimize for size instead of for speed.
  • Use the wee_alloc allocator which is optimized for size instead of the default allocator, optimized for speed.
  • Replace panic logic by abort with panic = "abort" and with wasm-snip --snip-rust-panicking-code.
  • Use wasm-opt -Oz -o output.wasm input.wasm on the output of wasm-pack. Remark that it's better to use the latest one from the binaryen project instead of the one shipped with wasm-pack automatically, so we add wasm-opt = false to wasm-pack config.
  • Profile the generated wasm with twiggy to find optimization opportunities. This requires adding debug = true to the release compilation profile, and -g to wasm-opt.

With the above tricks we start with a .wasm file weighing 470kb and end with a 251kb file! Most of it comes from the wasm-opt tool. Here is the detail of what each step brings:

  • Initial --release size: 479kb.
  • When using wee_alloc: 470kb.
  • When also adding wasm-opt -Oz: 366kb.
  • When also adding lto = true and opt-level = "z": 276kb.
  • When also adding wasm-snip --snip-rust-panicking-code: 271kb.
  • When adding debug = true and using twiggy, I found out that there was a non-negligeable part of the wasm binary dedicated to formatting f64 numbers. But in fact, this never happens in our use case, so we can snipe it!
  • When also adding wasm-snip -p "core::fmt::float::<impl core::fmt::Display for f64>::fmt::.*": 251kb.

So in summary, the steps to get the most shrinked wasm module are the following:

wasm-pack build --target nodejs
wasm-snip --snip-rust-panicking-code -p "core::fmt::float::<impl core::fmt::Display for f64>::fmt::.*" -o snipped.wasm pkg/elm_solve_deps_wasm_bg.wasm
wasm-opt -Oz -o output.wasm snipped.wasm
cp output.wasm pkg/elm_solve_deps_wasm_bg.wasm

All that being said, if you don't want to bother installing wasm-snip and the latest wasm-opt, you can simply call:

wasm-pack build --profiling --target nodejs

and let the provided wasm-opt do its job, with a generated .wasm of size 276kb.

You might also like...
Low level tooling for WebAssembly in JavaScript using wasm-tools

js-wasm-tools js-wasm-tools compiles some of the API of wasm-tools to JavaScript and WebAssembly via wasm-bindgen. This offers low level tooling for W

Rust bindings for Supabase JavaScript library via WebAssembly.

supabase-js-rs Rust bindings for Supabase JavaScript library via WebAssembly. Usage Add supabase-js-rs to Cargo.toml supabase-js-rs = { version = "0.1

🚀 An OSS project to develop and run serverless applications on WebAssembly

Wasm Workers Server Wasm Workers Server (wws) is a framework to develop and run serverless applications server in WebAssembly. These applications are

An attempt to build full-featured WebAssembly-based monolith charts

Graphima Graphima (Greek: γράφημα) is an attempt to build full-featured WebAssembly-based monolith charts. See "Can I Use" WebAssembly for browser sup

plugy empowers you to construct agnostic dynamic plugin systems using Rust and WebAssembly.

plugy plugy is a plugin system designed to enable the seamless integration of Rust-based plugins into your application. It provides a runtime environm

Let's pretend that life-before-main exists for Rust targeting WebAssembly

Let's pretend that life-before-main exists for Rust targeting WebAssembly. Installation Add a dependency on wasm-init. This crate intentionally provid

Code for my workshop
Code for my workshop "Production-ready WebAssembly with Rust" presented at RustLab 2023 in Florence

Workshop: Production-ready WebAssembly with Rust A workshop on Rust for WebAssembly by Alberto Schiabel (@jkomyno). 🤓 This workshop was first present

A simple programming language made for scripting inspired on rust and javascript.

FnXY Programming Language Quick move: CONTRIBUTING | LICENSE What? FnXY is a simple programming language made for scripting inspired on rust and javas

Just a little game I made in a day to try out the WASM-4 fantasy console.

Dodgeball This is just a little game I made in a day to try out the WASM-4 fantasy console. Play it here. The palette is SODA-CAP by Cappuchi. License

Releases(v1.0.2)
Owner
Matthieu Pizenberg
Raclette lover -- Retired Pokemon master -- Robots maker -- Tennis player -- Functional programming newbie -- Post-doc in computer vision
Matthieu Pizenberg
WebAssembly implementation from scratch in Safe Rust with zero dependencies

wain wain is a WebAssembly INterpreter written in Rust from scratch with zero dependencies. An implementation of WebAssembly. Features: No unsafe code

Linda_pp 328 Jan 2, 2023
A notebook app integrated with todo lists utility. Developed with Rust, WebAssembly, Yew and Trunk.

Flow.er A notebook app integrated with todo-list utility. Project flow.er is a Rust WASM app running in browser. Taking advantage of Yew and Trunk, it

null 45 Dec 31, 2022
NPM package distributing biscuit in WebAssembly for web components

Biscuit playground This is an example application for Biscuit tokens, where you can manipulate tokens and their verification in your browser. build wi

null 0 Dec 30, 2021
witgen is a library to generate .wit files for WebAssembly in Rust

witgen witgen is a library to help you generate wit definitions in a wit file for WebAssembly. Using this lib in addition to wit-bindgen will help you

Coenen Benjamin 28 Nov 9, 2022
Build frontend browser apps with Rust + WebAssembly. Supports server side rendering.

Percy Build frontend browser apps with Rust + WebAssembly. Supports server side rendering. The Percy Book This README gives a light introduction to Pe

Chinedu Francis Nwafili 2.1k Jan 1, 2023
`wasm-snip` replaces a WebAssembly function's body with an `unreachable`

wasm-snip wasm-snip replaces a Wasm function's body with an unreachable instruction. API Docs | Contributing | Chat Built with ?? ?? by The Rust and W

Rust and WebAssembly 177 Dec 28, 2022
WebAssembly (Wasm) interpreter.

Continuous Integration Test Coverage Documentation Crates.io wasmi- WebAssembly (Wasm) Interpreter wasmi was conceived as a component of parity-ethere

Parity Technologies 1k Jan 4, 2023
A simple code for checking crate 'prost' on WebAssembly (🦀 + 🕸️ = 💖)

rust-wasm-prost This repository is a simple code for checking crate 'prost' on WebAssembly ( ?? + ??️ = ?? ). What is prost? prost is a Protocol Buffe

Chris Ohk 6 Apr 5, 2022
Vite + Webassembly starter project

Vite + Typescript+ Webassembly A starter project for you to create a blazingly fast web application Before getting started You need to get these prere

Saugi 9 Aug 18, 2022
Mod_wasm - an extension module for the Apache HTTP Server (httpd) that enables the usage of WebAssembly (Wasm).

mod_wasm is an extension module for the Apache HTTP Server (httpd) that enables the usage of WebAssembly (Wasm). This module will allow to execute certain tasks in the backend in a very efficient and secure way.

VMware  Labs 67 Dec 21, 2022