programming in the reactive style with meteor js
DESCRIPTION
presented by Dave Anderson at FITC's Web Unleashed event in Boston on Nov 7ht, 2013. Meteor allows you to quickly create new web applications. Using a single code base for the client and the server, no-sql mongo, template-oriented UX organization and painless deployment, designing and developing with Meteor is fun. But the real game changer is Reactivity. Reactivity is made up of two parts – data sources and computations. When you build a page, Meteor remembers the computations that use reactive data sources. Then, when a data in a reactive source changes, the computations that depend on the data are invalidated and re-run – which can re-render the affected parts of your application. The true beauty of it is that it’s all automatic. You don’t need to write any code to watch for changes – Meteor does all that for you. Learning to build web applications in the Reactive Style gives you more time to concentrate on UX than traditional web development. Being able to side-step much of the application setup and data management frees you to focus on providing a pleasurable experience as well as useful functionality.TRANSCRIPT
What’s Meteor about?
“A better way to build apps.”
“Meteor is an open source platform for building top-quality web apps
in a fraction of the time, whether you’re an expert developer
or just getting started.”
Really?
Why Meteor?
Will Meteor make your web apps look better?
Will Meteor make it easier to build web apps users will enjoy?
Will Meteor stop the software apocalypse from coming?
Three Virtues of a Great
• Laziness
• Impatience
• Hubris
Web DeveloperProgrammer
• Laziness
• Impatience
• Hubris
What Matters?
• Fastest to Goal
• Most for Least Effort
• It Just Works
What Obstructs?
• Wide Technology Stack
• Finding and Changing Code
• ‘Extra’ Coding
• Conventional Flow
Traditional Wide Web Technology Stack
Client:
HTML, CSS, JavaScript !
Server: Programming Language, Database Access, Marshaling Language
Meteor Web Technology Stack
Client:
HTML, CSS, JavaScript, MiniMongo !
Server:
JavaScript, Mongo
Additional Stack
Java JavaScript libs, Jar files
Ruby on Rails JavaScript libs, Gem files
ASP Controls, Extensions
Clojure Clojure files
Meteor packages
How We Must Code
Nine months ago you wrote some code...
How We Must Code
Today you have to find and change it...
Follow the Breadcrumbs...
from the app in the browser
...to the app inspector...
...to a search of the code base
...repeatedly
Searching for Code, Traditionally
• look for element by CSS selector
• look for action bound to element
• look for code that emits element
• look for code that changes CSS selector
• keep looking inward...
Changing Code, Traditionally
• Change all the places!
• Test like the Dickens!
did you really change all the places?
• ummm...
Searching for Code in Meteor• look for the template that emits the element
• examine its html, css and javascript
Changing Code in Meteor
• Change the code in the template
• Test the changes (tinytest, laika, …)
‘Extra’ CodingThis one is hard to quantify.
HTML with handlebar templates JavaScript / CoffeeScript
CSS / SCSS packages
the code needed to build a Meteor-based web UX
is the most straightforward I’ve found.
YMMV
Conventional FlowCode uses the current values when called.
If a is 5 and b is 3, then
c = a+b
would set c to 8.
Later, if a became 4 and b became 2,
then c would still be 8 - until the code
was called again.
Reactive FlowCode uses values as they change.
If a is 5 and b is 3, then
c = a+b
would set c to 8.
Later, if a became 4 and b became 2,
then c would become 6 automatically.
Reactive Style Programming
not code that retrieves values so they can be rendered.
Data is pushed, not pulled.
is about writing code that renders values when they are delivered
How about an example...
Let’s Take Attendance!
webu13attend.meteor.com
webu13attend Deconstruction
client-only code
server-only code
shared code
webby bits
webu13attend client-only code
handlebars!
client/webu13attend.html
webu13attend client-only code
client/webu13attend.html
webu13attend client-only code
client/webu13attend.html
webu13attend client-only code
client/webu13attend.html
webu13attend client-only code
client/webu13attend.scss
webu13attend client-only code
client/webu13attend.coffee
webu13attend server-only code
server/attendees.coffee
webu13attend shared code
lib/collections.coffee
webu13attend webby bits
public/images/webu13.png
A Closer Look at Reactivity
Reactivity from the new-to-Meteor perspective...
In Meteor using its Reactive framework, a web application is coded Declaratively.
In the frameworks you’re probably used to, a web application is coded Imperatively.
Imperative Coding
Items.find().observe! added: (item) ->! $('ul').append '<li id="'+item._id+'">'+! item.name+'</li>'! changed: (item) ->! $('ul li#'+item._id).text item.name! removed: (item) -> ! $('ul li#'+item._id).detach()
if you’re lucky enough to have database notification through an observe-like function,
you implement callbacks
Items.find().observe! added: (item) ->! $('ul').append '<li id="'+item._id+'">'+! item.name+'</li>'! changed: (item) ->! $('ul li#'+item._id).text item.name! removed: (item) -> ! $('ul li#'+item._id).detach()
Items.find().observe! added: (item) ->! $('ul').append '<li id="'+item._id+'">'+! item.name+'</li>'! changed: (item) ->! $('ul li#'+item._id).text item.name! removed: (item) -> ! $('ul li#'+item._id).detach()
Items.find().observe! added: (item) ->! $('ul').append '<li id="'+item._id+'">'+! item.name+'</li>'! changed: (item) ->! $('ul li#'+item._id).text item.name! removed: (item) -> ! $('ul li#'+item._id).detach()
Declarative Coding
<template name="itemList">! <ul>! {{#each items}}! <li>{{name}}</li>! {{/each}}! </ul>!</template>
Meteor does the observe callback behind the scenes
Template.itemList.helpers! items: -> Items.find()
How does Reactivity work?
JS f Reactive Source
first use
How does Reactivity work?
JS f Reactive Source
Computation Processing
How does Reactivity work?
JS f Reactive Source
Dependency Established
How does Reactivity work?
JS f Reactive Source
ready to go
Why Computations?
Because Meteor has the potential to change the entire interface
when a reactive source changes!
Changes based on a computation becoming invalid focus on only the parts of the interface
that depend on the computation.
How does Reactivity work?
JS f Reactive Source
ready to go
How does Reactivity work?
JS f Reactive Source
Source Updated
How does Reactivity work?
JS f Reactive Source
Computation Invalidated
How does Reactivity work?
JS f Reactive Source
Computation Processing
How does Reactivity work?
JS f Reactive Source
Computation Processing
How does Reactivity work?
JS f Reactive Source
ready to go
What are Reactive Sources?
local (client)remote
database queries (subscriptions)
session variables
status
user / user id
logging in
subscription ready
Reactivity from the Meteor-savvy perspective...
The magic is all in the Deps object!
Deps
Computation Dependency
How does the Deps object work?
Deps.Computation
firstRun
onInvalidate(function)
stop( )
stopped
invalidate( )
invalidated
Deps.Dependency
depend( )
changed( )
hasDependents( )
Depsautorun(function)currentComputationactiveonInvalidate(function)flush( )afterFlush(function)nonreactive(function)
An Example:
Injectives
Sessions variables are reactive sources global to the client.
An Injective is a local reactive source that can be more closely scoped to the functions and objects that uses it.
Deps.injective = (init) ->! _value: init ? 0! _dep: new Deps.Dependency! ! set: (value) ->! if (@_value != value)! @_value = value! @changed()! get: ->! @depend()! @_value! depend: ->! @_dep.depend()! changed: ->! @_dep.changed()
Foo.innerWidth =! Deps.injective window.innerWidth
Consider the use of the an injective:
$(window).resize ->! Foo.innerWidth.set window.innerWidth
Any computation that calls Foo.innerWidth.get( ) will react when its value changes.
So then,
Example of InjectivesUse the height and width of a browser window to control the size of some objects.
innerWidth = Deps.injective window.innerWidth!innerHeight = Deps.injective window.innerHeight!!$(window).resize ->! innerWidth.set window.innerWidth! innerHeight.set window.innerHeight!!Template.box.helpers! size: ->! Math.floor (innerWidth.get()+innerHeight.get())/4.0
So why should Meteor and Reactivity
matter to me?• Less extra coding
• Narrower technology stack
• Changes are pushed, not pulled
• Easier to find and change code
When not to use Meteor
Try It!
Take the
Meteor Challenge
Give it two weeks and expand what you know about
building web applications!