Using cesium.js within Jupyter, web workers do not terminate, leaking resources

1. A concise explanation of the problem you’re experiencing.

I am trying to use cesium.js within a Jupyter notebook, where I am emitting HTML to render a Viewer within a step in the notebook. When I am iterating in the notebook, running the “step” that renders the Viewer repeatedly, eventually the browser (both Chrome and Firefox) gets laggy and FPS drops.

I noticed that the number of web worker thread instances increases monotonically upon each step execution, and they don’t seem to terminate after the Jupyter step has re-run. In some cases, I am loading large CZML files with GLTF models, so memory/CPU consumption quickly becomes an issue.

2. A minimal code example. If you’ve found a bug, this helps us reproduce and repair it.

In a jupyter notebook, enter this content into a cell and execute it ten times. In the Developer Tools, you’ll see ten web workers, which are labeled with GUIDs.

Update: I was able to work around this by wrapping the HTML in an iframe and using the srcdoc and sandbox allow-scripts attributes. This appears to trigger the correct behavior for cleaning up the web worker resources.

Can you please be slightly more specific on how you managed to get it to work in a Notebook? I tried a few different ways last year so I could do some workshops on using CesiumJS. Sadly I resorted to just using the Sandbox straight but it was insanely confusing to the participants. I/we normally always use Notebooks as they are so much better for trainings so if you managed to get a working solution I would kill to chat with you on it if you don’t mind.

I’m using JupyterLab 1.0, running inside a docker container for development. Try this as a hello world, running it inside one step. It’s a bit hacky, admittedly.

def cesium_html():

return \
      <iframe style="width: 1024px; height: 768px; overflow:hidden; border: 0px; margin: 0px" scrolling="no"
        frameborder="0" marginheight="0" marginwidth="0" sandbox="allow-scripts" srcdoc='
        <!DOCTYPE html>
        <html lang="en">
          <meta charset="utf-8">
          <script src=""></script>
          <link href="" rel="stylesheet">
          <div id="cesiumContainer" style="width: 1024px; height:768px"></div>
            //Cesium.IondefaultAccessToken = "your_access_token";
            var viewer = new Cesium.Viewer("cesiumContainer");

import IPython.display


You should see a cesium globe appear. The iframe was necessary to avoid leaking the web worker threads, which will eventually cripple your computer :slight_smile:

In use case, I’m using CZML, with the czml3 python library, to create and render my data inside cesium, though I’ll probably switch to native javascript soon as I need more flexibility.

I’m not a Jupyter expert, so there is probably a better way. I expect that the right way to do this is a formal “widget”, something like, but it’s a bit out of date and I haven’t tried it. There’s also but it also is a bit neglected and didn’t work for me, so I ended up doing my own thing.