Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Arquitetura de Front-end em Aplicações de Larga Escala

2,736 views

Published on

Para desenvolver um site institucional simples ou um hotsite pequeno, não é preciso muito mais que um pouco de HTML, um ou dois arquivos de CSS, alguns arquivos de JavaScript, e um sistema de CMS. No entanto, à medida que a complexidade de um site aumenta, o código passa a se tornar cada vez mais extenso, complexo, difícil de ser organizado, e projeto acaba virando um grande "code spaghetti".

Para garantir que isso não aconteça, é necessário implementar uma estrutura sólida para o HTML, CSS e JavaScript, de modo que os componentes da aplicação funcionem independentemente e sejam facilmente mantidos e modificados. Nesta palestra, mostrei como elaborar uma arquitetura de front-end que sustente uma aplicação de larga escala.

Published in: Technology

Arquitetura de Front-end em Aplicações de Larga Escala

  1. 1. Arquitetura deFront-end emaplicações delarga escala@shiota | eshiota.comRAILSEDITION
  2. 2. Front-end
  3. 3. Internet
  4. 4. Arquitetura simplesArquitetura complexa
  5. 5. Na minha visão, aplicações JavaScriptde larga escala são aplicações não-triviais que requerem um esforçosignificante de manutenção por parte dodesenvolvedor, onde a maior parte dotrabalho de manipulação de dados evisualização é atribuída ao navegador.Addy OsmaniDeveloper Programs Engineer @ Google
  6. 6. Aplicações com front-end de largaescala são aplicações não-triviais querequerem um esforço significante demanutenção por parte dodesenvolvedor, onde organização,modularização, otimização e reutilizaçãode código são cruciais.Eduardo Shiota YasudaLoves cat videos on Youtube
  7. 7. Aplicações depequena escala
  8. 8. style.csstemplatesapplication.js& jQuery / pluginsimagensCMS
  9. 9. CSS simplesCentenas de linhasFácil de manter
  10. 10. JS SimplesPlugins e algumas funçõesUma função autoexecutáveljQuery
  11. 11. Aplicações deLarga escala
  12. 12. HTML, CSS e JavaScriptmodulares
  13. 13. Noção de módulo
  14. 14. HTML & CSS modular
  15. 15. <section class="side-block"><h3>Quick links</h3><ul class="arrowed-list side-list"><li><a href="#">Your profile</a></li><li><a href="#">MKX settings</a></li><li><a href="#">MIH SWAT</a></li><li><a href="#">Invite users</a></li></ul></section>
  16. 16. <section class="side-block"><h3>Your starred content</h3><ul class="iconed side-list"><li class="file-locked"><a href="#">RubyConf - 02 - Ruby is cool</a><br /><small>in group: <a href="#">Ruby</a></small></li><li class="photo-locked"><a href="#">RubyConf entrance hall</a><br /><small>in group: <a href="#">Ruby</a></small></li><li class="doc"><a href="#">MongoDB</a><br /><small>in company: <a href="#">MIH SWAT</a></small></li><li class="forum"><a href="#">Ruby group files...</a><br /><small>in group: <a href="#">Ruby</a></small></li></ul></section>
  17. 17. <section class="side-block"><h3>Recommended contacts</h3><ul class="side-list"><li class="data-card"><div class="card-content"><hgroup><h4>Lorem ipsum</h4><h5>CEO @ <a href="#">MIH SWAT</h5></hgroup><p><a href="#">[add as contact]</a></p></div><img src="image.jpg" alt="Lorem ipsum" /></li><li class="data-card"><div class="card-content"><hgroup><h4>Lorem ipsum</h4><h5>Technical Architect @ <a href="#">MIH SWAT</h5></hgroup><p><a href="#">[add as contact]</a></p></div><img src="image.jpg" alt="Lorem ipsum" /></li></ul></section>
  18. 18. <section class="side-block"><h3></h3><ul class="side-list"><li></li></ul></section>
  19. 19. /*********************************** patterns/side_list.scss**********************************/.side-list {list-style: none outside;padding: 0;}.side-list li {margin-bottom: 10px;overflow: hidden;}/*********************************** patterns/arrowed_list.scss**********************************/.arrowed-list li {margin-bottom: 0.2em;position: relative;}.arrowed-list li:before {content: "25B8";display: inline-block;margin-right: 0.3333em;}
  20. 20. /*********************************** patterns/side_block.scss**********************************/.side-block {margin-bottom: 1.5em;}.side-block h3 {border-bottom: 1px solid #cecece;font-size: 1em; /* 16px / 16px */margin-bottom: 0.8em;padding-bottom: 0.1em;}
  21. 21. <section><h3>Recommended contacts</h3><ul class="side-list small-entity-list"><li class="data-card"><div class="card-content"><hgroup><h4>Lorem ipsum</h4><h5>CEO @ <a href="#">Buscapé</h5></hgroup><p><a href="#">[add as contact]</a></p></div><img src="image.jpg" alt="Lorem ipsum" /></li></ul></section>
  22. 22. <article class="data-card group-activity"><div class="card-content"><p><a href="#" class="actor">Rafael Dohms</a> joined a group:<a href="#" class="subject">I love Ruby on Rails</a></p><p><date>2 hours ago</date><a href="#">Unlike</a><a href="#">Comment entry</a></p></div><img src="image.jpg" alt="Rafael Dohms" /></article>
  23. 23. <article class="data-card"><div class="card-content"></div><img /></article>
  24. 24. /*********************************** patterns/data_card.scss**********************************/.data-card {min-height: 120px;position: relative;}/* Override width and height as needed */.data-card > img {position: absolute;left: 0;top: 0;width: 120px;height: 120px;}/* Override padding-left as needed */.data-card .card-content {padding-left: 140px;}
  25. 25. /**************************************** patterns/small_entity_list.scss** children extend patterns/data_card***************************************/.small-entity-list .data-card {min-height: 60px;}.small-entity-list .data-card > img {width: 60px;height: 60px;}.small-entity-list .data-card .card-content {padding-left: 80px;}
  26. 26. .button.large-button.confirm-button.send-button
  27. 27. .button {border-radius: 5px;font-family: "proxima-nova", sans-serif;height: 2em;line-height: 2em;padding: 1em;color: #fff;text-shadow: 0 -1px 0 #000;}.large-button {font-size: 3em;}.confirm-button {background: #ffba00;box-shadow: 0 3px 0 #cd9600;}.send-button {/* styles for icon placement */}
  28. 28. .button.large-button.confirm-button.send-button
  29. 29. .button.small-button.confirm-button.send-button
  30. 30. Multiple classes + Single responsabilitiesShort inheritance (3-4 levels max)Portable classes
  31. 31. Organizando os módulos
  32. 32. /** application.css example w/ Asset Pipeline**= require base/reset*= require core/typography*= require core/forms*= require_tree ./patterns*= require ui/buttons*= require ui/loader*= require ui/datepicker*/
  33. 33. application.scss w/ SASS
  34. 34. base/_functions.scss
  35. 35. core/_typography.scss
  36. 36. ui/_loader.scss
  37. 37. application-ec8971025292ecb7dd2c99d430d7a76e.css
  38. 38. Leituras
  39. 39. oocss.org
  40. 40. smacss.com
  41. 41. JavaScript modular
  42. 42. JavaScript não é (só) jQuery
  43. 43. shareTypeSelector.jsshareForm.jsshareField.jsnewsfeed.js
  44. 44. shareFormshareTypeSelector shareFieldmediator.jstrigger("share-type-changed") on("share-type-changed")shareProxynewsfeedon("new-post")trigger("new-post")init initsubmit getdataonsuccess
  45. 45. Modules + Tests=OMGBBQW00T
  46. 46. /**Loader constructor@params {Function} placement Function that determines the loaders placement@constructor**/ns("EDEN.ui.Loader", function (placement) {if (!(this instanceof EDEN.ui.Loader)) {return new EDEN.ui.Loader(placement);}this.frame = 1;this.framesQty = 8;this.stack = [];this.animating = false;this.$loader = $("<div class=loader><b> </b></div>");this.$renderer = this.$loader.find("b");this.placement = placement;this.init();});
  47. 47. /**Animation speed (in frames per second)@property fps@type Number@default 20**/EDEN.ui.Loader.prototype.fps = 20;/**Fading speed@property fadeSpeed@type Number@default 150**/EDEN.ui.Loader.prototype.fadeSpeed = 150;
  48. 48. /**Inits the loader by inserting it into the DOM. If a placement argumentwasnt passed to the constructor, uses a generic placement.@method init**/EDEN.ui.Loader.prototype.init = function () {if (!this.placement) {this.placement = function ($loader) {$loader.appendTo($("body"));};}this.placement.call(this, this.$loader);};
  49. 49. /**Starts the loader by fading in and starting the animation.If there are multiple processes, stacks the requests.@method start**/EDEN.ui.Loader.prototype.start = function () {this.stack.push((new Date()).getTime());if (this.stack.length === 1) {this._startAnimation();}};/**Stops the loader by fading out and stoping the animationIf there are any processes pending, pops the requestsuntil it can actually stop.@method stop**/EDEN.ui.Loader.prototype.stop = function () {this.stack.pop();if (!this.stack.length) {this._stopAnimation();}};
  50. 50. /**Starts the loader animation@private**/EDEN.ui.Loader.prototype._startAnimation = function () {this.animating = true;this._renderAnimation();};/**Stops the loader animation@private**/EDEN.ui.Loader.prototype._stopAnimation = function () {this.animating = false;};
  51. 51. /**Loops the animation, calling itself according to the fps@private**/EDEN.ui.Loader.prototype._renderAnimation = function () {if (!this.animating) { return true; }this._draw();setTimeout(this._renderAnimation.bind(this), 1000 / this.fps);};/**Draws the animation@private**/EDEN.ui.Loader.prototype._draw = function () {this.$renderer.removeClass().addClass("f" + this.frame);this.frame = this.frame + 1 > this.framesQty ? 1 : this.frame + 1;};/**Returns the animation stack.@return Array@private**/EDEN.ui.Loader.prototype._getAnimationStack = function () {return this.stack;};
  52. 52. não achei um logo maior :(
  53. 53. it("appends the loader to body as a default", function () {var loader = new Loader();expect($("body").find(".loader").length).toEqual(1);});it("appends the loader through an argument function", function () {var loader = new Loader(function ($loader) {$("#loader-placeholder").append($loader);});expect($("#loader-placeholder").find(".loader").length).toEqual(1);});it("stops the animation if stack is empty", function () {loader.start();loader.stop();expect($(".loader").data("spinning")).not.toBeTruthy();});
  54. 54. it("renders the animation at default speed (20fps)", function () {jasmine.Clock.useMock();spyOn(loader, "draw");loader.start();jasmine.Clock.tick(2000);// The first renderAnimation call renders the first frame, and then// starts the frame counting. So itll always be (fps * seconds) + 1expect(loader.draw.calls.length).toEqual(41);});
  55. 55. jasmincerice + guard-jasmine +PhantomJS + Jenkins=OMGWTFBBQW00TROFL
  56. 56. github.com/bradphelan/jasminerice/
  57. 57. github.com/netzpirat/guard-jasmine
  58. 58. phantomjs.org
  59. 59. Jenkins » rake guard:jasmine
  60. 60. SOLID principlesLoose coupling » PortableTestableMV**
  61. 61. Organizando os módulos
  62. 62. // application.js with Asset Pipeline////= require jquery//= require jquery_ujs//= require jquery/jquery.inputmask//= require jquery/jquery.validate//= require jquery/jquery.uniform//= require i18n//= require i18n/translations//= require i18n/setLocale//= require_tree shims//= require tools/namespace//= require accounting//= require handlebars-1.0.0.beta.6//= require eden/events//= require eden/dispatcher//= require eden/appMediator//= require_tree ./jquery//= require_tree ./eden/ui//= require_tree ./eden/presenters//= require_tree ./eden/validators//= require ./eden/forms/SubmitButton//= require_tree ./eden/forms//= require_tree ./eden/components//= require_tree ./eden/views//= require_tree ./eden/proxies//= require_tree ./eden/commands//= require_tree ./eden/services//= require_tree ./eden/modules//= require eden/app
  63. 63. documentcloud.github.com/jammit/
  64. 64. requirejs.org
  65. 65. //my/shirt.js now has some dependencies, a cart and inventory//module in the same directory as shirt.jsdefine(["./cart", "./inventory"], function(cart, inventory) {//return an object to define the "my/shirt" module.return {color: "blue",size: "large",addToCart: function() {inventory.decrement(this);cart.add(this);}};});
  66. 66. github.com/jwhitley/requirejs-rails
  67. 67. Leituras
  68. 68. addyosmani.com/largescalejavascript
  69. 69. addyosmani.github.com/todomvc/
  70. 70. Ferramentas paramanter a organização
  71. 71. github.com/cowboy/grunt
  72. 72. html5boilerplate.com
  73. 73. compass-style.org
  74. 74. Exemplos com compass
  75. 75. Geração de sprites
  76. 76. /* Attributes a sprite map to a variable */$icon-sprite: sprite-map("icon/*.png", $spacing:16px, $repeat: no-repeat, $layout: vertical);
  77. 77. $icon-sprite: sprite-map("icon/*.png", $spacing:16px, $repeat: no-repeat, $layout: vertical);
  78. 78. /* Compass sprite function receives the map variable andimage as arguments */background: sprite($icon-sprite, arrow_dropdown) no-repeat;/* Compiled CSS */background: url(/assets/icon-s5dab8c2901.png) -40px -158px no-repeat;
  79. 79. Inline images - base64
  80. 80. /* Generates a base64 image */background: #f5f3eb inline-image("bg_dots.png") repeat;/* Compiled CSS */background: #f5f3fb url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAQCAMAAAAcVM5PAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRF5+TW////////4qZUpQAAAAN0Uk5T//8A18oNQQAAACBJREFUeNpiYGBgAgMGBkYog4mJXAbILAiDkVxzAAIMAEMOAPMId2OWAAAAAElFTkSuQmCC) repeat;
  81. 81. Vendor prefixes
  82. 82. .my-gradient {background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -ms-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -o-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));}
  83. 83. .my-gradient {background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -ms-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -o-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));}
  84. 84. /* Generates vendor-prefixed rules */.my-gradient {@include background-image(linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)));}/* Compiled CSS */.my-gradient {background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -moz-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -ms-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -o-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));}
  85. 85. Resumindo
  86. 86. Modules, motherf*cker.
  87. 87. Aprenda JavaScript.
  88. 88. Use ferramentas e frameworks. <3
  89. 89. Se você chegar nesse ponto...
  90. 90. DOUBLE RAINBOW ALL THE WAYOMG SO INTENSE
  91. 91. Thanks!@shiota | eshiota.com

×