VOOZH about

URL: https://thenewstack.io/introduction-to-moonbit-a-new-language-toolchain-for-wasm/

⇱ Introduction to MoonBit, a New Language Toolchain for Wasm - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2024-07-13 06:00:00
Introduction to MoonBit, a New Language Toolchain for Wasm
tutorial,
Programming Languages / WebAssembly

Introduction to MoonBit, a New Language Toolchain for Wasm

We check out MoonBit, a modern language plus workflow designed to create efficient WebAssembly projects (it can also target JavaScript).
Jul 13th, 2024 6:00am by David Eastman
👁 Featued image for: Introduction to MoonBit, a New Language Toolchain for Wasm
Photo by John Ruddock on Unsplash.
WebAssembly (Wasm) combines the efficiency inherent in low-level code programming with the ease of component transportability typically found in Linux containers. In some respects, it competes with Docker. However, intensive work within a browser heavily suggests a future in AI. As it happens, other languages don’t necessarily compile efficiently to Wasm, which somewhat undoes the advantage of having a program that can run in the browser. This is where MoonBit comes in, although it can also target other backends, such as JavaScript. By targeting Wasm, MoonBit gets a free ride on many smaller specialist devices. MoonBit is a Chinese-led project: this accounts for some of the aesthetics, as well as the occasional Chinese language comments in the code. If applicable, you should check your own organization’s governance systems before playing with it. As MoonBit’s creator Hongbo Zhang says, “The reason we decided to have a fault-tolerant type system is because we want to have the IDE share the same code base with a compiler.” This allows the MoonBit language you see within Visual Studio Code to be more of a first-class citizen. This is why the type system is important — the stronger it is, the more valid work the IDE can do before the compiler takes over.

How to Run Wasm via MoonBit

But what do we mean by “running Wasm”? This is important because your OS doesn’t treat it as a free-running application sitting in your file system quite yet. Before we look closer at MoonBit, let’s make sure we understand how we run Wasm. In most cases, we need a JavaScript framework to load and hold it. To use WebAssembly in JavaScript, you first need to pull your module into memory before compilation/instantiation:
WebAssembly.instantiateStreaming(fetch("simple.wasm"), importObject).then( 
 (results) => { 
 // Do something with the results! 
 }, 
);
Compare with this example within the MoonBit Sudoku gallery code:
WebAssembly.instantiateStreaming(
 fetch("target/wasm/release/build/main/main.wasm"), 
 importObject 
 ).then((obj) => { 
 obj.instance.exports._start(); 
 assign = obj.instance.exports["sudoku/main::ij_assign"] 
 initValues = obj.instance.exports["sudoku/main::initValues"] 
 readValues = obj.instance.exports["sudoku/main::ij_read"] 
 solve = obj.instance.exports["sudoku/main::solveValues"] 
 });
So we have a few things to get our head around here. The WebAssemby.instantiateStreaming method waits for a Response object (as a promise) for the Wasm file to load. The obj instance member is then accessed, and the contained exported functions are invoked. The exports clearly describe a module/method to call within the Wasm code. OK, so this gives us a feel for what we need to do via MoonBit; prepare a Wasm file with the necessary exported functions. While we can play with the MoonBit language freely in this online visual code site, in this post I look at constructing the Wasm itself.

More About MoonBit and its CLI

Here are a few explanations:
  • Moon is the build system for the MoonBit language.
  • You can build third-party packages with mooncakes.io, so it is a putative package management system.
  • As I’ve mentioned, there is a Visual Studio code plug-in for MoonBit.
  • The term module is synonymous with a project.
  • To create the exports we saw evidence of, we need the Foreign Function Interface, which we’ll check out at the end of this post.
With that, let’s dig in. We could start with Visual Studio code and install the MoonBit Language Extension. As usual, I’m doing this on my trusty old 2015 Macbook, and it worked just fine. 👁 Image
But we’ll focus on the CLI tools to manage projects. That is because I want to cement in my mind the connection between Wasm code and exposing it in the browser. Opening Warp, I downloaded the CLI tools:
> curl -fsSL https://cli.moonbitlang.com/install/unix.sh | bash
👁 Image
I then created a nice default ‘hello’ module with the moon new command: 👁 Image
The project’s setup on disk shows the relationship between the library and the main package: 👁 Image
The JSON packaging manifest provides cues for the builder for each package. The mod file describes the module as a whole. The first line declares that this module is called “eastmad/hello”. The hello.mbt file contains our familiar language introduction:
pub fn hello() -> String { 
 "Hello, world!" 
}
This follows in a similar form to the modern language idiom for a method or function — we saw it in Gleam for example. This leaves the main.mbt code in the main package with the responsibility of posting the string to the console:
fn main { 
 println(@lib.hello()) 
}
That @lib.hello() is clearly an internal call to the lib package that was resolved within the package description. Running this through the CLI is simple enough: 👁 Image
Wonderful. But I’d like to know what that produced. There is a whole new target directory, so let’s take a look at that: 👁 Image
(You can see references to wasm-gc, which is the garbage-collected version of Wasm. All this means, essentially, is who and how responsibility for “cleaning up after itself” works out.) So we got the promised .wasm file — it is 285 bytes long bit of binary, with the greeting words visible, as well as the token “_start”, referenced in the example javascript call at the beginning — as well as other supporting objects. I don’t see evidence of any “exports” like in the JavaScript framework at the top yet; all we did was print to the console internally.

Interacting With the Hosting Runtime

To interact with the hosting runtime when embedded inside the browser, MoonBit refers to Foreign Function Interface (FFI). Let’s finish off our introduction by having a quick look at this. To declare a foreign function within MoonBit, you can do this:
fn cos(d : Double) -> Double = "Math" "cos"
The actual function itself (the body) has been replaced with the putative module name and function name. You’ll see this reconstructed below when we call it from JavaScript. You can then describe the relationship in the modules moon.pkg.json file:
{
 "link": {
 "wasm-gc": {
 "exports": [
 "add",
 "fib:test"
 ]
 },
 "js": {
 "exports": [
 "add",
 "fib:test"
 ],
 "format": "esm"
 }
 }
}
In this example the functions add and fib are exported, and the function fib will be exported with the name of test. Finally, for our maths example, the JavaScript calling framework would look something like this:
WebAssembly.instantiateStreaming(fetch("xxx.wasm"), { 
 Math: { 
 cos: (d) => Math.cos(d), 
 }, 
});
And this brings us more or less full circle. Most of these elements are visible in the Sudoku example. While MoonBit is nearly production-ready (check the status here), it already describes a modern language as well as a workflow to create a Wasm project. I’m expecting small LLMs will get packed efficiently into Wasm format in the near future.
TRENDING STORIES
David has been a London-based professional software developer with Oracle Corp. and British Telecom, and a consultant helping teams work in a more agile fashion. He wrote a book on UI design and has been writing technical articles ever since....
Read more from David Eastman
SHARE THIS STORY
TRENDING STORIES
TNS owner Insight Partners is an investor in: Wonderful, Docker.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.