Skip to content

Commit

Permalink
Add online and offline html export support (#118)
Browse files Browse the repository at this point in the history
Closes #33, cc @joelostblom

This PR adds support for converting Vega and Vega-Lite charts to live HTML documents. There is a "bundle" option that controls whether the JavaScript dependencies should be loaded from a CDN, or whether they should be inlined into the resulting HTML file. 

### bundle=False
When bundle is False, this follows the [Vega Embed directions](https://vega.github.io/vega-lite/usage/embed.html#start-using-vega-lite-with-vega-embed) to load vega, vega-lite, and vega-embed from jsdelivr 

### bundle=True
When bundle is True, things are a bit more involved. We already inline Vega and several versions of Vega-Lite into the VlConvert executables, so I wanted to avoid including additional copies for the purpose of HTML export.  But in order to use the JS deps inlined into VlConvert, they need to be bundled.  I found that the [deno_emit](https://github.com/denoland/deno_emit) project provides a Rust crate that uses SWC to bundle JavaScript / TypeScript dependencies, and this ended up working well.

One note, the bundled code isn't fully minimized yet, but I have an open PR that will expose SWC's minify option. See denoland/deno_emit#141. Currently, the resulting HTML files start at ~1.6MB, but this will drop to ~1MB when minification is enabled.

The bundling process takes about 1.5s on my machine. Because this is pretty slow, I decided to cache the bundle results, so that subsequent HTML exports that use the same Vega-Lite version will be fast (10-20ms).

### Custom JavaScript bundles
Additionally, a `javascipt_bundle` Python function is added that can be used to create bundles with custom JavaScript logic that references Vega Embed, Vega, and Vega-Lite.  The idea is that Vega-based systems like Altair can use this to build additional integrations.

### Integrations
The most immediate application of the HTML export is to remove the altair_viewer dependency in Altair's html export when `inline=True`.
 
We could also use this to add an "html-offline" Altair renderer, though this could result in large notebooks as every individual Chart would be over 1MB.

Another use-case I have in mind is to use the `javascript_bundle` function to create offline bundles for Altair's JupyterChart. This is why I added support for the lodash debounce function as well, since this is the only import, in addition to vegaEmbed, that JupyterChart's JavaScript logic uses.  The cool thing about this approach is that we can build the offline bundle on the fly (in under 2s) without an internet connection required.
  • Loading branch information
jonmmease authored Oct 5, 2023
1 parent b6b3080 commit 792622f
Show file tree
Hide file tree
Showing 32 changed files with 1,883 additions and 141 deletions.
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ jobs:
- name: Cache rust dependencies
uses: Swatinem/rust-cache@v2
with:
prefix-key: "v1-rust"
cache-on-failure: True
- name: Install Protoc
uses: arduino/setup-protoc@v2
Expand Down
Loading

0 comments on commit 792622f

Please sign in to comment.