Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modern Web Development Tools And Workflow

Modern Web Development Tools And Workflow

03637ef1a5121222c8db0ed48c34e124?s=128

Amjad Masad

June 06, 2014
Tweet

Transcript

  1. Modern Web Development Tools And Workflow Amjad Masad @amasad !

    facebook
  2. What Do I Mean By Modern?

  3. Invention of the web • STARTED AS A NOTEBOOK PROGRAM

    “ENQUIRE” WITH LINKS IN 1980S • INVENTED THE WEB AS WE KNOW IT TODAY WITH HTML AND HTTP IN 1990 • THE FIRST BROWSER WAS A PROTOTYPE THAT ONLY RAN ON NEXT OS • FIRST REAL CROSS PLATFORM ACCESSIBLE BROWSER WAS A LINE-MODE BROWSER
  4. CLI is 70’s Tech

  5. None
  6. Upon Inception The Web Was 20 Years Behind

  7. 1993 • GUI BROWSERS CAME ABOUT LIKE MOSAIC AND LATER

    MICROSOFT IE • ON PC LAND IN 1993 WE STARTED TO SEE ADVANCED 3D GRAPHIC GAMES LIKE DOOM
  8. Doom Eventually Made It’s Way To The Web in 2011

  9. repl.it ran Python, Ruby, Lua and other programming languages on

    the Web in 2011
  10. The Past Few Years Were Amazing For the Web

  11. In Just Few Years • FAST DOM MANIPULATION TO HANDLE

    COMPLEX APPS LIKE FACEBOOK • NEAR NATIVE JAVASCRIPT PERF GETS US 3D GAME ENGINES LIKE UNREAL • RELIABLE VIDEO PLAYBACK FOR APPS LIKE NETFLIX • WEBSOCKET AND WEBRTC API FOR REALTIME APPS AND VIDEO CHAT • OFFLINE MODE FOR GOOGLE DRIVE AND OFFICE APPS • AND MANY MORE
  12. We’re Trying To Build The Applications Of Tomorrow By Using

    The Tools Of Yesterday
  13. What’s Missing? • TO BUILD MAINTAINABLE SOFTWARE ON THE WEB

    WE NEED • POWERFUL UI FRAMEWORKS FOR BUILDING AND REUSING COMPONENTS • LANGUAGES WITH MORE ADVANCED PRIMITIVES • TOOLING
  14. What Do We Know About Maintainable Software?

  15. “the best way to attack the essence of building software

    is not to build it at all” The Mythical Man-Month On Reuse
  16. Unix Philosophy

  17. Rule of Diversity • ‘DISTRUST ALL CLAIMS FOR “ONE TRUE

    WAY”’ • NOT CLAIMING A ONE TRUE WAY. BUT CERTAINLY A WAY THAT HAS PROVEN TO WORK
  18. Rule of Modularity • “WRITE SIMPLE PARTS CONNECTED BY CLEAN

    INTERFACES” • OUR BASIC PRIMITIVE FOR MODULARITY IN JAVASCRIPT IS A FUNCTION • EVERYTHING IS GLOBAL BY DEFAULT • CAN’T REQUIRE OR INCLUDE CODE • WHICH MAKES IT PRE-C LANGUAGE IN TERMS OF MODULARITY
  19. Rule of Clarity function sum() { var args = Array.prototype.slice.call(arguments);

    var ret = 0; for (var i = 0; i < args.length; i++) { ret += args[i]; } return ret; } • “CLARITY IS BETTER THAN CLEVERNESS” • JAVASCRIPT IS INCREDIBLY VERBOSE
  20. Rule of Composition • “DESIGN PROGRAMS TO BE CONNECTED TO

    OTHER PROGRAMS” • PROGRAMS ARE HARD TO CO-EXIST IN JAVASCRIPT (SEE RULE OF MODULARITY) • NO BUILT-IN VERSIONING • UI CODE IS INCREDIBLY HARD TO COMPOSE BECAUSE PARENT NEEDS TO KNOW ABOUT CHILDREN STATE
  21. Composing UIs in Backbone init: function() { this.model.on('change:field', this.changeContent) },

    ! changeContent: function(text) { this.$('.field').val(text); }, ! renderSubview: function() { this.subview.$el.remove(); this.subview = new Subview(); this.$el.append(this.subview.render().$el); }, ! render: function() { this.$el.$html(this.template()); this.renderSubview(); this.renderAnotherSubview(); return this; }
  22. Rule of Simplicity • “DESIGN FOR SIMPLICITY; ADD COMPLEXITY ONLY

    WHERE YOU MUST” • HAVING TO POLLY-FILL THE APIS ADDS COMPLEXITY AND CODE TO MAINTAIN • IT TAKES A LOT OF CODE TO KEEP YOUR APPLICATION STATE IN SYNC WITH YOUR DOM • TO UPDATE THE DOM WE USE CSS SELECTORS WHICH COUPLES THE MARKUP TO OUR UI LOGIC
  23. Building UI With Templates <ul id="todos"> {{#todos}} <li id="todo-{{id}}"> <input

    type="checkbox" checked="{{done}}"> <div>{{task}}</div> </li> {{/todos}} </ul> ! ! // First render looks nice template({ todos: todos }); // Later .. todos.on('change', function(model) { $('#todo-' + model.id).find('input').val( model.get('done'); ); });
  24. Rule of Separation • “SEPARATE INTERFACES FROM ENGINES” • WE

    DO COMPUTATION ON THE UI THREAD • WE STORE DATA IN THE DOM • INTERFACES AND ENGINES ARE COMMINGLING
  25. Rule of Economy • “PROGRAMMER TIME IS EXPENSIVE; CONSERVE IN

    PREFERENCE TO MACHINE TIME” • WE SLAVE OVER OPTIMIZING DOM MANIPULATIONS • WE WRITE SO MUCH BOILERPLATE • LACK OF GOOD DEBUGGING TOOLS
  26. Rule of Repair • “WHEN YOU FAIL, FAIL NOISILY AND

    AS SOON AS POSSIBLE” • JAVASCRIPT IS NOTORIOUS FOR FAILING SILENTLY • BROWSERS WON’T THROW ERRORS FOR HTML OR CSS EITHER
  27. Rule of Generation • MACHINES ARE BETTER THAN US IN

    WRITING CODE • JAVASCRIPT COMMUNITY BUILT GREAT AST AND COMPILER TOOLS FOR JS • WE CAN USE IT TO GENERATE BOILERPLATE AND DO USEFUL TRANSFORMATION ON THE CODE
  28. We Can Do Better

  29. Enter ES6 • HELPS WITH MODULARITY • HELPS WITH CLARITY

    • HELPS WITH ECONOMY • HELPS WITH COMPOSITION
  30. Writing Modular Code • ES6 HAS POWERFUL PRIMITIVES • BUILT-IN

    MODULES • CLASSES • LET KEYWORD
  31. Clarity and Economy var sum = (...args) => args.reduce( (acc,

    n) => acc + n ); ES6 is concise
  32. Enter React • LIBRARY FOR BUILD UI • HELPS WITH

    MODULARITY • HELPS WITH CLARITY • HELPS WITH COMPOSITION • HELPS WITH SIMPLICITY • HELPS WITH ECONOMY • HELPS WITH REPAIR
  33. What is React var Hello = React.createClass({ render: function() {

    return <div>Hello {this.props.name}</div>; } }); ! React.renderComponent( <Hello name="Foo" />, document.body );
  34. What’s Special About It • DON’T NEED TO UPDATE THE

    DOM AND SYNC IT WITH YOUR APPLICATION STATE • JUST DESCRIBE THE UI DECLARATIVELY USING XML SYNTAX • DON’T NEED TO WORRY ABOUT OPTIMIZING DOM UPDATES • ALL JAVASCRIPT MEANS LESS GLUE CODE AND EASIER EVENT HANDLING
  35. var Counter = React.createClass({ getInitialState: function() { return { count:

    this.props.initialCount }; }, ! addToCount: function(delta) { this.setState({ count: this.state.count + delta }); }, ! render: function() { return <div> <h3>Count: {this.state.count}</h3> <button onClick={this.addToCount.bind(this, 1)}> +1 </button> <button onClick={this.addToCount.bind(this, -1)}> -1 </button> </div>; } });
  36. Revisiting Todo Example (Simplicity) <ul id="todos"> {{#todos}} <li id="todo-{{id}}"> <input

    type="checkbox" checked="{{done}}"> <div>{{task}}</div> </li> {{/todos}} </ul> ! ! // First render looks nice template({ todos: todos }); // Later .. todos.on('change', function(model) { template({ todos: todos }); });
  37. Clarity and Modularity <Typeahead />

  38. Composition render: function() { return <div> <Photo image={this.state.image}/> <Typeahead data={this.state.data}

    onSelect={this.onSelect} /> </div>; }
  39. Economy and Repair • REACT IS STRICT ABOUT MARKUP ERRORS

    UNLIKE THE BROWSER • CAN ONLY CHANGE REACT COMPONENT STATE VIA SETSTATE CALL MAKES IT EASY TO SPOT BUGS
  40. React’s Transparency ONLY ONE TO DO ITEM BUT UI SAYS

    IT’S TWO. example credit @vjeux
  41. React Devtools • FIND THE OFFENDING COMPONENT • LOOK ONLY

    IN THE COMPONENT FOR LOCAL VARIABLES • OR LOOK IN THE PARENT COMPONENT PASSING IN THE PROPS SINCE THEY ARE IMMUTABLE
  42. Tools • RECAST FOR GENERATION • FB-FLO FOR ECONOMY •

    DEBUG_UTILS FOR ECONOMY
  43. Recast • TRANSFORM JAVASCRIPT AST • EXAMPLE: USED RECAST TO

    AUTOMATICALLY MODERNIZE OUR JAVASCRIPT CODE • SAVES ON HUMAN TIME AND LESS ERROR PRONE • https://github.com/benjamn/recast
  44. Recast Example [3, 1, 10, 28].sort((a, b) => a -

    b) [3, 1, 10, 28].sort(function(a, b) { return a - b; }.bind(this)) INPUT (ES6) OUTPUT (ES5) example credit @benjamn
  45. Recast Example var recast = require("recast"); var types = recast.types;

    var traverse = types.traverse; var n = types.namedTypes; var b = types.builders; ! var ast = recast.parse( "[3, 1, 10, 28].sort((a, b) => a - b)" );
  46. Recast Example traverse(ast, function(node) { ! ! ! ! !

    ! ! ! ! ! ! ! ! ! ! });
  47. Recast Example traverse(ast, function(node) { if (n.ArrowFunctionExpression.check(node)) { ! !

    ! ! ! ! ! ! ! ! ! ! ! ! ! } });
  48. Recast Example traverse(ast, function(node) { if (n.ArrowFunctionExpression.check(node)) { var body

    = node.body; ! if (node.expression) { node.expression = false; body = b.blockStatement([b.returnStatement(body)]); } ! ! ! ! ! ! ! ! } });
  49. Recast Example traverse(ast, function(node) { if (n.ArrowFunctionExpression.check(node)) { var body

    = node.body; ! if (node.expression) { node.expression = false; body = b.blockStatement([b.returnStatement(body)]); } ! var funExp = b.functionExpression( node.id, node.params, body, node.generator, node.expression ); ! ! ! ! ! } });
  50. Recast Example traverse(ast, function(node) { if (n.ArrowFunctionExpression.check(node)) { var body

    = node.body; ! if (node.expression) { node.expression = false; body = b.blockStatement([b.returnStatement(body)]); } ! var funExp = b.functionExpression( node.id, node.params, body, node.generator, node.expression ); ! var bindExp = b.callExpression( b.memberExpression(funExp, b.identifier("bind"), false), [b.thisExpression()] ); ! this.replace(bindExp); } });
  51. debug_utils • ADVANCED JAVASCRIPT DEBUGGING UTILITY • CAN BREAK ON

    OBJECT ACCESS, EVENTS, CALLS, AND MORE • https://github.com/amasad/debug_utils
  52. Debugging Example • BUG WERE YOUR WINDOW SCROLLS ALL THE

    WAY TO TO TOP • YOU CAN GREP THE CODEBASE FOR WINDOW.SCROLLTO, WINDOW.SCROLLBY, BODY.SCROLLTOP = • IMPOSSIBLE AT THE SCALE OF FB OR EVEN MUCH SMALLER COMPANY • SOLUTION: SET UP TRAPS!
  53. Trap Scroll With debug_utils $dum(window, 'scrollBy');! $dum(window, 'scrollTo');! $dus(window, 'scrollTop');

  54. fb-flo • MODIFY RUNNING APPS WITHOUT RELOADING • FLEXIBLE AND

    CAN BE EASILY INTEGRATED INTO YOUR SETUP • SHORTER DEVELOPMENT CYCLE • https://github.com/amasad/debug_utils
  55. Why fb-flo • RELOADING AND GETTING TO THE USER FLOW

    TAKES A LONG TIME • HOOKS INTO THE RUNNING VM AND PATCHES THE CODE • NON OF THE OTHER TOOLS WORKED WITH OUR SETUP AT FACEBOOK • NON OF THE OTHER TOOLS WORKED WITH FACEBOOK SCALE
  56. Thank You ! @amasad