6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ダッシュボードも作れるStipple.jlの紹介

Last updated at Posted at 2020-09-01

Stippleの紹介

JuliaのWebフレームワークにGenieがあります。Juliaの機能を活かしており、とても使い心地の良いパッケージなのですが、英語/日本語問わずまだまだサンプルが少ない状態です。そんな中でGenie.jlの関連情報をあさっていたらJuliaCon 2020でGenieの作者のAdrian SalceanuさんがStippleというDashboardsの作成にも使えそうなWeb UI用パッケージを紹介されていました。Webサーバー越しにデータバインディングを実現している面白いパッケージなので、簡単に紹介したいと思います。

インストール

GenieはWebサーバー用のフレームワークで、その上にStippleというパッケージがあります。この二つをインストールします。

pkg> add Genie
pkg> add Stipple

実行

Julia REPLで次のコードを実行します。

using Genie, Genie.Router, Genie.Renderer.Html, Stipple

# define (reactive) model
Base.@kwdef mutable struct Name <: ReactiveModel
  name::R{String} = "World!"
end

# initialize the model
model = Stipple.init(Name)

# define UI
function ui()
  page(
    root(model), class="container", [
      h1([
        "Hello "
        span("", @text(:name); style="color:red")
      ])

      p([
        "What is your name? "
        input("", placeholder="Type your name", @bind(:name))
      ])
    ], title="Basic Stipple"
  ) |> html
end

# bind root "/" to ui
route("/", ui)

# start web server
up()

up()を実行するとWebサーバーが起動します。環境にもよりますが、例えば下記のように表示されるので、ブラウザからアクセスしてみます。

Web Sockets server running at 127.0.0.1:8001

Web Server starting at http://127.0.0.1:8000

Web Server running at http://127.0.0.1:8000
Genie.AppServer.ServersCollection(Task (runnable) @0x0000000015eae850, Task (runnable) @0x00000000356d2e10)

Stipple_example.png

この時、Julia REPLに下記のようなエラーが出ることがありますが、たぶんfavicon.icoがないために出ているだけなので無視してokです。

[ Info: / 200
[ Info: / 200
 Error: error handling request
   exception =
    IOError: stream is closed or unusable
    Stacktrace:
     [1] check_open at .\stream.jl:328 [inlined]
      ...
     [12] (::HTTP.Servers.var"#13#14"{HTTP.Handlers.var"#4#5"{HTTP.Handlers.RequestHandlerFunction{Genie.AppServer.var"#6#12"}},HTTP.ConnectionPool.Transaction{Sockets.TCPSocket},HTTP.Streams.Stream{HTTP.Messages.Request,HTTP.ConnectionPool.Transaction{Sockets.TCPSocket}}})() at .\task.jl:356
 @ HTTP.Servers C:\Users\dskkato\.julia\packages\HTTP\atT5q\src\Servers.jl:373
[ Info: /css/stipple/stipplecore.min.css 200
[ Info: /js/stipple/vue_filters.js 200
[ Info: /js/stipple/stipplecore.js 200
[ Info: /js/stipple/vue.js 200
[ Info: /js/stipple/underscore-min.js 200
[ Info: /__/channels.js?v=1.1.0 200

動かしてみる

StippleのUI部分にはVueが使われているようで、コンポーネント間のデータを同期してくれます。また、Julia-REPLと双方向のデータバインディングを提供実現しています。一つずつ試して行きましょう。

UIのコンポーネント間の同期

まずは先ほどの画面のテキストボックスにあるWorld!を適当にJulia!に書き換えて見ます。すると、赤い文字の部分も入力に追従して自動で変化していきます。VueやReact等を触ったことある方ならなじみのある操作かと思います。

Stipple_example2.png

Juliaとの双方向データバインディング

UI -> Julia

Stippleの目玉はこれかと思います。先ほどJulia!に書き換えた状態でmodelの状態を確認してみます。ちゃんとJulia!に更新されていますね。

julia> model
Name(Observable{String} with 1 listeners. Value:
"Julia!")

Julia -> UI

次にJulia側から操作してみます。この時、オリジナルのStringオブジェクトを書き換えたことが分かるように[]で参照を取ってきて更新する必要がある見たいです。

julia> model.name[] = "Julia-REPL"

下記のように書くと、Stippleがオブジェクトの更新をトラッキングできなくなるようで、うまく動かなくなるので注意が必要です。

julia> model.name = "Julia-REPL"

すぐにUIにも反映されます。

Stipple_example3.png

カウントダウン

最後に、簡単なカウントダウンを動かしてみます。

for i in reverse(0:10)
  model.name[] = "$i"
  sleep(1)
end 

(画面はそのうちupします...)

Stippleのポテンシャル

JuliaCon 2020での発表資料やDiscorseを見ているとダッシュボードを作れる程度には開発が進んでいるようです。多少HTMLのことを知らないと使いにくいかもしれませんが、簡単なGUIにも使えそうな印象を受けました。

Julia REPL->UIのフローはブロードキャストされているようで、マルチクライアントの状態でもすべての状態が更新されます。惜しむらくは、UI上での操作が他のクライアントに反映されませんでした。REPLからは出来ているので、大した問題ではないかもしれませんが。

Demos (リポジトリから転載)

関連情報

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?