Finding Patterns in Front-end JS

Finding Patterns in Front-end JS

We’re all building a client-side framework. And they’re all different implementations of the same stuff. I want to compare the approaches that popular frameworks take to solving these patterns. If they even try to solve them at all. I also want to include info about the custom framework that Yammer uses. It’ll be illustrative to see how all of these have different approaches to the same set of patterns.

30cd2c0748d86f53245986c5dc8281bf?s=128

Marco Rogers

May 28, 2014
Tweet

Transcript

  1. FINDING PATTERNS MARCO ROGERS @polotek Yammer in FRONT-END JS

  2. FINDING PATTERNS "When it comes down to it, everybody is

    building variants of the same MVCish framework. We should be talking about the shared patterns." ! - Me
  3. FINDING PATTERNS • Common (Basic MVCish) • Advanced (Better abstractions,

    integrated) • Emerging (New app capabilities)
  4. ! ! COMMON PATTERNS

  5. COMMON PATTERNS • Models • Views • Routing/Controllers • RESTful

    API access
  6. MODELS • Objects representing your data • Data properties that

    are read/write • Persist data to the server (usually) • Event listeners that fire when data changes
  7. MODELS: BACKBONE.JS var thread = new Backbone.Model({ ! id: 100,!

    latest_reply_at: '2014-05-28T17:36:05.707Z'! }); ! ! thread.get(‘id’) === 100;! ! thread.on(‘change:latest_reply_at’, function() {! /* Do Stuff */! });! ! thread.set(‘latest_reply_at’, (new Date).toISOString());
  8. MODELS: YAM.JS var thread = yam.model.Thread.create({ ! id: 100, !

    latest_reply_at: '2014-05-28T17:36:05.707Z'! });! ! thread.id === 100;! ! thread.hook(‘onUpdate’, function(oldData, newData) {! /* Do Stuff */! });! ! thread.update({! latest_reply_at: (new Date).toISOString()! });
  9. MODELS: ANGULAR feedApp.controller('ThreadViewCtrl', function ($scope) { ! $scope.thread = {

    ! id: 100, ! latest_reply_at: '2014-05-28T17:36:05.707Z' ! }; ! ! $scope.thread.id === 100;! ! $scope.$watch(‘thread.latest_reply_at’, function(old, new) { ! /* Do Stuff */ ! }); ! ! $scope.thread.latest_reply_at = (new Date).toISOString();! });
  10. MODELS • Objects representing your data • Data properties that

    are read/write • Event listeners that fire when data changes • Persist data to the server (usually)
  11. ! ! ADVANCED PATTERNS

  12. ADVANCED PATTERNS • Nested Views • Complex Rendering • Model

    Relationships • Local Data Caching • Data-binding (two-way)
  13. VIEWS • Render some markup to the DOM • Respond

    to user input from the DOM • Update the DOM based on some changes
  14. NESTED VIEWS • Organize views into a parent-child tree •

    Parents recursively render children • The tree has a shared lifecycle
  15. NESTED VIEWS: YAM.JS ThreadListItem ThreadStarter MessageListItem

  16. NESTED VIEWS: YAM.JS ThreadListItem = Backbone.Component.extend({! _addThreadStarter: function () {!

    this.threadStarter = new ThreadStarter(message, {...});! this.prepend(this.threadStarter);! });! ! _addReplyListItem: function (reply) {! this.replyListItem = new MessageListItem(reply, {…});! this.append(this.replyListItem); ! });! });! ! var threadList = new ThreadListItem();! threadList.render();
  17. NESTED VIEWS: MARIONETTE.JS MessageListItem = Backbone.Marionette.ItemView.extend({});! ! ThreadListItem = Backbone.Marionette.CompositeView.extend({!

    itemView: MessageListItem! });! ! var threadList = new ThreadListItem({! model: someModel,! collection: someCollection! });! ! threadList.render();
  18. NESTED VIEWS: EMBER.JS App.MessageListItem = Ember.Component.extend({…});! ! <div class=“thread-list-item”>! {{thread-starter}}!

    <ul class="thread-replies">! {#each reply in threadReplies}}! {{message-list-item reply=reply}}! {{/each}}! </ul>! </div>
  19. ! ! EMERGING PATTERNS

  20. EMERGING PATTERNS • Custom components (Polymer, React) • Real-time updates

    (Socket.IO, Pusher) • Real-time sync (Firebase, Meteor) • Persistent offline cache (hood.ie) • Device capabilities (e.g. camera, location)
  21. REAL-TIME UPDATES • Subscribe to real-time updates from the server

    • Dispatch updates to the model layer • Register to receive events with new model data
  22. REAL-TIME: ANGULAR var ItemListController = function($scope, $http, Pusher) {! $scope.items

    = [];! ! var retrieveItems = function () {! $http.get('/api/items').success(function (items) {! $scope.items = items;! });! };! ! Pusher.subscribe('items', 'updated', function (item) {! $scope.items.push(item);! });! ! retrieveItems();! http://blog.pusher.com/making-angular-js-realtime-with-pusher/
  23. REAL-TIME: EMBER.JS Discourse.TopicController = Discourse.ObjectController.extend(..., {! subscribe: function() {! var

    topicController = this;! var bus = Discourse.MessageBus;! ! bus.subscribe("/topic/" + this.get('id'), function(data) {! // Add the new post into the stream! topicController.get(‘postStream')! .triggerNewPostInStream(data.id);! });! }! } http://balinterdi.com/2014/01/14/how-real-time-updates-work-in- discourse.html
  24. REAL-TIME: YAM.JS // FeedModel! yam.model.define('yam.model.Feed', function () {! this.clientize(‘yam.client.RealtimeFeedClient’);! !

    // DataClient! yam.ctor(‘yam.client.BaseRealtimeClient’, {! connectToRealtime: function(params) {! yam.client.bayeux.subscribe({! id: this.getUrl(),! url: this.getRealtimeUrl(),! onData: _.bind(this.onRealtimeData, this)! });! }! });
  25. REAL-TIME: YAM.JS var feedModel = yam.model.Feed.create(…);! ! // Listen for

    events! feedModel.hook(‘onThreadUpdate’, function(thread) {! // Could be from an ajax request, could be real-time! // We usually don’t care! });
  26. REAL-TIME: METEOR Messages = new Meteor.Collection(‘messages’);! ! var query =

    Messages.find();! query.observeChanges({! added: function (id, message) { /* Do stuff */ },! removed: function () { /* Do stuff */ }! });
  27. REAL-TIME: METEOR <template name="messageList">! {#each messages}! <li>{{body}}</li>! {/each}! </template>! !

    Template.messageList.messages = function () {! return Messages.find();! };
  28. FINDING PATTERNS "I'm more interested in optimizing a person's understanding

    of problems than their understanding of solutions.” ! - Kris Gale
  29. THANKS. MARCO ROGERS @polotek Yammer