bokeh/ipywidgets_bokeh

Feature to customize default cdn

govinda18 opened this issue ยท 11 comments

Currently we default to unpkg for cdn. It will be helpful if we can have a way to configure custom cdn path for an ipywiget.

Reference Code

@govinda18 I'd be happy to take this issue. I was thinking about using an environment variable as an override for the CDN, but do you have a preferred approach here?

@govinda18 I'm in the process of testing this feature, but I can't seem to get ipywidgets_bokeh running. Are you able to serve ipywidgets_bokeh/examples/ipyvolume_camera.py? For me I get a blank page, and an error in the developer console:

Model 'ipywidgets_bokeh.widget.IPyWidget' does not exist. This could be due to a widget or a custom model not being registered before first usage.

Apologies for the delayed response - missed this

I was thinking about using an environment variable as an override for the CDN, but do you have a preferred approach here?

Not really sure but loader.js is run on client side and we have access to python package only right? Setting the env variable at run time in client side script can be tricky - may be I am missing something

I'm in the process of testing this feature, but I can't seem to get ipywidgets_bokeh running. Are you able to serve ipywidgets_bokeh/examples/ipyvolume_camera.py? For me I get a blank page, and an error in the developer console:

I did not try that example but a simple panel app serving any ipywidget should help I think. We have to build the javascript assets though if installed via a local checkout. The dev setup is not well documented but we can use npm run build or npm run dev as per the package.json scripts. Here is a simple app to test:

import panel as pn
import ipywidgets as w
pn.extension()

pn.Column(w.HTML("Test"))

Let me know if it works for you.

Just an FYI, there is an error in the webpack config here is slightly buggy as it needs to be three ===. An minimized build helps me in adding break points and make changes to build files easily as hot reloading is not configured currently.

Thanks for the context here, I think it will be really useful in this work.

One other thing: I'm not sure if you've check it out, but Panel is a mature project that can display bokeh plots and generate dashboards. I know development on ipywidgets_bokeh has slowed somewhat, so if you need a dashboard ASAP it might be worth considering as well.

One other thing: I'm not sure if you've check it out, but Panel is a mature project that can display bokeh plots and generate dashboards. I know development on ipywidgets_bokeh has slowed somewhat, so if you need a dashboard ASAP it might be worth considering as well

Yep, I am an active user of panel. Our original use case is actually not to embed ipywidgets in bokeh but in panel actually. Panel seems to be using ipywidgets_bokeh when serving in a standalone env (reference) and uses panel.models.ipywidgets when a comm is present (like in Jupyter).

I have a similar issue that this feature would fix - I'm developing a custom ipywidget that will also eventually need to be integrated into a panel dashboard. Since it isn't published on npm, the unpkg CDN URL doesn't work, and the widget won't display in a standalone env. I haven't been able to figure out any workarounds for this, so the ability for me to specify a different URL for my local widget would be super useful.

Not really sure but loader.js is run on client side and we have access to python package only right? Setting the env variable at run time in client side script can be tricky - may be I am missing something

@govinda18 Sure, we can alternatively do this by allowing the user to override the CDN on the python side by modifying ipywidgets_bokeh.widget.IPyWidget. Can you take a look at this branch and see if it works for you? You can test with something like this:

# example.py
import panel as pn
import ipywidgets as ipw
from ipywidgets_bokeh import IPyWidget

pn.extension()


def app():
    return pn.Column(
        IPyWidget(widget=ipw.HTML("Test"), cdn="https://mytestcdn.org")
    )


pn.serve({'app': app})

Run the example with python ./example.py, no need to panel serve explicitly.

I did this in the least intrusive way I could, so we'll have to see what the maintainers have to say about this approach. Keep in mind the CDN will be used like this: ${cdn}/${packageName}@${moduleVersion}/dist/${fileName}.

While this works, The issue with this is from a user perspective. For example, if I have a custom ipywidget which is used by many different users, I would probably want them to be abstracted from the details of how ipywidgets are working with panel under the hood using ipywidgets bokeh.

A better solution perhaps can be to be able to configure a static variable in the IPyWidget class that may be a dict where some specific widgets can be configuredto use a particular cdn. Something like:

IPyWidget.set_cdn(MyCustomWidget, "mycustomcdn") # Allows setting cdn for specific widgets

IPyWidget.set_default_cdn("mycustomcdn") # Allows configuring the default cdn - default to unpkg

Let me know what you think.

This sounds great to me - I've implemented these suggestions so that there are now three ways of setting the CDN:

  1. When a widget is initialized, you can supply a cdn kwarg to override that particular widget instance. If no cdn kwarg is given, the IPyWidget.default_cdn class variable is used
  2. Calling my_widget.set_cdn('https://mycustomcdn.com') will set the CDN on a particular widget instance after initialization
  3. You can set the default CDN by calling IPyWidget.set_default_cdn('https://mycustomcdn.com') before creating any IPyWidget instances

I've updated this branch to reflect these changes. If this looks good to you, I'll make a PR and we'll see if we can get it merged here. Thanks for your input! ๐Ÿš€

Looks great to me!

Closing as #60 has been merged