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

Modern Web Development Tools And Workflow

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

Modern Web Development Tools And Workflow

Avatar for Amjad Masad

Amjad Masad

June 06, 2014

More Decks by Amjad Masad

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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
  4. 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
  5. “the best way to attack the essence of building software

    is not to build it at all” The Mythical Man-Month On Reuse
  6. 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
  7. 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
  8. 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
  9. 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
  10. 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; }
  11. 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
  12. 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'); ); });
  13. 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
  14. 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
  15. 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
  16. 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
  17. Enter ES6 • HELPS WITH MODULARITY • HELPS WITH CLARITY

    • HELPS WITH ECONOMY • HELPS WITH COMPOSITION
  18. Enter React • LIBRARY FOR BUILD UI • HELPS WITH

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

    return <div>Hello {this.props.name}</div>; } }); ! React.renderComponent( <Hello name="Foo" />, document.body );
  20. 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
  21. 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>; } });
  22. 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 }); });
  23. 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
  24. React’s Transparency ONLY ONE TO DO ITEM BUT UI SAYS

    IT’S TWO. example credit @vjeux
  25. 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
  26. 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
  27. 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
  28. 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)" );
  29. 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)]); } ! ! ! ! ! ! ! ! } });
  30. 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 ); ! ! ! ! ! } });
  31. 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); } });
  32. debug_utils • ADVANCED JAVASCRIPT DEBUGGING UTILITY • CAN BREAK ON

    OBJECT ACCESS, EVENTS, CALLS, AND MORE • https://github.com/amasad/debug_utils
  33. 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!
  34. 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
  35. 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