You Should Be Using Flight

Stop the Fanaticism: Use the Right Tool for the job.

You Should be Using Flight

Why I use Flight, and you should consider it, too.

About Me

  • Javascript Addict (Node, Front-End, Robotics)

 

  • Engineering Evangelist at RetailMeNot

 

  • I have a .gif problem.

What is Flight?

"Flight is a lightweight, component-based JavaScript framework that maps behavior to DOM nodes. Twitter uses it [...you're not even reading this far.]" - flightjs.github.io

But I'm a fan of [ AngularJS, Backbone, Ember, Knockout, React, whatever ] framework!

Warning: opinion
incoming

I think a lot of frameworks are over-used and shoehorned into projects where they aren't the best tool for the job.

 

I question the work-to-reward ratio of a lot of today's front-end frameworks

We have a serious problem with framework fanaticism.

Instead of asking 'how is Y framework like [my favorite],' we should ask 'how will this make my JS better?'

Let the argument commence!

(Later. Over food or a beer.)

 

Definition of the word 'framework':

"an essential supporting structure of a building, vehicle, or object."

-Merriam-Webster

Flight is a framework:

  • Set of small utilities
  • Encourages well-written, modular apps
  • Lightweight

Not Overly Prescriptive

  • Not MV* (Unless you write it).
  • Plays well with other libraries
  • Gives you tools to structure your code

Commandments of Flight

  • Components are atomic
  • Communication via Events
  • Use the DOM (, Luke!)
  • Test Everything

An Aside about
Functional Mixins

Functional Mixins

  • Applies functionality to a prototype
  • "a process, not an object" - Angus Croll
  • The best thing to happen to JS since JSHint

Generic
Resuable
Functionality

Why not
inheritance?

  • Gang of Four: Composition over Inheritance
  • Does a signup button inherit from signupFormElement, or Button?
  • JS isn't meant for inheritance (!)

 

Writing a
Flight Application

You can follow along at GitHub

Step 1: write your HTML

Count: <span class="js-count"></span>
<a class="btn btn-success js-increment" href="" target="_blank"></a> 
<a class="btn btn-danger js-decrement" href="" target="_blank">-</a> 

Step 2: write your component code


function counter() {
	this.attributes({
		'counterDisplay': '.js-count',
		'incrementButton': '.js-increment',
		'decrementButton': '.js-decrement'
	});

	this.after('initialize', function () {
		this.select('counterDisplay').text('0');
		this.on('click', {
			'incrementButton': this.increment,
			'decrementButton': this.decrement
		});
		this.on('counterChange', this.change);
	});	

	//...event handlers after this...
}

Component code breakdown

  • this.attributes({})
  • this.after('initialize', function(){})
  • Event handlers
  • Component Definition / Mixins

Component Definition / Mixins

  • mixins go first - most generic -> most specific
  • Overrides go in the component
return defineComponent(
  withMixin1,  
  withMixin2, 
  withMixin3, 
  componentConstructor);

Step 3 - Actually using our component

  • Require in our module
  • run .attachTo(selector)

define(function(require){
	var myCounter = require('components/counter');

	myCounter.attachTo('.js-counter', {
		//you can override attributes here.
	});
})

Why we put all selectors in defaultAttrs

We can now override our selectors without changing the class. We have made our component markup agnostic.

 

This gives us a large chunk of the code reusability that we normally don't get.

Flight Component
Events Explained

Cute Critters as Components

 

 

this.on('toy_falls', this.omg);


this.after('initialize', function(){
  this.on('friend_lick', this.nope);
})

this.nope = function(){
  this.push();
  this.cleanSelf();
}

 


//...some other code...
try{
	this.weirdFunction();
} catch (e) {
	$(this).trigger('weirdError', {
		error: e
	});
}

//...our component...
this.after('intiialize', function(){
	this.on('weirdError', this.panic);
});

Testing Flight Applications

Flight provides all the utilites you need to write testable client-side JS

How is flight code testable

  • Components = Tiny little services
  • Each service has a consistent API
  • Event A is listened to, Event B is emitted with data C

But wait, there's more

  • Flight proivdes a full testing framework
  • jasmine-flight, mocha-flight
  • Yeoman app generator
    • Sets up karma, mocha-flight

What do these wrappers do?

  • Event Spies
  • Automate HTML markup injection
  • headless test running

A Mocha-Flight test


beforeEach(function () {
  setupComponent('<span class="js-counter"></span><span class="js-increment"></span>'); 
}); 

it('should fire a counterChange with 1 when the increment button is clicked', 
function(){ 
  var eventSpy = spyOnEvent(document, 'counterChange');
  this.component.select('incrementButton').click();
  expect(eventSpy).toHaveBeenTriggeredOn(document);
  expect(eventSpy.mostRecentCall.data).toEqual({ value: 1 }); 
 }); 

Not only does Flight give you the tools, it encourages you to write testable code.

But, I *still* like whatever.js better!

That's OK. Flight plays well with other libraries. Or maybe Flight isn't the solution. Use the right tool for the job.

"But...but...moving frameworks is haaaaard." - a friend

The super-secret super-complicated very-difficult omg-halp plan to mix Flight code into your codebase

  • Put event handlers in your existing code
  • Put event triggers in your existing code

Flight <3's Developers

(And you should totally <3 it, too.)

Everyone's Invited to the Party

Flight is a framework that allows you to structure your app without intimidating and confusing your newer devs.

Test all the things...easily!

Save yourself from absolute chaos, and relegate yourself to the normal level of chaos.

Because developer hapiness is contagious!

Questions?

http://github.com/kperch/midwest_js

@nodebotanist

kas@nodebots.io

Flight-Talk

By kperch

Flight-Talk

  • 1,890