27 ms·
Ractive.js
- boothead 13y agoNice - looks very simple and lightweight! I especially like the effort put into the interactive tutorial documentation that these frameworks have. Angular and knockout both had stand out docs too! Is there a particular niche for this framework would you say e.g. small, fast to market apps like news stories - or is is suitable for larger projects where you might normally reach for more of a "framework"?
- rich_harris 13y agoLibrary author here - thanks! The interactive tutorials borrow very heavily from Knockout (in fact Knockout was a big source of inspiration all round). It was initially designed to scratch my own itch - I'm a newsroom developer at the Guardian, where we turn around projects with fairly tight deadlines, so I guess you could say it's optimised for that. (Blog post here: http://www.guardian.co.uk/info/developer-blog/2013/jul/24/ractive-js-next-generation-dom-manipulation http://www.guardian.co.uk/info/developer-blog/2013/jul/24/ra...) In particular I wanted an API that wouldn't be completely mysterious to journalists who are starting to dabble with code. There's actually a separate discussion on Ractive at https://news.ycombinator.com/item?id=6096545 https://news.ycombinator.com/item?id=6096545 - I'm not sure what the HN etiquette is, can anyone enlighten me? (I appreciate both submissions though!)
- boothead 13y agoI've had a look at the last slide now - I think the transitions could use a little work. With that in mind - how hard would it be to integrate with d3 do you think?
- rich_harris 13y agoYes, that slide is still a bit of a work in progress. You can certainly use D3 (or any other library) alongside Ractive, though things could go awry if two libraries were trying to manipulate the same bit of the page at the same time - e.g. if an element has a style attribute like style='left: {{left}}px;' and D3 modifies the element's style, D3's changes will only last until the value of {{left}} is updated.
- ganarajpr 13y agoSo what is ractive.js's equivalent of $scope.$apply ? $scope.$apply is used for this specific purpose, to notify angular of any external changes.
- rich_harris 13y ago$scope.$apply is necessary because sometimes changes to the model happen outside Angular's event loop. Ractive doesn't have this issue because updates always happen explicitly with ractive.set( 'key', value ) (or with array mutator methods). It's not quite as magical as Angular's frictionless updates, but it gives you slightly more control (e.g. you can do ractive.animate( 'key', value ) and so on), without needing to inherit from custom observable classes.
- wiremine 13y ago+1 on the tutorials: came to comment just on that. The layout is solid, and the content is paced well.
- SkyMarshal 13y agoIt's "Ractive.js", not "Reactive.js".
- rich_harris 13y agoIndeed - as in 'interactive'. Got the name from Neal Stephenson's The Diamond Age, in case anyone wondered... Though it is also reactive, in the 'reactive programming' sense.
- oh_sigh 13y agoI think this person was responding to the fact that the title of this article on HN is "Reactive.js" and not "Ractive.js"
- SkyMarshal 13y agoYup, but glad to know where "ractive" came from too.
- SkyMarshal 13y agoEdit: Question answered in the other thread: https://news.ycombinator.com/item?id=6096660 https://news.ycombinator.com/item?id=6096660 I haven't dug into it yet, but from the description it reminds me a bit of Facebook/Instagram's React js framework [1]. React creates a lightweight model of the DOM in memory, and when any part is changed, it sends a diff to update the browser DOM. No bindings necessary: "When your component is first initialized, the render method is called, generating a lightweight representation of your view. From that representation, a string of markup is produced, and injected into the document. When your data changes, the render method is called again. In order to perform updates as efficiently as possible, we diff the return value from the previous call to render with the new one, and generate a minimal set of changes to be applied to the DOM." Your description is similar, but it's not clear how exactly the update is made: "In this example, Ractive.js constructs a parallel DOM representation which is aware of its dependencies on the values of user and messages.unread. When those values change, it knows exactly which parts of the real DOM need to be updated. This kind of surgical DOM manipulation is more efficient than constantly trashing views only to re-render them, and it scales far more elegantly than manually updating elements." How does the DOM update mechanism work? [1]: http://facebook.github.io/react/blog/2013/06/05/why-react.html http://facebook.github.io/react/blog/2013/06/05/why-react.ht...
- smagch 13y agoIts naming is a bit conflicting to component/reactive. The name "reactive" is so presumable that other people will choose in the future. https://github.com/component/reactive https://github.com/component/reactive I haven't looked into Rivet.js, component/reactive or other equivalent library. I'm just planning to research which library is the best fit for me. I don't really like full-stack framework like Angular. It was nice to know yet another candidate. Does anyone know any other reactive template engine?
- tlrobinson 13y agoThe name is actually "Ractive" I like Knockout.js
- smagch 13y agoAh, "Ractive". Shame on my eye.
- tlrobinson 13y agoIt wasn't your eye, the title was wrong for awhile!
- jonahx 13y agoHi Rich, This looks promising. Can you comment on similarities/differences between Ractive and facebook's React.js in terms of style and performance? Also, looks like the github minified version is 72k, is that correct?
- rich_harris 13y agoThanks. Performance-wise, I haven't tested Ractive and React against each other, but that would be a test worth doing. Ractive is definitely built with performance in mind - it uses dependency tracking to ensure that the DOM is only updated when necessary. As far as the style goes, I'm obviously biased, and I'd encourage people to try both to see what suits them best. For me, mustache syntax is very readable, even by non-devs (which makes collaboration and rapid prototyping very easy), and the Ractive API aims to be as easy as possible. I find React's JSX to be a bit of a barrier (I'm aware that it's not essential to use JSX with React), but as I say it's a matter of personal preference. Yes, it's currently about that size (27k gzipped) - one of my goals for future versions is to try and wrangle that down. It's not that big a library for the amount of functionality it contains, but smaller is always better.
- peterhunt 13y agoHey there! I'm on the FB/IG React core team. Syntax differences aside, seems to me that React is geared more towards interactive UI components and Ractive is oriented more towards reactive documents, kind of like Tangle[1]. Is this accurate? The similarity seems to be in the philosophy of the implementation (manipulating a fast representation and rendering to the DOM). It's pretty cool to see that we both discovered the "secret" though :) Seems like we're validating each others' projects! If you ever want to nerd out we hang out in #reactjs on freenode. [1] http://worrydream.com/Tangle/ http://worrydream.com/Tangle/
- rich_harris 13y agoHi! Yes, I was excited when React came out because it demonstrated that I wasn't the only one who felt that these problems hadn't been fully solved yet (though a part of me thought 'well I may as well give up now...'), Yes, you could draw the Tangle comparison, though I think there's probably a fair amount of overlap - a couple of the Ractive examples are recreations of React/Angular demonstrations. Looking forward to spending some more time with the React source code to try and learn your secrets!
- rubiquity 13y agoSo it's data binding + templating? Why would I use this over something like Rivets.js?
- rich_harris 13y agoData-binding is the most obvious feature of Ractive but there are others - easier event handling, transitions, animations, JavaScript-ish expressions within templates, server-side parsing and HTML rendering, and so on. On the other hand, Rivets is much smaller, so if you only want the data-binding then it's a fine choice. Personally I really enjoy the freedom of writing mustaches straight into my template, rather than using data-bind attributes everywhere, but it's horses for courses.
- GMFlash 13y agoRivets.js can do mustache-style templating too: https://github.com/mikeric/rivets/pull/182 https://github.com/mikeric/rivets/pull/182
- Narretz 13y agoSounds like a cool alternative to angularjs when you can't use or don't need a full-blown framework with routing, http layer etc.
- nkerkin 13y agoJust to clarify, you don't need to use routing/http/etc to get the benefits of Angulars DOM binding.
- alphonse23 13y agoanother frontend framework for Dom manipulation, so would this be the 50th one out there on the web?
- invalidOrTaken 13y agoYes, and you better hope 50 more come out. Early adopters do your shit work for you. "______.js is picking up speed" is code for "Thousands of hours of unpaid labor have gone into making better tools for you, and evaluating them against other tools."
- SkyMarshal 13y agoThink of it as the Cambrian Explosion for code. Evolutionary processes occur outside of biology too. https://en.wikipedia.org/wiki/Cambrian_explosion https://en.wikipedia.org/wiki/Cambrian_explosion This is how most major advancements in human civilization occur, not in bio/techno/etc monocultures. Don't forget to thank Stallman and early FOSS advocates.
- scottmessinger 13y agoI like it's elegance, but it looks seems similar to using an Ember.js view and Handlebars templates. http://j.mp/reactiveinember http://j.mp/reactiveinember
- nilliams 13y agoThanks for that example, very handy (currently learning Ember) and illustrative w.r.t. Ractive.
- rich_harris 13y agoThanks, this is an interesting example. I'm not wild about the extra DOM it creates (the placeholder <script> tags, etc) but I'm intrigued about what's going on under the hood - will poke around the source code.
- skore 13y agoVery interesting, but one thing Re: AngularJS > dependency injection minification headaches Meh, that's hand-wavy at best. The only thing you have to do to pass minification is to include the injected dependencies in an array like so: ['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) { // Stuff }] You get used to it in seconds and then it's not really an issue anymore.
- rolandboon 13y agoOr if you're already in the process of minification you can also fix these injections automatically, with a simple regex or https://github.com/btford/ngmin https://github.com/btford/ngmin.
- skore 13y agoThere is also this direct integration for IntelliJ/WebStorm/PHPStorm: http://www.youtube.com/watch?v=ZvWftlp7TKY http://www.youtube.com/watch?v=ZvWftlp7TKY
- nailer 13y agopersonally, I already have a massive library of AMD modules, using a second module system, even if it adds a feature is confusing for people who join the project and makes for ugly code. Also I don't like having to organize unrelated code into factories and services just because that's how Angular wants to view the world.
- tbranyen 13y agoI'm currently using this style in a RequireJS/Angular project. Everything works great, but it's pretty ugly. We should strive to not write ugly shit, but good clean expressive code. This is so non-standard it hurts. There are plenty of other ways the Angular team could have gone; CommonJS or AMD would have been better choices IMO.
- likeclockwork 13y agoUse ngmin, it converts into the ugly style. https://github.com/btford/ngmin https://github.com/btford/ngmin There's also a grunt plugin. https://github.com/btford/grunt-ngmin https://github.com/btford/grunt-ngmin
- usethis 13y ago@rich_harris: 1. Great library, thanks for contributing! 2. What was your motivation to add transitions and animations, isn't that a bit out of scope? 3. I has no dependencies, why did you choose not to?
- rich_harris 13y ago1. Thanks! 2. Not at all - animation is something I need in my day job all the time, and having .animate() saves me so much time. I wasn't sure if I'd get much use out of transitions (I was jealous of ng-animate and wanted to see if I could implement something similar!) but I've found them very useful. Transitions probably need a bit more work though. 3. It just doesn't need any. The amount of code I could save by using a helper library like Underscore wouldn't be worth the potential extra hassle of version headaches etc. Personally I much prefer using 'fire and forget' libraries with no dependencies.
- ghostdiver 13y agothat is false statement actually HTML is an amazing language for creating static documents, but it was never designed for interactive web apps
- andrewvc 13y agoOut of curiosity, where's the love for knockout? It's mature, and works well, but gets no press anymore.
- dustingetz 13y agoKnockout and Ractive take opposite approaches to managing the DOM. There is value in understanding all approaches and then choosing the best fit.
- emn13 13y agoThey do? It looks superficially similar to me anyhow. What's the difference? I mean, the syntax is different, but unlike other templating systems they try to be "smart" about what needs rerendering by tracking dependencies.
- scott_karana 13y agoThere's actually an aside in the article that specifically thanks Knockdown.js and Backbone.js for their contributions :)
- rich_harris 13y agoAbsolutely! We're all standing on the shoulders of giants like Steve Sanderson (KO creator).
- stoodder 13y agoI've got a library called Falcon.js (https://github.com/stoodder/falconjs https://github.com/stoodder/falconjs) that essentially provides a Model, Collection, View framework on top of Knockout that I've been using for over a year now on internal and client projects. It works really well for single page and mobile web hybrid apps, it's completely unit tested, and I'm currently in the works of getting the documentation finished up. It's only dependency is jQuery and it comes bundled with Knockout 2.2.1 built in. Feel free to take a look at what I have so far, I'd love your feedback. Again, I apologize for the incomplete state of documentation at the moment but I promise everything'll be wrapped up sooner than later!
- Dekku 13y agoDoesn't seem to work in Firefox: "TypeError: templateBlock.innerText is undefined"
- rich_harris 13y agoThat's very odd - which version of FF are you using? From the error I'm guessing you saw this on the tutorial pages?
- ineedtosleep 13y agoSame for me on the homepage, messages.unread setter: Firefox Aurora 24.0a2 (2013-07-19) and 2013-07-20 TypeError: templateBlock.innerText is undefined @ http://www.ractivejs.org/:217 http://www.ractivejs.org/:217
- rich_harris 13y agoWell, that's embarrassing. Not sure how I missed that! Fixed now, as soon as GitHub pages updates. Thanks for the heads up
- Dekku 13y agoFirefox 22.0 but no version of Firefox ever had the innerText property. But yes, you're right, the problem is in the inline code, not in the library.
- deleted 13y ago[deleted]
- codereflection 13y agoWould be nice to see this up on http://todomvc.com/ http://todomvc.com/
- robotmay 13y agoI actually find that website almost entirely useless. A to-do list means nothing and demonstrates nothing useful. It has no associations between models and nothing particularly complex. I have tried so many of these frameworks and found crippling flaws in all of them, but on the surface they all look peachy when compared via a to-do app. It's pretty much only useful if you want to write a to-do app.
- beefsack 13y agoI completely disagree. I find it very useful to see small, easy to digest, and easy to compare example apps when new frameworks come out for a first impression to help decide if I want to have a play with it myself.
- mannix 13y agoI have a question, since this has been bugging me with other js MV* frameworks lately... Is the set() method necessary for updating single attribute? All browsers have supported getter/setter APIs (__defineGetter__ and Object.defineProperty), why not take advantage of them? Being able to say this would be cool: div.color = 'blue'; instead of: div.set({ color: 'blue' }); or div.set('color', 'blue'); Or would this cause other problems that I'm not thinking of? Edit: my ruby cap is on a little tight today. Javascript programmers might not expect extra logic to be run just by updating a property. I still think it would be cool though :)
- nailer 13y agoES5 specifically has Object.defineProperty. Which works on all current browsers and Node. Rich what do you think?
- plorkyeran 13y agoIE8 doesn't support it for non-DOM objects.
- mannix 13y agoCrap. you're right. that's probably a dealbreaker.
- mnemonik 13y agoMany of these frameworks want to support IE 8, which is the default browser of windows 7. IE 8 only supports Object.defineProperty with DOM objects[0], which can be infuriating. No one should use __defineGetter__ and __defineSetter__ because they are non-standard and deprecated[1]. [0] http://kangax.github.io/es5-compat-table/#define-property-ie-note http://kangax.github.io/es5-compat-table/#define-property-ie... [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineGetter https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... Edit: left this tab open and I see this point has since been made, but I will leave the comment anyways.
- 13y ago
- oakaz 13y agohow would you compare it to github.com/component/reactive ?
- nathansobo 13y agoThe examples for these kinds of frameworks always show you data binding for scalar values. That's easy. What's the story for more complex updates?
- rich_harris 13y agoRactive has a concept of 'expressions' - tutorial here: http://learn.ractivejs.org/#!/expressions/1 http://learn.ractivejs.org/#!/expressions/1 Hard to explain concisely but it allows fairly complex updates to be expressed very efficiently - see this animated chart for example. The path is created using an expression, which is reevaluated during animation and whenever the dimensions of the chart change: http://www.ractivejs.org/examples/animated-chart/ http://www.ractivejs.org/examples/animated-chart/
- seanmcdirmid 13y agoDeclarative data binding is intrinsically limited. If you want something that supports more complex updates, you need to start looking into things like incremental algorithms, self-adjusting computations, damage and repair, logged reversible effects, iterative processing methods, and so on. Say you want to write a compiler whose input is "bound" to a source file; when the input changes, you don't want to recompile the entire file all over again. Instead, you memoize at AST node boundaries, trace dependencies between AST nodes, and then "clean" nodes when they become dirty, detecting changes that affect other nodes to clean them also. To be honest, I find these data binding frameworks to be very boring, since we've been doing this forever (I did my dissertation on one myself). We really should be looking at the next level that supports incremental processing of more complicated updates.
- curveship 13y agoKnockout does incremental updates as well as memoization. It instruments the evaluation of computed observables to determine the dependency relationships. I haven't delved into Ractive.js closely, but it sounds like it does something similar. How is what they do different from what you're describing?
- xrd 13y agoCan someone comment on where to find performance information on this framework? AngularJS has some very smart ideas that allow it to be magical and performant. This looks very cool, and I would like to make sure it is not just polling for changes. I'm suspicious because there is no $apply required. :)
- rich_harris 13y agoDefinitely no polling! Model changes are done explicitly with ractive.set() (or ractive.animate(), or array mutator methods). It uses a dependency tracking mechanism to update the view with the fewest calculations and DOM touches necessary.
- CoryG89 13y agoIs there anyway to use any other templating system with Ractive other than the Mustache style syntax? Couldn't use microtemplates / EJS style templating for example?
- rich_harris 13y agoNo, Mustache only I'm afraid. The reason is that it's not actually using Mustache or any of the Mustache-based engines (such as Hogan.js) - it's using its own implementation. That's because almost all other templating engines are string -> string (i.e. you add data to a string template, and get HTML) whereas Ractive is string -> DOM. Microtemplates, EJS etc would have to be reimplemented as string -> DOM engines separately if they were to work with Ractive.
- CoryG89 13y agoSeems like that should be decoupled for this exact reason.
- rich_harris 13y agoMaybe one day ;-)
- d0m 13y agoI really like this library.. it's been a while I've been looking for something similar. Angular was a bit "too big" for some of my projects, and backbone was just too verbose. Something like this will let me keep the code clean while still not getting involved in a big framework.
- curveship 13y agoI like a lot of this, but one part I'm not so sure of is that, if I follow the docs, all get/set operations need to be from the root of the model. They take a "keypath" that starts at root, like "obj.get('subObj1.subArray[3].prop')". It seems to me like that would make it difficult to decompose a large application into component pieces. Your components, to do any get/set operations, would need to know their path from root. And what if that path changes, like an array that's modified? Seems like it could become a considerable barrier in mid-to-large applications.
- rich_harris 13y agoYou're right, all keypaths start from the root. One approach for large apps is to split the UI up into several Ractive instances (which might all be bound to a single global model, but 'start' at different keypaths). Array modifications aren't generally a problem, because you'd reference the index from within the template - Ractive keeps the references up to date. Also, proxy event handlers are aware of the current keypath context - see this JSFiddle to see what I mean http://jsfiddle.net/KJt2Y/2/ http://jsfiddle.net/KJt2Y/2/
- apidoc 13y agoNice little library. I think i will have a close look and implement it into apiDoc (http://apidocjs.com http://apidocjs.com) Templates - for now i use crude jQuery events (quick & dirty coded). With Ractive i think i can make the code cleaner and easier to modify. At the moment i prefer Backbone in my other projects, but it is to "heavy" for a small single page (especially for users that did not know backbone and want to modify the templates).
- sambeau 13y agoThis is fascinating: I've been writing a very (and I mean very) similar library that also uses the concept of a Parallel DOM (dependents, views updating on a 'data' property, nodes named by standard ids, all child nodes with IDs scanned for and bound to a property), I had just decided to create the concept of 'Keypaths' as my events were clashing on ids. The thing I have that I can't see here is a selecting/switching node: essentially a page or a tab that holds multiple states but only presents one at a time. Thus makes me very happy and very sad: happy as I don't have to write all things things now; sad becasue I don't get to write all these things now.
- rich_harris 13y agoI would feel the same way if we switched places! Really interesting that we have such similar approaches.
- leke 13y agoSo as this is DOM manipulation, it's a competitor to jQuery, right? If so, what are the advantages over jQuery, and would it make jQuery redundant now (for new projects)?
- rich_harris 13y agoI wouldn't say it makes jQuery redundant - the AJAX stuff is helpful (if replaceable) and it does a great job of e.g. $div.height() and so on, which can be a source of cross-browser headaches without it. Though personally yes, I find I rarely use jQuery now I've got Ractive. The difference is the difference between declarative and imperative programming. With jQuery you have to describe the steps that the browser has to follow in order to do something (e.g. $button.toggleClass( 'selected' ), whereas with Ractive you're much closer to simply declaring your intentions (e.g. ractive.toggle( 'selected' ), assuming your template references that variable). It's an inherently more scalable approach (which isn't to knock jQuery at all - they're attacking different if overlapping problems).
- modarts 13y agoCan anyone comment on using Ractive as a replacement to Backbone.View? I'd think that making Ractive the view layer in a Backbone app would go a long way in augmenting a lot of the things that Backbone refuses to do in views (binding, smart DOM management/manipulation, actual templating support)
- rich_harris 13y agoThere's a Ractive.extend() function for this exact use case, which allows you to incorporate all the functionality your Backbone View would have in a reusable constructor. Info on the wiki: https://github.com/Rich-Harris/Ractive/wiki/Ractive.extend() https://github.com/Rich-Harris/Ractive/wiki/Ractive.extend() There's also a concept of 'adaptors' which are ideal for Backbone.Model <-> Ractive binding, though it's a bit experimental and incomplete at the moment. You can bind to a model manually like model = new MyBackboneModel( attrs ); ractive = new Ractive({ el: whatever, template: tpl, data: model.attributes }); model.on( 'change', function ( model ) { ractive.set( model.changed ); });
- boubiyeah 13y agoCool website and examples! You should probably explain how ractive.js differentiates itself from knockout. It's the direct competitor out there, not angularJS which is doing things very differently. I glanced at the source and (correct me if I'm wrong) it seems array templating is done by simply comparing the length of the current and previous arrays? That's naive and buggy? Good luck
- rich_harris 13y agoThanks! Yes, a lot of the feedback I've had through various channels has involved 'how does this compare to x', and I'm pleased to see that a lot of people have picked up on the similarities to Knockout. On the project homepage I specifically refer to Angular because my sense is that it will be more familiar to more people, and despite the many architectural differences they're attacking the same problem space (though Angular deals with xhr/routing etc whereas Ractive is focused on DOM stuff). I'll add a comparison table of some sort to my (lengthening!) todo list. Could you elaborate at all on 'naive and buggy'? I think I probably know what you're getting at, but I'd be interested to hear your thoughts. Array sections do have a concept of 'smart updates' - if you do e.g. list.push( newItem ) or list.splice( index, 1 ) then it will take a more surgical approach to updates. You can see this in action at http://www.ractivejs.org/examples/todos/ http://www.ractivejs.org/examples/todos/, explanation of array modification at https://github.com/Rich-Harris/Ractive/wiki/Array-modification https://github.com/Rich-Harris/Ractive/wiki/Array-modificati...
- boubiyeah 13y agoI must have missed the 'smart update' bit :)