Make a webapp framework/ecosystem as awesome as R's Shiny: a challenge to Julia's community

Nice. Is there a way to publish it as well?

if instead of using Interact you did using InteractNext, Mux [1]

You can serve it as a web server:

ui = @manipulate for language in ["Julia", "R", ...]
    plot(...)
end
webio_serve(page("/", req -> ui))

[1] Pkg.clone("https://github.com/JuliaGizmos/InteractNext.jl.git"); Pkg.checkout("WebIO") – I’ve just tagged the WebIO fix needed for this.

7 Likes

Has anyone tried getting appmode in Jupyter working with Julia?

https://github.com/oschuett/appmode

This would be a nice step towards building shiny apps.


An example binder is below:

https://github.com/binder-examples/appmode

3 Likes

Just following up. A precursor to a dashboard app can be seen at:

juliatetris.com

This combines WebIO and Binder (using the appmode described above). The binder repo is available at:


Putting it together,

@xiaodai, what do you think is still needed to get you there?

7 Likes

Ok, so no more bullshit! I actually made a Julia dash app relatively quickly. See:

Julia Dash Binder – Tetris Challenge

You should now truly be in a good spot for forking this project and making your own.


As an aside, I think Julia would greatly benefit from package developers adopting a binder standard.

Exploring a package’s functionality without downloading it is usually one of the few perks reserved for javascript.

3 Likes

That’s very interesting! Did you also try something like Mux or HTTP.jl to serve a WebIO app?

See some examples of that here
https://github.com/lancebeet/julia-scripts

1 Like

My main argument against a Mux setup is it takes time (to code).

This binder took up very little time past setting up the Jupyter notebook. // i.e. the devops


Also, the idea was never could “I” build a WebIO app using Mux or HTTP.jl.

It’s can I build a dash app in a way accessible to Julia users without 5 years of web development experience.

See:


edit: One final remark is that I don’t think Julia is anywhere near close to being suitable for a backend server.

Although Genie.jl exists, there is just not the ecosystem in place to make an API that measures up to one from Rails or Django.

This is why all the links in this thread are for Dash apps. As proof, the API the Tetris Challenge uses for keeping scores is actually a Rails server I built in a day.

1 Like

We’ll get there.

5 Likes

My understanding is that once people start re-jiggering LLVM, JVM etc to output to WebAssembly and it is universally supported in browsers, the JavaScript domination might come to an end shockingly quickly, no? (This is a question not an assertion, I have no idea what I’m talking about.)

Well, I guess that was my question though, will it really take that long? I don’t see why it would take that long, all you need is to write the code that does LLVM IR to WebAssembly and things start changing really, really fast right? I suppose there is the barrier of all the front end developers not necessarily wanting to jump up and change to a different language, but the front-end developers I know don’t particularly like JavaScript.

The Birth & Death of JavaScript

2 Likes

I see. I don’t have a lot of experience on this, but I’d love to hear specifically what are the extra steps that are required (after the application is already done with WebIO) to set it up with Mux, how the Binder approach solves them and whether there is some tradeoff or the binder approach is just fine.

1 Like

Although I personally would love to see the death of JavaScript :nerd_face:, and have Julia → WebAssembly take over as the preeminent language of the web, unfortunately, no matter what much better options are available, I don’t see JS going away anytime soon - just because of the shear momentum, all the resources available (books, on-line courses, tools, coding camps, money spent to make JS run fast), and all the programmers already skilled in getting JS to do what they want, no matter whether or not they are truly happy with it.

After all (as I commented on here), COBOL and FORTRAN are still around and in heavy use :scream::joy: after nearly 60 years!

I am cautiously optimistic that WA will help level the playing field, and in addition, just as LLVM has helped spark a lot of creativity in new programming languages (such as Julia itself), WA will spark just as much creativity in new languages designed for client side web programming.

1 Like

I want to report back with some great news.

I’ve been eying Predix UI for quite some time, wanting to use their components on top of Genie. If you’re not familiar with Predix UI, it’s developed by GE and they have a huge amount of high-quality UI elements implemented as Polymer components. Lots of them are focused on data science and data visualization as they’re used by GE to build software for monitoring their industrial equipment. They fit perfectly into Genie’s view architecture as they can be represented purely as a combination of HTML elements and data - so no ugly generation of JS from Julia! :nauseated_face: Ex: Predix UI – Learn From Scratch

What’s been holding me back from pursuing this was the weird GE licensing of the code. The awesome part is that a couple of weeks ago GE started to migrate the Predix UI components over to BSD-3 and Apache licenses. (Amazing luck or maybe my constant nagging on all available channels, from Quora to Github, got them to review their licensing :blush:)

I’ve now begun experimenting with building Genie + Predix UI apps. There are some hurdles, mostly related to assets management: Polymer and Predix use Bower, which is deprecated, while Genie uses the modern Webpack + Yarn combo. Plus there’s gonna be some work to setup reactivity. But most of it Just Works by default and if I’ll have enough time I might have a demo in a couple of months. Fingers crossed!

26 Likes

Way to go @essenciary, exciting!

I think it basically boils down to:

  • do you want a notebook?
  • or do you want a website?

As a dashboard app is a single page thing, I’m guessing the easiest way to do this is through a jupyter notebook.

Binder solves the threading issue this causes by using docker boxes to house your jupyter notebooks.

Once InteractNext upgrades to the new version of WebIO that’s compatible with Binder, it should remove the javascript issues (for simple stuff like sliders)

// also, I think a Jupyter app looks a lot more iconic (at this point in time) than a home-rolled bootstrap app

I’m picturing something very simple: a plot, a few sliders, some check boxes, some dropdown menus and I wanted to understand how much extra effort it takes from: “it works locally on WebIO” to “it is a web app everybody can use online”. Your approach seems to simplify this step drastically.

What were the drawbacks of the binder approach? For example, is the slowish page loading time due to using Binder or is it inevitable with Julia based web apps?

2 Likes

Slow page loading isn’t a julia thing in general. I’ve written a recommendation system on top of HttpServer.jl and a small embedded webdemo application to explore the results in a web gui (the recommendation itself is meant to be used via a simple REST interface) and it’s lightning fast. But I just used HttpServer to process get requests and all the webpages are handwritten html (and a little javascript) directly on top of that.
Also I did load testing on the rest interface (again directly on top of HttpServer.jl) and I was pleasantly surprised how well it scaled on a simple PC with 4 cores it could easily handle hundreds of requests per second.

2 Likes

In 2019, Julia 1.x world, I found the combination of Intract+Mux relatively simply for deploying an interacting model to the web à-la Shiny, although the documentation of the two cited packages could still be improved…

using Interact,Plots,Mux

function myModel(p1,p2)
    xrange = collect(-50:+50)
    model = p1.*xrange .+ p2.* (xrange) .^2
    return model
end

function createLayout()
  p1s = slider(-50:50, label = "Par#1 (linear term):", value = 1)
  p2s = slider(-5:0.1:5, label = "Par#2 (quad term):", value = 1)

  mOutput = Interact.@map myModel(&p1s,&p2s)
  plt = Interact.@map plot(collect(-50:50),&mOutput, label="Model output")
  wdg = Widget(["p1" => p1s, "p2" => p2s], output = mOutput)
  @layout! wdg hbox(plt, vbox(:p1, :p2))
end

function serveLayout(port)
    try
      WebIO.webio_serve(page("/", req -> createLayout()), port)
    catch e
      if isa(e, IOError)
        # sleep and then try again
        sleep(0.1)
        serveLayout(port)
      else
        throw(e)
      end
    end
end

serveLayout(8001)

Resulting in:

Disclaimer: the code in this example is from an upcoming Apress book on Julia I am finalising… I am a bit confusing on copyrights, but I think I can still post it…

20 Likes

This is really lovely! We can definitely make something here!