cycle.js ? Another virtual DOM based purely reactive framework

2,399 views
Skip to first unread message

Henry Story

unread,
May 28, 2015, 12:58:59 PM5/28/15
to scal...@googlegroups.com
Anyone looked at Cycle.js ?
 

It claims to be taking the best of Facebook's React but using another JS virtual DOM framework and combining it into a fully reactive application using RxJS .
I was just getting going with japgolly's great scalajs-react but was getting a bit stuck today on the Flux side, and started wondering about wether RxJS would be helpful when I found out about this.

Has anyone ported RxJS to scalaJs?

Henry

Henry Story

unread,
May 28, 2015, 3:22:05 PM5/28/15
to scal...@googlegroups.com
I can now answer that question: there is no need to as there is monifu https://github.com/monifu/monifu .
 

Henry

Henry Story

unread,
May 29, 2015, 5:35:27 PM5/29/15
to scal...@googlegroups.com
I found a very interesting article "A little experiment; Scala.js à la Elm"  
   https://medium.com/@mark_dj/a-little-scala-js-experiment-4a8da7b8ab8c

that seems to  follow very much the style of cycle.js using on the client Monifu, scalajs-react and scalaz
applicatives !  It describes the code on https://github.com/Fristi/reactive-poule which one can compile
and run to see it in action...  Very exciting :-)


On Thursday, 28 May 2015 18:58:59 UTC+2, Henry Story wrote:

Devon Miller

unread,
Jun 8, 2015, 9:36:15 AM6/8/15
to scal...@googlegroups.com
I just started looking at cycle.js. 

It is very interesting.

I like the use of virtual-dom and Rx together. I think there is a play there to combine reactive + virtual dom = new scala.js library that could be the basis of applications. Using react has left me wanting. I'm not sure that gluing into complex libs like React will really work in the long run, despite my desire for it to work. jpgolly has done an awesome job with react-js but it make you wonder if there is another step in the journey to take here.

I've written a 20 line program with virtual-dom and scala.js just to ensure it works, so I'll peek under the hood at cycle.js and see if using monifu to drive the rendering process makes sense.

Henry Story

unread,
Jun 9, 2015, 4:31:24 AM6/9/15
to scal...@googlegroups.com
I'd be interested in your feedback on what the problems you found with React where.

If I remember correctly @japgolly's criticism of cycle.js was that it was not typed at all, and that the separation between the UI and the events->Intentions mapping meant that there were many places where errors due to typos or code drift could enter the picture, and bit like when in Java Land at some point all the configuration started happening in xml files. By separating the UI component from the logic of their use in a type unsafe way he felt we were open to this type of problem. Which interestingly means that @japgolly has become more OO friendly recently :-)

 As for the Scala.js Elm experiment he was a lot more positive there, as that example is typesafe, and the logic is more closely stitched together.

Hmm, that Elm example is interesting but I have an issue with it - like cycle (probably like all 'reactive' approaches) it seems to create a global ctx (channel) for handling callbacks/commands. It's good that it's strongly-typed with exhaustiveness-checking but still.... I'm wary of that. I guess you could still have 'modular' commands and lift them into a higher hierarchy but I guess I just don't like the globalness of it. It feels problematic to me.
The way I use React, components are isolated, they ask for what they need including callbacks. Each component that nests children components manages where those callbacks come from - usually they're all views/modifications to a single piece of data, which can be a composite, and so following the same principle, whichever component nests that one, it only needs to provide exactly what it needs. In A→B→C, A never knows or cares about C. I think that's great! This Elm example feels a bit like in addition to A→B→C there's also G←{A,B,C}.

The Elm author agreed with that criticism, btw. 

( Mind you I am finding I am having to send quite a lot of state to the components: a Web Actor for fetching pages, the Identity of the user, the RouterCtl ( as it is very likely that any subcomponent's click may end up setting off some routing.... ( I wonder how much more? Perhaps that's all ) )

So I am back on React.js with using Rx.Vars rather than monifu - which looks really good though! Oddly enough inside the components rx.Var's seem more appropriate because when drawing a component one cannot afford to wait. One needs a component with a get that returns immediately - if only to tell us that information is being fetched on the web.
But I only spent three days exploring those alternatives, and it is certainly worth exploring the alternatives.

Btw. there are quite a lot of vdom JS libs. https://github.com/localvoid/vdom-benchmark 
It may be interesting to have a pure Scala one, and develop at some point a library that would work on the client as well as on the server (Play or Akka) so that initial rendering can be easily done on the server to speed up initial page views. ( An extra bonus, though only if done elegantly, would be the ability to write pages in such a way that an application could be written for clients that did not have JS - I doubt that is possible really ).

That's a summary of the discussion as I remember it. 

Let us know how your exploration goes.

Justin du coeur

unread,
Jun 9, 2015, 8:19:43 AM6/9/15
to Henry Story, scal...@googlegroups.com
On Tue, Jun 9, 2015 at 4:31 AM, Henry Story <henry...@gmail.com> wrote:
Btw. there are quite a lot of vdom JS libs. https://github.com/localvoid/vdom-benchmark 
It may be interesting to have a pure Scala one

Hear, hear...

Devon Miller

unread,
Jun 12, 2015, 10:47:34 AM6/12/15
to scal...@googlegroups.com
All these points make sense. I was looking at cycle.js to see if I could understand how it handled automatic redraw in order to roll my own on top of something like vdom but using just a plain observable to drive the update "heartbeat".

I think react is great, but I kept feeling that it prescribes way too much around state, properties, children, etc. I've not used it extensively though and perhaps have not learned to love it.

Based on reading through the source of vdom, I do not think creating a scala.js vdom would be outrageously difficult at all. I think the only complexity is in how you attach state to an actual DOM element to link it back into the vdom for very specific book-keeping. There's probably some type classes and monads in there somewhere.

Per Justin's post, maybe a scala.js vdom + automatic rendering via a reactive library would be the "killer app" for scala.js on the front-end. If it had back-end rendering, that makes it compelling on the server. 

At some point, the facade could become too complex and disconnected from the vdom and you might end up with one of those facade UI layers or a WPF thing which may make it hard again.

Devon Miller

unread,
Jun 15, 2015, 2:31:27 PM6/15/15
to scal...@googlegroups.com
I took a look at virtual-dom by MattE and react (under the hood). React has alot of code to encapsulate different aspects of working with the DOM.

I'll try my hand at a vdom for scala.js but more like virtual-dom then react. I did not realize how much React tries to paper over vagaries of the DOM. There seems to be a bunch of singletons in react but it was kind of hard to tell. There are a few things in react that need to get backed into any vdom solution such as handling attributes vs. properties.


Henry Story

unread,
Jun 16, 2015, 7:14:37 AM6/16/15
to scal...@googlegroups.com


On Monday, 15 June 2015 20:31:27 UTC+2, Devon Miller wrote:
I took a look at virtual-dom by MattE and react (under the hood). React has alot of code to encapsulate different aspects of working with the DOM.

I'll try my hand at a vdom for scala.js but more like virtual-dom then react. I did not realize how much React tries to paper over vagaries of the DOM. There seems to be a bunch of singletons in react but it was kind of hard to tell. There are a few things in react that need to get backed into any vdom solution such as handling attributes vs. properties.


Great! You may want to look at this blog post for other usages of virtual dom frameworks
 

including the also pretty interesting looking https://muut.com/riotjs . I can imagine that if a virtual dom lib
appears in scalajs there will be a lot of interesting experimentation going on here too.


 

Justin du coeur

unread,
Jun 16, 2015, 8:35:04 AM6/16/15
to Henry Story, scal...@googlegroups.com
On Tue, Jun 16, 2015 at 7:14 AM, Henry Story <henry...@gmail.com> wrote:
including the also pretty interesting looking https://muut.com/riotjs . I can imagine that if a virtual dom lib
appears in scalajs there will be a lot of interesting experimentation going on here too.

Yeah, that's fascinating, and quite encouraging.  Riot suggests that the barrier to entry for a pure-SJS vdom isn't necessarily that high: a library that gets the key elements right could be enough to get things going.

My gut says that starting by building on top of scalatags, maybe forking it to add some built-in concept of reactive fields -- so that you can simply specify reactive members for any property or attribute, and it does the right thing -- would get you halfway there, maybe more.

Frankly, I wish I had more available time -- this seems like a fun project to play with, and I'm getting the sense that the amount of code required isn't enormous.  I might yet think about evolving my (very ad-hoc) framework in this direction...

Justin du coeur

unread,
Jun 16, 2015, 9:20:29 AM6/16/15
to Henry Story, scal...@googlegroups.com
On Tue, Jun 16, 2015 at 8:35 AM, Justin du coeur <jduc...@gmail.com> wrote:
My gut says that starting by building on top of scalatags, maybe forking it to add some built-in concept of reactive fields -- so that you can simply specify reactive members for any property or attribute, and it does the right thing -- would get you halfway there, maybe more.

I should note, BTW, that I'm not at all sure you would even need to fork scalatags.  The Gadget framework I evolved for Querki is essentially a primitive, rough-and-ready, partial-vdom environment built on top of pure scalatags by creating a new "managed" subclass of Frag.  What I'm now trying to figure out (and I may yet get distracted onto this) is whether you can add a clean form of reactivity by subclassing AttrValue to allow Rx members.

I'm not certain that it works, but if it does, you've got the heart of a simple reactive framework.  (And I wish I'd thought of this six months ago -- I'm beginning to see how to evolve this to something cleaner and more correct...)

Devon Miller

unread,
Jun 18, 2015, 7:54:22 AM6/18/15
to scal...@googlegroups.com, henry...@gmail.com
I thought about scalatags as well. I think this is a good authoring-level library and I will definitely use it once the vdom machinery is working. It's a no-brainer. I did borrow the attribute constructor model from scalatags though to represent properties and their values.

What I found very quickly is that for even foolish little things like setting properties or attributes, that the DOM is pretty much incoherent. A slightly smart glue'ish layer is needed. virtual-dom by MattE is great in a whole bunch of ways but you have to know more about DOM semantics than I would like. In react, there are *alot* of singletons holding rules for how to do things with the DOM.

Having said that, its easy to learn from all the great vdom libraries out there where the glue'ish part needs to be. I built Patch as a monoid (and IO'ish like slick's DBActions) so they could be composed together (empty patch + andThen = monoid) and run in a specific "environment" and am working on DOM glue right now for the browser. Should get to the diff part next week. It's not alot of code, I think I'm at 100 lines right now and some repetitive config objects. I think diff is the 1000 line part.

Justin du coeur

unread,
Jun 18, 2015, 10:25:29 AM6/18/15
to Henry Story, scal...@googlegroups.com
Following up: this conversation has led to some thoughts about how to clean up my codebase (with an eye towards extracting an actual framework from it), and I've proven that this:

On Tue, Jun 16, 2015 at 9:20 AM, Justin du coeur <jduc...@gmail.com> wrote:
What I'm now trying to figure out (and I may yet get distracted onto this) is whether you can add a clean form of reactivity by subclassing AttrValue to allow Rx members.

Totally works.  By adding this clause (note, depends on scalatags.JsDom, jquery-facade and Scala.Rx):

  class RxAttr[T <% AttrVal] extends AttrValue[Rx[T]] {
    def apply(t:dom.Element, a:Attr, v:Rx[T]):Unit = {
      Obs(v) {
        $(t).attr(a.name, v())
      }
    }
  }
  implicit def rxAttr[T <% AttrVal] = new RxAttr[T]

It allows me to write Scalatags code like this:

  p(
    button(disabled := Rx{ selectedProperty().isEmpty })
  )

This works exactly as expected -- the button is enabled only when the selectedProperty Rx member is defined.

That's only one step towards a framework, but it's an initial proof of concept that you can glue Scalatags and Scala.Rx together pretty easily and effectively to produce a nicely reactive environment...

Devon Miller

unread,
Jul 9, 2015, 8:01:38 AM7/9/15
to scal...@googlegroups.com, henry...@gmail.com
I put together a quick scala only vdom library. It's a toy and cannot be used for production use. It has 0 optimizations in it so it diffs the entire vdom tree everytime you diff.  I doubt the library will work for anything but the test page. Use sbt fullOptJS to create the code.


I'm still fiddling with the interface and trying different things out. Right now, I have framed the library like slick because I need different backends for different environments (client and server side) and thought that patch is kind of like an "update" query. All environment (like the DOM environment) specific code is isolated in a "Backend" object. It also has a VDom implementation like scalatags but I've not built a scalatags layer on top as I am focusing on design first.

My next step is to create tests so I can start writing the diff optimizer. I am having issues getting phantomjs running under fedora.

I'll keep reading through various vdom implementations to see how they optimize the diffing process as well as React to see how they have structured server-side rendering. The library does not include React-like components, only the virtual dom part.

Matthew Pocock

unread,
Jul 14, 2015, 9:32:02 AM7/14/15
to Devon Miller, scal...@googlegroups.com, Henry Story
Hi Devon,

Does this bind against the scalatags API? This is a general comment really, but I was wondering if there was a compelling reason why the scalatags API wouldn't work fine for a virtual dom API. Also, the bit I've never been sure of is how you handle events in the virtual dom. How do you manage event handlers?

Cheers,
Matthew

--
You received this message because you are subscribed to the Google Groups "Scala.js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-js+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scala-js/ab286a37-4bdd-4998-9c49-12cd4ee9b77c%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Dr Matthew Pocock
Turing ate my hamster LTD

Integrative Bioinformatics Group, School of Computing Science, Newcastle University

skype: matthew.pocock
tel: (0191) 2566550

Devon Miller

unread,
Jul 14, 2015, 11:34:31 AM7/14/15
to scal...@googlegroups.com, aappd...@gmail.com, henry...@gmail.com
scalatags is not used to build the virtual nodes and it is not used to represent the virtual nodes. 

Once the library has advanced enough, I may have learned enough that allows scalatags to play either or both roles.

For example, it may be useful to specify vdom tree processing performance hints (e.g. "this vdom will never change") directly in the nodes you create and I'm not sure that you could do that easily in scalatags yet. I also need to finalize what state, if any, needs to be kept around on the virtual  tree nodes.

Having said that, there is nothing that prevents scalatags from being a convenient front-end for creating virtual nodes in my library since it is used that way to for the react lib from japgolly.

No event handling yet, hence the comment that it is a toy. There are two ways to do it: a) attach to the top of the tree (e.g. body) or b) attach it directly into the node that is created. I am still trying to figure out why one way is chosen in some vdom implementations while other libraries do it another way. 

If someone knows, I could use the answer to implement event handling, it does not look difficult.

Justin du coeur

unread,
Jul 14, 2015, 11:53:31 AM7/14/15
to Devon Miller, scal...@googlegroups.com, Henry Story
On Tue, Jul 14, 2015 at 11:34 AM, Devon Miller <aappd...@gmail.com> wrote:
For example, it may be useful to specify vdom tree processing performance hints (e.g. "this vdom will never change") directly in the nodes you create and I'm not sure that you could do that easily in scalatags yet. I also need to finalize what state, if any, needs to be kept around on the virtual  tree nodes.

That ought to be easy enough -- just create a pseudo-Attr in scalatags that the renderer checks for, which doesn't actually generate any output.  See my comment upthread for an example of adding a new AttrValue type...

Devon Miller

unread,
Jul 14, 2015, 12:25:09 PM7/14/15
to scal...@googlegroups.com, henry...@gmail.com, aappd...@gmail.com
I initially used a scalatags like structure for specifying attribute keys and values. In fact it was very scalatags-like to start with until I realized that I was then forced to push too much information into the Attr structures and expose too much complexity to the programmer. I needed internal DOM mutation configuration information, namespaces and other info at the attribute level and other information that is at the element level.

So I pulled out some of the complexity and created a "Backend" abstraction. This simplified the virtual dom (element and attributes) and patch class definitions.

I do agree that scalatags can mostly likely easily be used to generate the vdom e.g. the API you would use to author trees in. I'll write one once the diffing and patching algorithms stabilize. Like japgolly's work and react jsx, the scalatags API would be used to create "virtual nodes" underneath.

Currently, I am focused on the virtual node implementation and diffing optimization which I don't know yet if the scalatags internal structure is the best for representing.

Devon Miller

unread,
Jul 28, 2015, 10:44:40 PM7/28/15
to Scala.js, henry...@gmail.com, aappd...@gmail.com
I put together a cycle.js - like demo using the scala-vdom library. scala-vdom is still a toy. I rewrote ftdomdelegate into a scala-only version for eventing as a placeholder until I figure out what to do for event management in scala-vdom.

The cycle.js-like demo uses monifu so that it closes matches mvi-example (model view intent). I used functions for everything to make it look more like mvi-example.

It appears that cycle.js links the observables in a circle with a mechanism to break the circle to kick off the view processing. You have to kick-start processing.


Look in the "reactive" sub-project.

I like the cycle.js concept in that other than having everything be an Observable and linking it together in a circle, there is no real enforced structure to your application.

I'm not sure that the cycle.js model is scalable to large applications. However, this little toy demo really made me realize how conceptually easy it can be.

The "component" project is targeted for a react-ish like component layer but I am going to switch back to working on the vdom part of the library and continue to try and extend/validate the API so it is easy to use by higher-level libraries.

Henry Story

unread,
Nov 4, 2015, 7:09:52 AM11/4/15
to Scala.js, henry...@gmail.com, aappd...@gmail.com
Hi Devon, Hi all,

  Have you seen Vue.js ? They make an intriguing claim at http://vuejs.org/guide/comparison.html

contrary to the common misconception that Virtual-DOM makes React faster than anything else, Vue.js actually out-performs React when it comes to hot updates, and requires almost no hand-tuned optimization. With React, you need to implement shouldComponentUpdate everywhere or use immutable data structures to achieve fully optimized re-renders.

We had a discussion of this on gitter last week here https://gitter.im/scala-js/scala-js?at=56310aef1cc814df63f7dc33
@lihaoyi thought it was not impossible for this to be true

It's not surprising at all that not generating/allocating a massive datastructure and then traversing the massive datastructure to diff it against another simultaneously-traversed massive datastructure isn't the fastest way to do things

targeted DOM manipulation has always been faster than React, it's just that it's impossible to keep it targeted as the code base scales 

Of course one would need to double check their claims somehow. 

How does Vue.js manage to keep the targeted dom manipulation consistent with scale? Do they manage it? 
Is there something we can learn from this? 

ebruchez Oct 28 17:50

Pablo Guerrero

unread,
Nov 5, 2015, 2:34:13 AM11/5/15
to Scala.js, henry...@gmail.com, aappd...@gmail.com
Hi all,

I've been playing with similar things lately, and I found the concept of Incremental DOM really interesting and powerful (maybe similar to what they don in vue.js). Allocating too much memory was the main problem I had with React, and diffing as you go with the real DOM was the obvious solution, but I didn't put the effort to test it. Fortunately, I discovered that someone at google already did the test for me, and it seems a much better alternative to a virtual DOM.


Looking forward to a good solution, 100% in scala.js.

Cheers,
Pablo

Devon Miller

unread,
Nov 5, 2015, 10:32:19 AM11/5/15
to Scala.js, henry...@gmail.com, aappd...@gmail.com
I looked at that as well when I built the vdom solution for scala-js (all scala no js).

I structured my scala library so you could do that kind of differential DOM but its not fully enabled because I was in a hurry. I modelled "patches" as delayed operations to be run against some target DOM as the programmer sees fit. I used the same style of programming found in slick e.g. an Action framework so any action can be created and applied under your control.

Based on my earlier code review of that library (its been awhile so my head is fuzzy), I felt that all these libraries are the same but there is some differences in how differentials are staged to parts of the DOM tree. You can stage the entire patch at one time or bleed out the "patch" in the spirit of that library you mention.

Whether you diff the whole thing, or part of the tree, or apply a "patch", or part of a patch, most of the libraries have the same conceptual basis. I seem to remember that the incremental library stores state directly in the DOM from what I recall (I had to read the code hard to find it), so its not completely state free. In fact, neither is my library. I think its impossible not to keep some state around and the most convenient spot in all the libraries is of course the DOM itself. React, differential, and I think all of them that I looked at keep significant state lying around. You may not see it in the API, but its there: backpointers, copies of stuff, lists of actions (queues) to apply, cleanup routines, etc. It's alot of cruft lying around that you need to "diff" and apply "patches" and a deferred basis.

Devon Miller

unread,
Nov 5, 2015, 10:52:16 AM11/5/15
to Scala.js, henry...@gmail.com, aappd...@gmail.com
It's quite easy to be technically faster than react, and since react is extensible with plugins, its quite possible to be alot faster depending on what plugins you enable and how they impact the vdom layer.

But I found that alot of smaller vdom libraries are less complex than react only because they drop features or scenarios that the react people thought were important to include and that require wiring in the vdom layer itself. These parts need to have alot of infrastructure code to support various scenarios. For example, generating the HTML server side then shipping it over and having the HTML reconcile with the in-memory representation and match up via "hashes." I recall that the initial render, even on the client, goes to HTML so that the mechanism is consistent across both scenarios. react also has queues on DOM elements to stage changes in so they can be attached by different components depending on the plugins and infrastructure you are using and control the timing of when the "vdom tasks in the queues run. Most js only vdom libraries skip alot of these features and I do not think many vdom libraries can easily be extended at the vdom layer, you have to build on top of them.

I also found that being technically faster may not actually mean that the user experience is improved and vice-versa.

In my small scalajs-vdom library I created a small cycle.js demo that use the same concept. I found it easy to program something. But I immediately wondered if I could build a larger more complex application, with different teams hacking on the UI, using that reactive model. It was not obvious to me although conceptually it sounded like a good story.

In most of these libraries, including react, you can control the amount of DOM covered. Some non-react vdom libraries have "hints" as well so the programmer can say that this part of the vdom is static or various such tricks of the trade to skip tree traversal.
Reply all
Reply to author
Forward
0 new messages