Migrating Javascript library to Rust

I have been writing some web apps using Rust and WebAssembly. It is awesome.

While writing something from scratch was not a problem, I am unsure about how to migrate an existing js library in an incremental way. The library has a grunt file for packaging and testing.

I remember reading a blog post about migrating a C codebase to Rust in which the author converted some parts while keeping the others in C, and this was repeated until everything was on rust. I would like to take the same path here, but I am not sure how. Any suggestions?

Does this section of the WASM book help?

I will give it a try. Thanks for the tip.

1 Like

I have tried but not succeeded, yet. Briefly, I migrated one js file to rust, then build it using wasm-pack build --target web and replace the content of the original js file within the project

(function( $ ){
    /// here Point was defined as $.Point = 
}( Project123 ));

by the following:

(function( $ ){
    $.Point = rsjs.point_new;
}( Project123 ));

where rsjs is the compiled rust project that contains point_new. I have tried multiple ways to import/require rsjs without success. I guess because the original project is ECMA5. Any ideas how to solve it? I know this is not strictly a rust question but maybe somebody has a clear roadmap of how to migrate a js project to rust web asm in this incremental way (that allows me to run all tests in each step of the migration).

The blog post may have been one from Federico Quintero of the gnome project. Here's one. https://people.gnome.org/~federico/blog/refactoring-the-length-type.html

There's also a video of a talk he did on the same subject on YouTube, if you search for his name and rust.

If you use wasm-pack, it generates a JavaScript file and a .wasm file. Copy those to your JS project. wasm-pack takes arguments where you can define the type of module generated (Typescript. ES5 module, etc). See wasm-pack build --help for the possible options.

Then include that JavaScript file in your project. How you do that depends on your bundler and what module type you set. This is just regular JavaScript stuff.

The module defines wasm_bindgen, which is a function you pass the path to the .wasm-file to. It returns a Promise that you have to await. After that, wasm_bindgen is an object that contains all the types and global functions you exported from Rust (via #[wasm_bindgen]).

You can declare structs in Rust and return them, which then become JavaScript objects. These objects are just wrappers that call into Rust whenever you call a function on them. Some types are also converted automatically, like strings and numbers.

Thanks for all the suggestions. I finally settled with the following workflow. I created a rust webpack package using this tutorial. This package imports the original library, patches it and re-export it using expose-loader.

The entry js looks like this:

var MyJSLibrary = require('myjslibrary');
MyJSLibrary.rspatched = true;

import(
    /* webpackExports: ["default", "named"] */
    "../pkg/mylibrary-rs.js"
).catch(console.error).then(module => {
  MyJSLibrary.legacyUser = MyJSLibrary.User;
  MyJSLibrary.User = module.User;
});

Here I replace a JS User implementation by rust one.