Arquitetura deFront-end emaplicações delarga escala@shiota | eshiota.comRAILSEDITION
Front-end
Internet
Arquitetura simplesArquitetura complexa
Na minha visão, aplicações JavaScriptde larga escala são aplicações não-triviais que requerem um esforçosignificante de man...
Aplicações com front-end de largaescala são aplicações não-triviais querequerem um esforço significante demanutenção por pa...
Aplicações depequena escala
style.csstemplatesapplication.js& jQuery / pluginsimagensCMS
CSS simplesCentenas de linhasFácil de manter
JS SimplesPlugins e algumas funçõesUma função autoexecutáveljQuery
Aplicações deLarga escala
HTML, CSS e JavaScriptmodulares
Noção de módulo
HTML & CSS modular
<section class="side-block"><h3>Quick links</h3><ul class="arrowed-list side-list"><li><a href="#">Your profile</a></li><l...
<section class="side-block"><h3>Your starred content</h3><ul class="iconed side-list"><li class="file-locked"><a href="#">...
<section class="side-block"><h3>Recommended contacts</h3><ul class="side-list"><li class="data-card"><div class="card-cont...
<section class="side-block"><h3></h3><ul class="side-list"><li></li></ul></section>
/*********************************** patterns/side_list.scss**********************************/.side-list {list-style: non...
/*********************************** patterns/side_block.scss**********************************/.side-block {margin-bottom...
<section><h3>Recommended contacts</h3><ul class="side-list small-entity-list"><li class="data-card"><div class="card-conte...
<article class="data-card group-activity"><div class="card-content"><p><a href="#" class="actor">Rafael Dohms</a> joined a...
<article class="data-card"><div class="card-content"></div><img /></article>
/*********************************** patterns/data_card.scss**********************************/.data-card {min-height: 120...
/**************************************** patterns/small_entity_list.scss** children extend patterns/data_card************...
.button.large-button.confirm-button.send-button
.button {border-radius: 5px;font-family: "proxima-nova", sans-serif;height: 2em;line-height: 2em;padding: 1em;color: #fff;...
.button.large-button.confirm-button.send-button
.button.small-button.confirm-button.send-button
Multiple classes + Single responsabilitiesShort inheritance (3-4 levels max)Portable classes
Organizando os módulos
/** application.css example w/ Asset Pipeline**= require base/reset*= require core/typography*= require core/forms*= requi...
application.scss w/ SASS
base/_functions.scss
core/_typography.scss
ui/_loader.scss
application-ec8971025292ecb7dd2c99d430d7a76e.css
Leituras
oocss.org
smacss.com
JavaScript modular
JavaScript não é (só) jQuery
shareTypeSelector.jsshareForm.jsshareField.jsnewsfeed.js
shareFormshareTypeSelector shareFieldmediator.jstrigger("share-type-changed") on("share-type-changed")shareProxynewsfeedon...
Modules + Tests=OMGBBQW00T
/**Loader constructor@params {Function} placement Function that determines the loaders placement@constructor**/ns("EDEN.ui...
/**Animation speed (in frames per second)@property fps@type Number@default 20**/EDEN.ui.Loader.prototype.fps = 20;/**Fadin...
/**Inits the loader by inserting it into the DOM. If a placement argumentwasnt passed to the constructor, uses a generic p...
/**Starts the loader by fading in and starting the animation.If there are multiple processes, stacks the requests.@method ...
/**Starts the loader animation@private**/EDEN.ui.Loader.prototype._startAnimation = function () {this.animating = true;thi...
/**Loops the animation, calling itself according to the fps@private**/EDEN.ui.Loader.prototype._renderAnimation = function...
não achei um logo maior :(
it("appends the loader to body as a default", function () {var loader = new Loader();expect($("body").find(".loader").leng...
it("renders the animation at default speed (20fps)", function () {jasmine.Clock.useMock();spyOn(loader, "draw");loader.sta...
jasmincerice + guard-jasmine +PhantomJS + Jenkins=OMGWTFBBQW00TROFL
github.com/bradphelan/jasminerice/
github.com/netzpirat/guard-jasmine
phantomjs.org
Jenkins » rake guard:jasmine
SOLID principlesLoose coupling » PortableTestableMV**
Organizando os módulos
// application.js with Asset Pipeline////= require jquery//= require jquery_ujs//= require jquery/jquery.inputmask//= requ...
documentcloud.github.com/jammit/
requirejs.org
//my/shirt.js now has some dependencies, a cart and inventory//module in the same directory as shirt.jsdefine(["./cart", "...
github.com/jwhitley/requirejs-rails
Leituras
addyosmani.com/largescalejavascript
addyosmani.github.com/todomvc/
Ferramentas paramanter a organização
github.com/cowboy/grunt
html5boilerplate.com
compass-style.org
Exemplos com compass
Geração de sprites
/* Attributes a sprite map to a variable */$icon-sprite: sprite-map("icon/*.png", $spacing:16px, $repeat: no-repeat, $layo...
$icon-sprite: sprite-map("icon/*.png", $spacing:16px, $repeat: no-repeat, $layout: vertical);
/* Compass sprite function receives the map variable andimage as arguments */background: sprite($icon-sprite, arrow_dropdo...
Inline images - base64
/* Generates a base64 image */background: #f5f3eb inline-image("bg_dots.png") repeat;/* Compiled CSS */background: #f5f3fb...
Vendor prefixes
.my-gradient {background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -moz...
.my-gradient {background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, .5), rgba(0, 0, 0, 0));background-image: -moz...
/* Generates vendor-prefixed rules */.my-gradient {@include background-image(linear-gradient(right, rgba(0, 0, 0, .5), rgb...
Resumindo
Modules, motherf*cker.
Aprenda JavaScript.
Use ferramentas e frameworks. <3
Se você chegar nesse ponto...
DOUBLE RAINBOW ALL THE WAYOMG SO INTENSE
Thanks!@shiota | eshiota.com
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Arquitetura de Front-end em Aplicações de Larga Escala
Upcoming SlideShare
Loading in …5
×

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

2,612 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

×