Compiled components : Final step - help needed - removing nodejs from the build process

We have a pile of internal components we developed. We are on Bokeh 2.3.1 and used “Bokeh init” to setup the framework (folllowing the documentation online replaced the imports with “@bokehjs/” ) and compiled all the components to a single file. then loaded them up using a template - all that looks and works great as long as we include in the actual python side in the project on each of the components:

__implementation__ = JavaScript('''
    // fake creation to avoid bokeh throwing errors.

while everything now works we can see that bokeh behind the hood is trying to compile the components at runtime as nodejs is running and things are still slow in first load - a step we are trying to avoid. setting things to None - throws an error - even though everything is ready and working as long as we put something in the implementation.

what is the correct configuration on the implementation side if we want to indicate to bokeh not to worry about it as it has been created and compiled already - aka not to depend on nodejs being in the environment as all the files have been pre-compiled?

Thanks for any help in advance!

cc @mateusz and @Philipp_Rudiger

@Bryan did the team (@mateusz or @Philipp_Rudiger ) have a response - did it get deleted due to the transition?

This seams like a critical item that is missing from documentation, online and as far as i can see i can’t figure it out from looking at the source files.

thanks in advance!


There is an “awesome panel” extension to panel/bokeh. The following URL provides details on their approach to pre-built bokeh extensions. Hopefully, it provides some additional information relevant to your problem.

Hey @_jm thanks for that comment and you are right they are probably the only resource that goes into the depth needed to create custom components so i followed that document to build/compile our component but i still am in the dark on the question I’ve asked as there is no mention to it anywhere - and it’s forcing us to run our server with node for the build steps.

Like many OSS projects, there is far more work to do than people to do it, which means that work has to be prioritized. The reality is that compiled components is a very advanced feature, and I expect the number of people using it only reaches to the low tens of people, if not less. By that measure, there are simply more important priorities ahead of this.

cc @Timo We have historically avoided labeling things as “experimental” or “advanced” in any official way, largely due to lack of concrete definitions or decision making process around when and how to apply those labels. But I think it might be advised to add some large disclaimers to the extensions chapter of the User guide to make it clear that:

  • this is a highly advanced feature
  • it is still under heavy active development (“experimental”)
1 Like

All that is left on my end is to say is thank very much for everything the team is doing, understood, just hoped we’d missed something obvious!

going to stop trying to find different ways of asking the same question every other month :slight_smile:

1 Like

@anx I would suggest though, opening a GitHub Issue regarding the documentation for compiled extensions and nodejs. AFAIK there is not one and not having any issue is another reason things can and do get lost in the shuffle.

1 Like

I added a note to my to do list - having an issue on GitHub would be great!

By the way now that we figured out that there isn’t currently a built in solution currently, I’ve consulted with a friend/workmate that is a much more prolific python developer than myself (I’m a JS guy at heart) and he whipped up something that works for our case - probably not production external friendly but thought this might be helpful if anyone else encounters this issue while developing components:

   # Monkeypatch the Bokeh compiler to not compile script if we give a custom component a completely blank script.
# We want to pre-compile it and make it available via URL instead, so we don't incur the overhead of invoking node at runtime .
def monkeypatch_bk_compiler():
    import bokeh.util.compiler as buc
    # Get a ref to their compiler
    bk_compiler = buc.nodejs_compile

    # Define our own, that ultimately delegates to theirs
    def our_compiler(code, lang="javascript", file=None):
        print('In our monkeypatched compiler.  Checking if we supplied anything to compile')
        if code.strip() == '':
            print('No code supplied, returning default implementation')
            return buc.AttrDict({'code': '//Null implementation to avoid bokeh throwing errors.\n', 'deps': []})
            print('Found a real implementation, compiling it')
            return bk_compiler(code, lang, file)

    # Make the monkeypatch
    buc.nodejs_compile = our_compiler