Julia in the Browser
There is a strong push to move everything to the web. There are many reasons for that: You don't need to install anything, there are powerful web frameworks and people want to show the results of their research online - as visual and interactive as possible. Especially the last part is important for Julia - a new scientific programming Language!
Julia can't fully run in the browser right now, but this article explains the different approaches and shows how close we are. This article is not only aimed at developers wanting to work on this, but also for interested users that want to learn about possible future directions.
1.1. WebIO + JSExpr
JSExpr is the only option that works of today - but it's also the most restricted approach. It only offers execution of very simple Julia functions defined with the
Advantages & Disadvantages:
+ works today
- only works for a small subset of Julia
To compile already defined / more complex Julia functions, one needs more sophisticated approaches! Enter the world of compiling Julia to WebAssembly (Wasm) - the new assembly language running in the browser!
All in with Wasm
All in with Wasm
Completely compile the Julia compiler to Wasm. This includes all of LLVM, the JIT and Julia's runtime. This way, everything will "just work™". A simple strategy, but needs lots of work in practise. There is some ongoing work to add wasm32-unknown-unknown and wasm32-unknown-emscripten targets to BinaryBuilder, which may make it easier to port libraries (including LLVM) to Wasm.
+ lets any Julia program run in the browser
+ performance should be good
- will likely produce a pretty big WebAssembly binary
- all Julia dependencies need to be compiled to WebAssembly, which is quite a lot of work
Instructions on how to compile Julia to Wasm are presented at the end of the article. In fact, it's directly set up in the articles runtime, and the resulting docker container can be downloaded here (this URL can be looked up for any Nextjournal article in the runner menu to the right).
Half & Half
Half & Half
Compile Julia LLVM IR (Intermediate Representation) to Wasm via emscripten, seperately compile the Julia runtime to Wasm, and then link them together to enable calling into Julia's C runtime! A working prototype for this exists in ExportWebassembly.jl.
+ no need to compile everything to WebAssembly
+ clear separation between WebAssembly backend + Julia backend
+ will work nicely with WebIO to only compile selected callbacks
- cannot JIT code anymore, so code needs to be fully static and ahead of time compilable
1.4. Pure Julia
+ relatively simple with pure Julia tools & no dependencies
+ could yield decent performance for most cases
+ flexible on the compiler side, since one has full control of emitted code
- can't work naturally with C calls (only via emitting different calls)
- more prone to compiler bugs + wrong results
- likely less optimized WebAssembly. Julia's IR is not very optimized since LLVM usually does the difficult optimizations for Julia, so removing LLVM from the equation will also remove lots of optimizations.
2. Compiling Julia to Wasm
2.1. Start a Julia Webserver
To run the generated Wasm in this article we need to start a webserver. Bash can't actually reach the outside of a Nextjournal container, so we need to run the webserver in a Julia code cell! We also need to start it before compiling, because we need to get the proxy URL, to compile the wasm with a source map.
2.2. Setup & Compilation
For now we just partially build Julia with
emcc to Wasm, to get a REPL running. Downloading and compiling Julia is done here and frozen in a container, so that we never need to repeat that step. From here on, we can start compiling Julia's C dependencies to Wasm:
cd julia make clean make -C deps/ clean-utf8proc make -C deps/ install-utf8proc touch src/julia_flisp.boot touch src/julia_flisp.boot.inc make -C src
Display the html we generate & host (will show 404 when article is not in edit mode):
HTML(""" <iframe src=$(repr(url)) style="width:100%;height=800px" frameborder="0"> </iframe> """)
At this point, the WebAssembly code was started in the browser, but it failed. The failure is likely caused by using the wrong femto lisp version, since it was compiled from a different branch. I didn't get the correct branch (kf/wasm) to build right now. Anyone interested should try to build the kf/wasm branch and see how much further we can push it!