Programming in the Reactive Style with Meteor JS

Preview:

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.

Citation preview

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?

Dave Anderson dave@neo.com @eymiha

Programming in the Reactive Style using

Meteor JS

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!

Dave Anderson dave@neo.com @eymiha

Questions?

Recommended