Wrong Technology

Nitro v0.11 shipped with Web Assembly support

Nitro 0.11 can run apps entirely in-browser.

What does this mean?

Ordinarily, your Nitro app runs on a server (or cloud) somewhere, and displays interactive user interfaces in your web browser:


                    Network
                       │            Python
                       │           ┌──────────────────┐
                       │           │  Nitro           │
                       │           │ ┌──────────────┐ │
                       │           │ │              │ │
                       │           │ │     App      │ │
                       │           │ │              │ │
                       │           │ └─────▲─┬──────┘ │
  Browser              │           │       │ │        │
 ┌───────────┐         │           │       │ │        │
 │           │         │           │ ┌─────┴─▼──────┐ │
 │           │     I/O │           │ │              │ │
 │    UI     └─────────┼───────────┼─►    Flask     │ │
 │           ◄─────────┼───────────┼─┐              │ │
 │           │         │           │ └──────────────┘ │
 └───────────┘         │           │                  │
                       │           └──────────────────┘
                       │

With Nitro 0.11, you can put your Python code (and packages) on a static website somewhere (like Github Pages or S3 static websites), and have it load and execute entirely inside a web browser:

                                        Network
                                           │
                   Python                  │
                  ┌──────────────────┐     │
                  │  Nitro           │     │
                  │ ┌──────────────┐ │     │
                  │ │              │ │     │
                  │ │     App      │ │     │    Web Server
                  │ │              │ │     │   ┌──────────────┐
                  │ └─────▲─┬──────┘ │     │   │              │
  Browser         │       │ │        ◄─────┼───┤ Static Files │
 ┌───────────┐    │       │ │        │     │   │              │
 │           │    │ ┌─────┴─┴──────┐ │     │   └──────────────┘
 │           │    │ │              │ │     │
 │    UI     └────┼─►    Nitride   │ │     │
 │           ◄────┼─┐              │ │     │
 │           │    │ └──────────────┘ │     │
 └───────────┘    │                  │     │
                  └──────────────────┘     │
                                           │

How is this possible?

Nitro 0.11 introduces an application runtime called Nitride, built atop Pyodide, a port of CPython to Web Assembly.

Nitride is a tiny (~5KB) layer that makes it possible to spawn a Python process in a Web Worker, which then controls the UI. The UI then continues to operate normally, assuming it's communicating with a Nitro server over the network. In reality, the Nitro "server" is simply running locally on a separate operating system thread.

What kind of apps is this useful for?

Running apps this way is useful only if:

What does it look like in practice?

Broadly, there are two ways to run your app:

  1. Embed your code directly in HTML using a <script type="text/python"> tag.
  2. (Recommended) Provide a configuration in a <script type="application/nitro"> tag.

Embedding Python code directly in HTML looks like this:

<script type="text/python">
from h2o_nitro import AsyncView as View, box

async def main(view: View):
name = await view(box('What is your name?', value='Boaty McBoatface'))
feel = await view(box(f'How do you feel today, {name}?', value='intrigued'))
await view(f'What a coincidence, {name}, I feel {feel}, too!')

nitro = View(main, title='Hello Nitro!', caption='v1.0')
</script>

Although the above technique works, it's more convenient to write programs in .py modules and load them dynamically using a YAML configuration that describes your app:

<script type="application/nitro">
language: python
entrypoint: example_hello.py
</script>

You can also load external packages, wheel files, and modules dynamically, like this:

<script type="application/nitro">
language: python
packages:
- numpy
- pandas
- bokeh
bundles:
- h2o-nitro-bokeh
files:
- example_bokeh_util.py
entrypoint: example_bokeh.py
</script>

For more comprehensive documentation, see https://nitro.h2o.ai/wasm/.

Summary

The primary reason I added support for Web Assembly is to make our interactive docs run in-browser, and those docs are a lot more interesting to play with than the static documentation :)

Also, if you're interested in things like PyScript, Nitro offers a "batteries-included" approach - a huge variety of interactive components that you can snap together quickly and build applications, instead of using Python as a substitute for Javascript and futzing around with the browser DOM. Anything you can do with PyScript, you can do with Nitro, too!

Happy hacking!

« Pyodide for Nitro: Progress update 2 Nitro in Web Assembly - Performance »