r-wasm / quarto-drop

Drop down an interactive R or Python console, code editor, and plotting window from the top of your Quarto slides.
https://r-wasm.github.io/quarto-drop/
MIT License
100 stars 3 forks source link

Run Pyodide in a Web Worker #5

Open georgestagg opened 1 month ago

georgestagg commented 1 month ago

Comlink should work well here.

Needs research -- Can we distribute a .js worker script with a Quarto reveal.js plugin without executing it?

georgestagg commented 1 month ago

This may be doable without shipping a separate resource file using URL.createObjectURL(), Blob(), and bundling the worker script embedded with esbuild's loader mechanism.

coatless commented 1 month ago

I was playing around with doing an inline worker:

https://github.com/coatless-quarto/pyodide/issues/12

The most promising approach is to use a Blob web worker similar to what is proposed on SO by vsync:

<!DOCTYPE html>
<script id="worker1" type="javascript/worker">
  // This script won't be parsed by JS engines because its type is javascript/worker.
  self.onmessage = function(e) {
    self.postMessage('msg from worker');
  };
  // Rest of your worker code goes here.
</script>
<script>
  var blob = new Blob([
    document.querySelector('#worker1').textContent
  ], { type: "text/javascript" })

  // Note: window.webkitURL.createObjectURL() in Chrome 10+.
  var worker = new Worker(window.URL.createObjectURL(blob));
  worker.onmessage = function(e) {
    console.log("Received: " + e.data);
  }
  worker.postMessage("hello"); // Start the worker.
</script>
georgestagg commented 1 month ago

Indeed, using createObjectURL() and new Blob() in that way works well.

Initial implementation work here: https://github.com/r-wasm/quarto-drop/compare/main...pyodide-worker, combined with esbuild text bundling rather than loading from a <script> in the DOM.

Still, it will need more work to get plotting back up and running. Will need to either use tricks like using the bitmap AGG backend and sending results back as base64 encoded .png, or use the custom OffscreenCanvas based renderer developed for quarto-live.

Will return to this after quarto-live initial release.