holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.61k stars 500 forks source link

Document and generalize loading of extensions and third party libraries #1582

Open philippjfr opened 3 years ago

philippjfr commented 3 years ago

Panel is an extension on top of Bokeh and before any Bokeh model that is part of Bokeh can be rendered panel.js needs to be loaded in some form. In the notebook this relies on the panel/_templates/doc_nb_js.js template which waits until both Bokeh and Panel have been loaded. Additionally I also recently had to add some support to ensure that third party libraries need to be loaded before rendering (as sometimes when using inline resources they would not load in time), see https://github.com/holoviz/panel/pull/1577.

However while this handling is fine for Panel itself it does not work for other extensions (e.g. awesome-panel-extensions). So there are a number of things we can do to make sure further extensions can register themselves both with bokeh and with panel.

The first thing is that bokeh/core/_templates/try_run.js does not even consider third-party extension (including panel) which is why we had to override this template in Panel in the first place. So we should make sure that we upstream a patch into bokeh that ensures that all imported extensions are considered in try_run.js.

In Panel we should have a mechanism for other Panel extensions to register themselves appropriately as well. We have to consider whether this should be via a plugin mechanism or simply discover extensions that have been imported before pn.extension is run.

Secondly we should make sure that the mechanism for ensuring third-party JS libraries are loaded before rendering is also extensible. In all likelihood this should discover all custom models being rendered and then check some attribute on the model to look for any JS libraries that need to be available globally, e.g. something like PlotlyModel.__js_required__ = 'Plotly'. The rendering code can then ensure that 'window.Plotly' is available before rendering the model and do so in a way that is transparent for other downstream libraries.

Currently to make this work the user would have to:

  1. Register their custom model with pn.extension._imports
  2. If not loading the custom extension with pn.extension('custom') manually add the extension to pn.extension._loaded_extensions
  3. Register the global variable on the JS window with pn.extension._globals

Cc: @MarcSkovMadsen

MarcSkovMadsen commented 3 years ago

Thanks. I've read it. I have a rough understanding of this. But to fully understand and work with it. I would have to try out steps 1. to 3.