12 ms·
The Future of JavaScript MVCs
- EGreg 13y agoHow is this different from the dirty checking that Angular does in its ModelView update cycle?
- peterhunt 13y agoThis is copied from a comment of mine on Reddit which should cover it: http://skulbuny.com/2013/10/31/react-vs-angular/ http://skulbuny.com/2013/10/31/react-vs-angular/
- dmak 13y agoThat seemed more like a rant about Angular than an unbiased comparison. I had the impression that the writer didn't do things the "Angular way" when he said, "Since composing directives is so annoying, they end up being basically mini-jQuery apps that are pretty hard to maintain."
- sebmarkbage 13y agoReact does the diffing on the output (which is a known serializable format, DOM attributes). This means that the source data can be of any format. It can be immutable data structures and state inside of closures. The Angular model doesn't preserve referential transparency and therefore is inherently mutable. You mutate the existing model to track changes. What if your data source is immutable data or a new data structure every time (such as a JSON response)? Dirty checking and Object.observe does not work on closure scope state. These two things are very limiting to functional patterns obviously. Additionally, when your model complexity grows, it becomes increasingly expensive to do dirty tracking. However, if you only do diffing on the visual tree, like React, then it doesn't grow as much since the amount of data you're able to show on the screen at any given point is limited by UIs. Pete's link above covers more of the pref benefits.
- Joeri 13y agoSo, maybe i'm misunderstanding, but, the perf advantage is that react waits until the next RAF and then only updates the parts of the DOM that actually changed? So, now i'm wondering: why can't the browser do that? Isn't this whole middle-man approach something to eventually be optimized out?
- polarix 13y agoSure, the browser could implement a virtual dom and then sync it and do a reflow once per frame.
- fbender 13y agoYou can do that with the help of `document.createDocumentFragment()`.
- peterhunt 13y agoThe browser does do this already to an extent. The difference is that React constrains the operations a user can do (i.e. we only give them the DOM node if they explicitly ask for it and only let them manipulate it at certain times) so we eliminate the operations that cause the DOM to be slow. If the DOM were to implement this it'd have to break backwards compatibility.
- STRML 13y agoI'm not great at reading ClojureScript - but I'd really like to port some of the optimizations from Om, such as the rendering on requestAnimationFrame and usage of shouldComponentUpdate to Backbone.LayoutManager[1]. Swannodette, if you're around, do you have a minute to give a more in-depth explanation of how that works? 1. https://github.com/tbranyen/backbone.layoutmanager/wiki https://github.com/tbranyen/backbone.layoutmanager/wiki
- swannodette 13y agoIf you're using Backbone.js I would just rely on React to deliver the requestAnimationFrame enhancement. As far as shouldComponentUpdate, just make your component implement a better one. To be honest at this point there is little that Om does over React other than provide really good defaults ;)
- STRML 13y agoThanks for the input. I'll look into it. We've been talking a bit about doing a more general rewrite of LM and I've been looking for ideas that would make it worthwhile (not just cleaner code, but better perf or features). This might be one of them.
- d_j_s 13y agoThe requestAnimationFrame part with simple backbone views is pretty straight forward: https://github.com/danshearmur/backbone-fast-view/blob/master/backbone.fast-view.js https://github.com/danshearmur/backbone-fast-view/blob/maste... I'm sure doing a similar thing with LayoutManager wouldn't be too hard. I think LayoutManager uses _render internally too so you may want to call it something else. It also definitely does make the benchmarks faster http://danshearmur.github.io/backbone-fast-view/ http://danshearmur.github.io/backbone-fast-view/
- STRML 13y agoThat's great - benchmark 2 is essentially a bunch of useless work, and it appears to really speed things up by making sure we only actually touch the DOM every 16ms, instead of constantly. I'd imagine a Backbone integration with React would get us even closer. I'm not sure if it actually makes sense to go too far with an LM conversion as React appears to do a better job. But LM could certainly benefit from waiting until RAF.
- swannodette 13y agoI apologize that the Om TodoMVC version is a little bit buggy at the moment, I put it together mostly to demonstrate the benefits of the React/Om model and it appears I missed a couple of TodoMVC behavior issues as they weren't important for demonstrating the approach - I'll try to clean up these annoyances later this evening. Feel free to ask any questions.
- _sh 13y agoThanks for posting this. Forgive me for not looking over your code before asking: how does Om compare with Pedestal? Am I correct in thinking there is a lot of architecture overlap, with Pedestal's application state map occupying a similar role to React's virtual DOM, and mutation through message tuples in channels? Both frameworks seem to offer similar advantages: decoupled model and view, UI state playback (VCR style) and instrumentation. How significantly do these frameworks differ? Or are we seeing different paths towards a convergence around a new set of model/view practices?
- ludwigvan 13y agoYes, you are right, there are overlaps. Pedestal is undergoing a major rewrite these days, as I heard from the team at the ClojureConj. Also, Brenton Ashworth, Pedestal's developer has recently started investigating reactjs and found that it "perfectly complements the new version of Pedestal" (see his Twitter https://twitter.com/brentonashworth https://twitter.com/brentonashworth ) so exciting things to come!
- NVI 13y agohttp://swannodette.github.io/todomvc/labs/architecture-examples/om/app.js http://swannodette.github.io/todomvc/labs/architecture-examp... has "//# sourceMappingURL=app.js.map" but the file is missing.
- taybin 13y agoBut I just finished rewriting everything in angular!
- deleted 13y ago[deleted]
- rubiquity 13y agoWhat about long GC pauses and running for cleaning up all those wonderful immutable data structures? Immutability is great when it's at the forefront of how a language is designed. Plastering immutability all over hot code paths in a language that wasn't designed with immutability in mind isn't great.
- ibdknox 13y agoIn practice, unless you're animating at 60fps over hundreds of objects (and who would do that with dom elements?), you shouldn't run into any GC issues. LightTable uses ClojureScript datastructures for pretty much everything and there were only a small handful of cases we had to optimize. Any "normal" application probably won't ever have to.
- peterhunt 13y agoFor a little more color: these objects usually live in the new generation which I've observed doesn't drop frames even on mobile. You can pull this up on an iPhone 4S or newer (it uses the same technique with tons of allocations but doesn't really drop frames): http://petehunt.github.io/react-touch http://petehunt.github.io/react-touch
- girvo 13y agoExcuse my language, but holy shit that's awesome. I'm blown away by how... Native that feels, running on my 4S (iOS 7). 60fps the entire time. Jesus.
- peterhunt 13y agoThanks! The secret sauce is that you can animate CSS transforms every requestAnimationFrame without breaking out of React's natural data flow. So we declaratively express the UI as a function of a single float which represents the scroll position (i.e. how open/shut the nav is or what position in the photo viewer you're at). When we do that, we can use the excellent Zynga Scroller touch gesture physics engine (reverse engineered from iOS) to do the touch gesture stuff, then we can declaratively rotate, fade and translate everything as a function of this float. Code is on github! And is actually in a reusable library!
- bretthopper 13y agoThere's two big highlights for me: > Thus we don't need React operations like setState which exists to support both efficient subtree updating as well as good Object Oriented style. Subtree updating for Om starting from root is always lightning fast because we're just doing reference equality checks all the way down. I don't think anyone actually likes using explicit setters/getters in frameworks like Backbone and Ember. Of course Angular avoids it but that's by the crazy "dirty-checking". Obviously the new Object.observe will help this situation, but I love how simple Om/CLJS makes this. > This also means that Om UIs get undo for free. You can simply snapshot any state in memory and reinstate it whenever you like. It's memory efficient as ClojureScript data structures work by sharing structure. > VCR playback of UI state I can't wait for details on this. This has gotten me really excited about client-side apps again.
- DannoHung 13y agoAre there a lot of details to explain? An immutable data structure means that modifications to the structure tend to be memory cheap. So you save every instance you care about secure in the knowledge that it doesn't waste much space. Then to perform forward or backward operations, you just switch which version you're looking at.
- jaredly 13y agomaybe "details" is the wrong way to phrase it. I'm excited to see /a real world implementation/, either proving that it really is that simple, or showing what other complications arise.
- swannodette 13y agoI've already played around with some simple prototypes - it works as advertised. There'll be a future blog post showing how it can be done.
- porker 13y ago>> VCR playback of UI state > I can't wait for details on this. This has gotten me really excited about client-side apps again. Why? I'm curious what I'm missing about it and the possibilities you see?
- mtrimpe 13y agoI've been expecting this after seeing a few of your teaser tweets and as expected I absolute love it! I've been waiting for something like this ever since I read up on persistent data structures and functional reactive programming almost 10 years ago. I'm wondering how this compare to the Javelin library as that seems to offer the same functionality when combined with hlisp. Would I be correct in saying that Om achieves the same by using ClojureScript's data structures and core.async to offload the FRP part to React?
- swannodette 13y agoI haven't looked at Javelin enough to have a strong opinion about it. Om at the moment is completely focused on rendering EDN data and making that blazing fast. Personally I think representing UI components as generic data has a lot of legs. I also don't really believe in templating languages, but I also think that functional boilerplate for rendering children is a bummer. I'd like to see a client side query language modeled after Datomic's Datalog syntax instead.
- mtrimpe 13y agoI'll be diving into the source code soon to figure it out, but are you then using core.async only to handle incoming user events or also to coordinate the rendering of the UI?
- swannodette 13y agoWe just use React for events that update the state of the tree. For inter-component communication core.async seems promising.
- ibdknox 13y agoWe've been thinking about this a lot lately for some of the projects we've been doing for Light Table and we've essentially been doing the same thing as what David's proposing here. What react ultimately opens up is a way to do immediate mode UI [1] on top of the DOM _efficiently_, which changes things pretty dramatically. It means we can start to treat the browser as just a renderer and get the infectious design decisions of the DOM out of our programs. If nothing else, this gives us freedom, but as david is suggesting, I think this also gives us an opportunity to treat UI much more directly than we currently are. If you want to know what the state of your UI is, you just have to read linearly down through the code that produces your tree. No nest of dependencies, no state hidden in the UI components, you could even get rid of event hierarchies if you wanted. More important than anything else, this gives us a chance to dramatically simplify our model for UI and magically be even faster than we were before. Sounds like a win to me. [1]: http://en.wikipedia.org/wiki/Immediate_mode http://en.wikipedia.org/wiki/Immediate_mode
- cia_plant 13y agoIf you want to do immediate mode, then why would you use the DOM at all? Canvas is supported in IE9+, and is much less complicated for such applications.
- deleted 13y ago[deleted]
- lazerwalker 13y agoThere are many cases (e.g. accessibility for people using screen readers) where having your web site be a machine-parseable document is very valuable. There are cases where using Canvas for everything makes sense, but having it be the default feels like a step back in many respects.
- mtrimpe 13y agoBecause there are millions of developers who can use the DOM and CSS to create their design and only a handful who can do the same with Canvas.
- wheaties 13y agoBeen playing around with RxJs and wonder how much difficulty would it be to combine React with this? RxJs seems to work particularly well with Angular but I know Back one much better. is there harmony between the two?
- dmak 13y agoI think it really depends on what you are trying to accomplish. For one thing, a quick peak into React revealed to me that there isn't two-way data binding. I think React and Angular have a lot of friction. They both seem to do well with data binding in their respective ecosystems.
- peterhunt 13y agoOur (React core) team has experimented with React+RxJS before: https://github.com/facebook/react-page/commit/082a049d2a13b14199a13394dfb1cb8362c0768a https://github.com/facebook/react-page/commit/082a049d2a13b1... We think that "two-way binding" is actually very, very hard to get right since it flies in the face of the way data flows in a von Neumann program. Instead, we provide some sugar that lets you get the conciseness of two-way binding but without making it hard to debug or understand performance: http://facebook.github.io/react/docs/two-way-binding-helpers.html http://facebook.github.io/react/docs/two-way-binding-helpers... But we don't really recommend that for newbies since it's important to understand how the data flows in your program before covering it up with sugar.
- sebmarkbage 13y agoReact exposes event handlers and setState methods which are seemly mutable and Object Oriented. This is because React is designed for large scale organizations and to be approachable by a broad developer base. However, once you have certainly complexity in your asynchronous flow, RxJS is a great way to express that. The interesting part of our experiments (which we designed together with Erik Meijer) can be found here: https://github.com/facebook/react-page/blob/082a049d2a13b14199a13394dfb1cb8362c0768a/src/elements/VectorWidget/VectorWidget.js#L39-L89 https://github.com/facebook/react-page/blob/082a049d2a13b141... RxJS makes it easy to create abstractions from complex pieces of your async flow. The getStreams method in that example could easily be broken apart into multiple pieces. This fits very well into the React model and is definitely a great compliment if your organization is already familiar with Rx.
- puppetmaster3 13y agoLol, why can't it be just another FW that's not MVC? We can't evolve? Games don't use MVC, they use E/S. There is more than that pattern. Also when using API, you need something better.
- hderms 13y agoWhat's E/S?
- jamii 13y agoI'm guessing he means http://en.wikipedia.org/wiki/Entity_component_system http://en.wikipedia.org/wiki/Entity_component_system While some big games have used it, a lot more games are still stuck on class hierarchies.
- munificent 13y agoThose aren't orthogonal. There's a pretty wide design space for component systems. Lots of games use "components", where game entities are split into pieces for different game domains (rendering, AI, etc) without going all the way down the entities/components/systems path. It is true that most games don't use MVC. I think that's because MVC isn't a good fit for games. It seems to work fine for business apps, though more experimentation is always good.
- peterhunt 13y agoI think swannodette's post is less about MVC and more about declarative manipulation of the DOM. As long as you have a function somewhere that creates that representation and a way of handling events you can use any sort of architecture you want.
- phillmv 13y agoThe web's headed that way as well, we just call them services. That said, I'm not sure why MVC is inappropriate for component intra architecture. I love how different programming communities never talk to each other.
- avolcano 13y agoThe title of this post is strange. This seems more like the future of JavaScript views than the future of models or controllers. I don't see a large movement to immutable data structures on the horizon in JS. I can appreciate the performance implications in Om, and would be interested in using React + Mori to the same end, but I'm not sure that it would keep me from having mutable data structures to represent most of my application state. There are so many now-solved problems in JS MVCs that were a complete trainwreck several years ago - client-side routing, sanely managing data, and intelligently organizing your code base - that all assume mutable data structures and traditional object-oriented paradigms. This might be the future of ClojureScript (in fact, it should be the future of CLJS, as it's much more elegant than any other view solution I've seen for it), and functional data structures may be a clever way to optimize the DOM, but this certainly doesn't seem like the future of JavaScript to me.
- swannodette 13y agoReact is used by Facebook and Instagram and many others - I think these companies know a thing or two about scaling rich complex client side applications. React + immutable data has been used by Facebook to get order of magnitude performance enhancements. So I dunno, seems like it might catch on eventually ;)
- phillmv 13y ago> scaling rich complex client side applications. Instagram's really not a good example here. Do comments and likes even update in real time?
- eliseumds 13y agoI think Instagram is not a good example too, but could you please provide the name of a project as big as Facebook (or better, 10% of it) using AngularJS?
- jaredly 13y agoI can imagine client-side routing, sane data management, and intelligent code base organization all without mutating the data of your state. Granted, JS won't move to immutable data structures, but React encourages you to treat your states as immutable, which leads to lots of benefits.
- EvilTrout 13y ago> Om never does any work it doesn't have to: data, views and control logic are not tied together. If data changes we never immediately trigger a re-render - we simply schedule a render of the data via requestAnimationFrame. Ember.js has done this since day one with the Run Loop. Additionally it allows to coalesce operations yourself if you need control. Angular also would not update the DOM as many times as the backbone example as it uses dirty checking to get around this problem.
- avolcano 13y agoYeah, I think it's rather misleading to compare om to the performance of the least optimized and most naive (on purpose, mind you) framework instead of a more robust one.
- programnature 13y agoThere are benchmarks comparing vanilla React to other frameworks: http://facebook.github.io/react/blog/#todomvc-benchmarks http://facebook.github.io/react/blog/#todomvc-benchmarks At least according to this data, React and Backbone are the fastest. (Om is faster than vanilla React) One suspects that with hand-optimization the other frameworks could be a lot faster, but the point of this post is that it is fast without hand-optimizations.
- peterhunt 13y agoKeep in mind that those benchmarks don't use the requestAnimationFrame() batching strategy (out-of-the-box it's not installed since it makes testing harder since you have to wait for the next frame) like swannodette mentions. I'd be interested to see these numbers after doing `npm install react-raf-batching` and doing `require('react-raf-batching').install()`.
- esailija 13y agoIn general "faster without optimization" is completely meaningless because it doesn't mean fast with optimization, which is what actually matters. Example: Average code written in node.js is typically just as slow as, say, PHP (in fact node.js was 3x slower than php in techempower benchmarks). However, it has potential to be much faster when optimized whereas PHP doesn't reward such optimization almost at all.
- drcode 13y agoI know it sounds crazy, but I think your post just outlined the next 5 years of web development innovation, swannodette- This ties together a lot of ideas that are extremely important, for the first time in one place. Thanks for doing this. I already have my own React.js+Clojurscript bridge for personal projects, because I think it's an extremely powerful web dev combination. I'm glad I can finally abandon my own library for Om!
- swannodette 13y agoGreat to hear, it needs more work :) It's more or less a conceptual foundation at this point, but I think it's going to rock with help from the community. BTW, it was your React mailing lists posts that also really got me digging into this.
- bguthrie 13y agoI agree––I've found this tremendously exciting. Thanks @swannodette for the code and the writeup.
- chrisege 13y agoNot to take away from the other points in your post, but on the benchmarks, the backbone example is writing to localStorage, while the om example isn't. The overhead from localStorage appears to account for a significant chunk of the difference in performance. You can remove the localStorage calls with 'Backbone.sync = $.noop' or similar. After doing that and clearing localStorage, benchmark one drops to around 350ms, and benchmark 2 drops to around 2000ms. Of course, benchmark 2 is where your library really shines, and backbone still takes its time with that one.
- swannodette 13y agoNot true, all Om timing information includes writing to localStorage. I just don't load the page from localStorage because that made benchmarking tedious for me.
- chrisege 13y agoMy mistake - i see that now. I think I lost sight of the single key for your example in with the hundreds of distinct keys from the backbone one.
- invalidOrTaken 13y agoThis is fantastic. I've been goofing around trying to figure out a way to approach the general case (representing an interactive DOM with just EDN), but I hadn't done jack on performance. Thank you thank you David.
- jordwalke 13y agoJordan, from the React core developer team here. Awesome post, swannodette! This is exactly how we intended React to be used. As swannodette said, at Facebook, we use persistent data structures, in order to prune the update search space for comment updates. We've seen as much as a 10x improvement in update speed for certain operations. React is a really great fit for Om, persistent data structures, and functional programming in the following ways: 1. We want to allow developers to elegantly describe their user interface at any point in time, as a pure-as-possible function of data dependencies. 2. We allow hooks for your system to help guide the updating process along. These hooks are not necessary. Often, we'll add optimizations long after we ship. We strongly believe that perf optimizing shouldn't get in the way of writing code elegantly and shouldn't get in the way of the creative development process and actually shipping to your users. At the same time, performance matters - a lot. So we ensure that at any point in the update process, if you know better than the framework, you can help guide the system. The fact that this is optional and doesn't change the functionality or correctness of the system is critical. Persistent data structures are an excellent (likely the very best) way to hook into the update system without making the developer do anything special. Some people here were wondering about the apparent OO influence in React. Here's how I personally think of React's OO support/influence: 1. It's there to help you bridge with other existing mutative, stateful libraries in your stack - you know you have them. The DOM falls into this category as well. 2. It's there when you want to treat state as an implementation detail of a subcomponent. This is only because we don't have a good way of externalizing state changes, while simultaneously keeping the nature of them private. We just need more people to think about it (I'm sure the ClojureScript community can help us chew on this). Our internal motto is to keep things as stateless as possible. 3. A lot of the OO support in React is there as a concession, more than being considered a virtue. It's really cool to have the FP community involved in the UI space. Those people are already sold on FP and statelessness and get the luxury of programming in tomorrow's paradigms today (how ironic that FP has been around for decades!) To accelerate this momentum, we also want to reach out to people who aren't yet sold and change how they think about building UIs and software in general. The most effective way to do this is to reach out to them where they stand today, on some middle ground. It's really great to see eyes light up when they see that they can use simple functional composition in order to build large, sophisticated apps. We're really glad to have swannodette and the ClojureScript community checking out React (github.com/facebook/react). We should consider adding some level of support for persistent data structures in the React core. Let us know if there's anything we can do to help.
- asolove 13y agoOm looks very interesting and seems to handle exactly what I've been looking for. We have reactive widgets, which is great for making changes in the data automatically update the UI. But the hard part is closing the loop: how does the widget communicate back to the data about changes? It would be interesting if we had a zipper-like abstraction, so that the widget gets handed both its data and a function to call when it wants to change just its data. Then that function is smart enough to go find the right place in the big data structure to go do the replace. Edit: Ok, I now see how the Om todo example is handling update, and it's really cool. It creates a set of channels that encapsulate the knowledge of how to handle each type of change to a todo [0]. That gets passed in to the todo widget as "chans" and the widget sends messages to it in its event handlers [1]. I wonder if this whole channel CRUD abstraction is general enough to make it part of Om or another layer so that it didn't have to be recreated each time. [0] https://github.com/swannodette/todomvc/blob/gh-pages/labs/architecture-examples/om/src/todomvc/app.cljs#L106 https://github.com/swannodette/todomvc/blob/gh-pages/labs/ar... [1] https://github.com/swannodette/todomvc/blob/om/labs/architecture-examples/om/src/todomvc/item.cljs#L40 https://github.com/swannodette/todomvc/blob/om/labs/architec...
- dustingetz 13y ago> so that the widget gets handed both its data and a function to call when it wants to change just its data this is precisely how React works.
- asolove 13y agoYeah, took me a second to wrap my head around the Om todo code. I've updated my comment with links to show how it works.
- malandrew 13y agoFor zippers, check out this library: https://github.com/dyoo/js-tree-cursor https://github.com/dyoo/js-tree-cursor
- jarpineh 13y agoThis is like a dream coming true. I don't like Javascript's quirks, nor programming DOM with templates nor functions. I'm looking to build somewhat complex UIs without having to think in JS and manage state. React absolves me from DOM and ClojureScript keeps JS at bay. Only if starting ClojureScript development wasn't so hard. I'd like to use browser REPL, IDE like LightTable. I am used to LiveReload's speed which makes loading changes instantaneous. But ClojureScript compiling seems to be still slow(ish) and I have already found half a dozen of different cljsbuild configuration examples. Compiling simple cljs files can take anything from sub second to 20 secs, and I don't understand why. Could you perhaps tell more about your development process, Swannodette? How do you develop ClojureScript apps? I don't see anything beyond base cljsbuild in Om's project.clj. I confess I haven't yet had time to play with Om and see how fast it can be compiled.
- swannodette 13y agoThe first build of ClojureScript app is somewhat slow because we need boot the JVM, compile ClojureScript, and then analyze and compile your code. After the first compile it should be sub second. I always use the auto build mode and when I'm developing I don't use any optimizations. Works well enough for me. I'd start with this, http://swannodette.github.io/2013/10/27/the-essence-of-clojurescript/ http://swannodette.github.io/2013/10/27/the-essence-of-cloju...
- jarpineh 13y agoThank you, yours is what I tried first and it's definitely fastest, sub second after first compile. However there is no REPL like cljs-start and couple of others I tested have. Between cljsbuild, Austin and LightTable I haven't yet found a stable and fast solution yet. I'll try adding these various REPLS to your example and see what happens. External browser with REPL inside LightTable seems easiest for a noob like me. Unfortunately LT doesn't support that use case yet, and you can't use Chrome debugger inside it. I still need to see what the browser thinks is happening and not just the ClojureScript's side. I did manage to get React + JSX, CoffeeScript and ClojureScript + bREPL working with LiveReload, in a single page app. That felt truly powerful.
- programminggeek 13y agoThere was a really good talk from Charles Nutter about making JRuby fast and the mutable things that Ruby does that basically break caching and things that you do to make things faster at runtime. I'm not surprised that persistent data structures can make things fast, in fact I've spent the last week speeding up a Rails app in some ugly spots by preloading the data structures to keep DB queries from happening, effectively turning a lot of just in time queries at the ORM level into a pre-loaded data graph. The speed is fantastic, but what is interesting is you could add a level of immutability to this and would be potentially even faster, especially on top of the JVM. I've been playing with the idea of immutable entities in Obvious Architecture for a while and it really changes the way you look at your business logic and performance.
- d_j_s 13y agoSo I rewrote Backbone views to use a queue system that fires on requestAnimationFrame -https://github.com/danshearmur/backbone-fast-view https://github.com/danshearmur/backbone-fast-view I'm getting pretty good results with swannodette's benchmarks - http://danshearmur.github.io/backbone-fast-view/ http://danshearmur.github.io/backbone-fast-view/ I'm getting approx 150ms in Chrome for benchmark 1 and about 400 ms for Chrome for benchmark 2
- swannodette 13y agoAbout what I'd expect for the first benchmark, but that's the kind of intervention from the user that I think frameworks should not require. The time still spent by Backbone.js on the second one more or less illustrates why I don't believe in event oriented MVCs.
- rtfeldman 13y agoThis kind of thing is exactly what makes me think CLJS is the current frontrunner to be the first compile-to-JS language to gain mass adoption without JS-like semantics (as CoffeeScript has). It's the performance. So many of us who want JS alternatives have made our peace with the idea that we'll have to sacrifice a bit of performance if we want to use a nice language. But being able to improve performance while using a nicer one?! Count me in! I already have a serious project in mind for this.
- TheHydroImpulse 13y agoFor me, the non-idiomatic compiled JavaScript and Google's library that's stopping me. Wisp seems like a good solution with it being a Clojure dialect that provides super clean JavaScript that you can work with.
- john2x 13y agoI'm really excited about this. Until now I've hated working with Javascript because of a combination of the language itself, and its primary domain (the DOM). Seeing React.js at JSConf.asia last month got me excited that I don't have to touch the DOM anymore, but I still had to deal with Javascript the language itself. And now this comes along. Now I don't have to deal with DOM (or at least it offers better abstractions for working with it) and I get to use the most pleasant language I've tried so far. Christmas came early. :)
- gfodor 13y agoThis is really cool, and I am one of those people who rolls their eyes whenever there is another article about some newfangled way to build Javascript apps on HN. One logical step from here is instead of having a one-to-one correspondence between the "virtual" DOM and the browser DOM is to introduce a higher level meta representation based upon the context. This seems like a logical path towards a generative, projectional approach to controlling UI and browser document rendering in general. It's been tried before in several contexts and the hacks I've tried myself have always been to hard to get my head around since it's a complex problem, but this seems like it could be a really decent foothold to build a projectional, transform-based paradigm. For example, having a meta-DOM that encodes mathematical notation (probably inspired by LaTeX), which gets transformed into the current virtual DOM, which is used to update the real DOM. User manipulates a integral on screen, and the downstream transformations are performed lazily and efficiently all the way to the screen. This type of lazy evaluation from document to screen is essentially the core challenge (from a engineering standpoint) in building a usable real-time projectional editor like that demonstrated by intentional software back in 2010 [1]. [1] http://www.infoq.com/presentations/Intentional-Software-at-Work http://www.infoq.com/presentations/Intentional-Software-at-W...
- peterhunt 13y agoThat's exactly what we encourage :) composition of higher level components that render down to other high level components that eventually render to (virtual) DOM.
- jarpineh 13y agoI wonder if this approach would work with visual XML (Docbook) and HTML editing, where resulting DOM can be complex and large. Competent writer might generate loads of input (writing 100 letters per minute, copy-paste). If my writing tool has latencies, that annoys me far more than game latency. Other approach I have been testing is contenteditable, but this won't work with virtual DOM at all. Though how you parse an existing XML document to React's virtual DOM is beyond me. Perhaps you have to generate function calls SAX style.
- brosco45 13y agoAngularJS
- _pmf_ 13y agoOn another note: maybe if the installation of ClojureScript would be manageable in, say, an hours instead of having to search half a day among outdated information, more people would try it (and this is from someone who already uses Clojure and Leiningen a bit). Clojure and its libraries has the worst documentation, and this malpractice seems to be continued in ClojureScript.
- chc 13y agoIt's as easy as "lein new mies". Hard to get much easier.
- davedx 13y agoI had a few teething problems getting it configured properly, but I managed to get ClojureScript working from scratch on a Windows machine in about an hour, I think. What problems did you have? (Mine were Java related)
- danneu 13y agohttps://github.com/magomimmo/modern-cljs https://github.com/magomimmo/modern-cljs is how I got started with Cljs. If you scroll down, you'll see some tutorials that get you set up and lead you to a workflow. http://swannodette.github.io/2013/10/27/the-essence-of-clojurescript/ http://swannodette.github.io/2013/10/27/the-essence-of-cloju...
- jlehman 13y agoI spent the day working out the React tutorial in Om. It was an enlightening process. Code: https://github.com/jalehman/react-tutorial-om https://github.com/jalehman/react-tutorial-om
- dgreensp 13y agoI've been watching Clojure for a while, and I love the spirit of this work. However, as a framework author, I feel obliged to point out that of course you can create a more expressive and performant UI framework in a language with S-expressions, macros, and value semantics. What's hard is doing it in JavaScript. :) It also feels a bit like reverse logic to cite ever-faster JavaScript VMs as a reason to choose a new framework for performance reasons -- shouldn't it matter less exactly how you structure your application logic when you're running on a "fusion reactor"? -- but I realize there's some subtlety here about lower constants enabling better algorithms. (Still, if your framework includes a language compiler or gets to take advantage of an expressive macro system, it should be able to run on anything.) Once it's possible to compile ClojureScript without booting up a JVM -- which could happen if it becomes self-hosting -- I'll make a Meteor package for it. I'd also like to see the compile times get a little shorter and the runtime library get a little smaller.
- rads 13y agoThe main features David talks about in the post are available in vanilla JavaScript: > If you're a JavaScript developer, I think taking a hard look at React is a really good idea. I think in the future, coupling React with a persistent data structure library like mori could bring JS applications all the way to the type of flexible yet highly-tuned architecture that Om delivers. I think there are a couple reasons Mori and other libraries like it haven't caught on in the JS mainstream: 1. It's clunky to use them in vanilla JS compared to the default mutable objects and arrays. While you gain simpler semantics, the code becomes harder to read, and that tradeoff isn't always worth it. 2. Most JS developers are not experienced with building programs around immutable values.
- phineas 13y agowould you mind simply explaining a little more what an immutable value is? I Understand immutable as something that cannot be changed. > all of our collections are immutable How can a collection which is data that eventually ties into a db be unchangeable?
- 13y ago
- secoif 13y agoThe flame graphs are meaningless and misleading: om's graph is only looking at 260ms of data, while the backbone's is looking at 1200ms.
- STRML 13y agoBut that's the whole point; it's effectively the same operation, but Om takes 1/5 the time and takes a much more efficient path. Backbone with some simple RequestAnimationFrame deferral somewhat approaches that speed but in some cases Om still beats it by an order of magnitude.
- secoif 13y agogotcha. understood.
- jpatte 13y agoIt may be because I'm not familiar with ClojureScript's syntax, but the whole sample application code seems like a real mess to me. It's full of boilerplate code and it is happily mixing application logic with DOM rendering. [1] Compare this with an alternative JS MVC framework (like, say, Knockout.js) and another modern "javascript-compatible" language (like, say, TypeScript), and see for yourself. [2] While I didn't run any benchmarks, it's safe to assume the Om demo is faster. However which sample do you think is easier to write, test and maintain? If "The Future of JavaScript MVC Frameworks" is supposed to look like the Om sample, sorry but I'll pass. [1]: https://github.com/swannodette/todomvc/tree/gh-pages/labs/architecture-examples/om/src/todomvc https://github.com/swannodette/todomvc/tree/gh-pages/labs/ar... [2]: https://github.com/jpatte/TodoMvc-Knockout.ts https://github.com/jpatte/TodoMvc-Knockout.ts
- lucian1900 13y agoI don't see how language has anything to do with you criticism.
- jpatte 13y agoIt's not really about a choice of language. My point is that if Om claims to be superior to other JS MVC frameworks - as it is presented as "the future of MVC frameworks" - it needs to be good (if not superior) in many aspects. Performance is a big deal all right, but another aspect (which seems essential to me) is that using this framework should be easy, concise and intuitive. And I've been kinda disappointed to see that the sample code given to present Om in action is not. At all. If I wanted to fiddle a bit with this code right now, to add a few features for example (like adding a timestamp besides each item indicating when it was created), I wouldn't have any clue where to start. What bothers me is that Om has clearly been written with ClojureScript in mind, so in a way this framework is supposed to be sublimated by the language. It should "feel" right. And I know it's possible with other frameworks (and my comparison with Knockout+TypeScript was meant to illustrate that), so I expected it to be the case with Om.
- drcode 13y ago
- rgbrgb 13y agoIs there any reason we couldn't mod the JQuery object to work on a virtual HTML tree that syncs with the DOM on requestAnimationFrame? Couldn't this even be done at the browser level? I think I must be missing something.
- drcode 13y agoThat wouldn't change the amount of DOM thrashing caused by jQuery, it would only improve rendering (and perhaps reflow) performance, but would not improve the cost of DOM manipulation.
- rgbrgb 13y agoCan you expand on that a bit? As I understand it, om/react don't improve the cost of DOM manipulation, they just reduce the amount of DOM manipulation that's done by only altering parts of the DOM that have changed. Couldn't you do the same type of change checking on the virtual DOM tree so that you only touch the actual DOM when it changes?
- drcode 13y agoI see, yes viewed that way you COULD do this with jQuery- But you'd be missing most of the benefits of react.js, due to the missing "functional programming" that is possible with the react.js approach.
- dylnclrk 13y agoNeat, first time I've seen Computer Modern outside of a TeX'd pdf. It looks quite nice on your site. Also... an interesting read, thank you :)