Your SlideShare is downloading. ×
  • Like
Desafios do Desenvolvimento de Front-end em um e-commerce
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Desafios do Desenvolvimento de Front-end em um e-commerce

  • 2,891 views
Published

Quando o objetivo é vender, uma modificação mínima pode impactar a taxa de conversão final. Para que um e-commerce atinja sua performance máxima, é necessário fazer com que os componentes, a equipe e …

Quando o objetivo é vender, uma modificação mínima pode impactar a taxa de conversão final. Para que um e-commerce atinja sua performance máxima, é necessário fazer com que os componentes, a equipe e mínimos detalhes funcionem em perfeita harmonia -- e o front-end é um deles.

Nesta palestra, mostrei os desafios enfrentados pelo time de engenharia de Front-end da Baby.com.br: como trabalhar com uma equipe com vários desenvolvedores, gerando componentes auto-contidos, testáveis e escaláveis, mantendo a melhor performance possível, sem perder o padrão de qualidade.

Fonte das métricas: http://blog.bizelo.com/blog/2012/10/18/infographic-shopping-cart-abandonment-rates/

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,891
On SlideShare
0
From Embeds
0
Number of Embeds
8

Actions

Shares
Downloads
79
Comments
0
Likes
20

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. os desafios do desenvolvimentode front-end em um e-commerce@shiota 2013
  • 2. olá!slideshare.net/eshiotagithub.com/eshiota@shiota
  • 3. front-end engineer@
  • 4. DEV
  • 5. e-commerce 101em alguns slides
  • 6. =)
  • 7. taxa de conversãodos usuários que entram no site, quantosfinalizam uma compra?
  • 8. ticket médioem média, quanto os usuários gastampor compra?
  • 9. =)taxa de conversão×ticket médio=
  • 10. taxa de conversão×ticket médio= $
  • 11. = $=)
  • 12. = ?=)
  • 13. complexoindecisoexigenteinexperientedecididocuidadosoexperiente
  • 14. ser humano, comotodos nós =)
  • 15. o que faz o usuárioabandonar o carrinho?
  • 16. alto custo de frete$
  • 17. não estão prontospara finalizar?
  • 18. produtos muito caros$
  • 19. guardam para depois
  • 20. não mencionouclaramente o frete?
  • 21. sem guest checkout
  • 22. formulário commuitas informações
  • 23. checkout complexo
  • 24. website lento
  • 25. taxas extras
  • 26. falta de opçõesde pagamento
  • 27. entrega demorada
  • 28. spam de ofertas
  • 29. site não funciona=(
  • 30. como o front-end podemelhorar a conversão?
  • 31. formulário com muitas informaçõescheckout complexowebsite lentosite não funciona
  • 32. velocidade da páginainterface estáveldetalhes = emotion designvalidação de novas hipóteses
  • 33. desafios de front-end(agora a palestra começa =P)
  • 34. múltiplos desenvolvedoresdesenvolvimento escalávelperformance client-sidetestes a/b
  • 35. trabalhando comvários desenvolvedores
  • 36. trabalhar em equipeé difícil... =(
  • 37. aspas simples×aspas duplas
  • 38. ponto e vírgula no JS×sem ponto e vírgula
  • 39. JavaScript×CoffeeScript
  • 40. (JavaScript, claro)
  • 41. (com ponto e vírgula)
  • 42. ... mas cada um pode teruma visão diferente ecomplementar. =)
  • 43. code smell performancesintaxe arquitetura
  • 44. mantenha um codestandard para o time.
  • 45. consistência, legibilidade,sem bikeshed.
  • 46. git + pull requests
  • 47. qualquer um revisa,qualquer um comenta.
  • 48. diferentes visões,mais erros detectados.
  • 49. o conhecimento édisseminado pelo time.
  • 50. todos ficam maiscriteriosos com o que fazem.
  • 51. desenvolvimentoescalável e testável
  • 52. desenvolvimento ágil:mudanças precisas,altos ganhos.
  • 53. melhorias são constantes,e nada é 100% definitivo.
  • 54. o código deve ser facilmentealterável/adaptável.
  • 55. dica 1usem pre-processors de CSS.sério. agora. já. eu espero.
  • 56. sass+
  • 57. variáveis, mixins efunções
  • 58. /*********************************************************************** Variables Module** All constants that will be used through the styles must be* defined here.**********************************************************************/$TEXT_COLOR : #555;$DISCOUNT_COLOR : #ef6565;$LIGHT_COLOR : #fefafa;$SELECTION_BACKGROUND : #41bdce;$SELECTION_COLOR : #fff;$LINK_COLOR : #447f87;$LINK_HOVER_COLOR : #41bdce;$LINK_ACTIVE_COLOR : #447f87;$ERROR_BACKGROUND : #fffaad;$LIGHT_BACKGROUND : #fefefa;$SITE_WIDTH : 978px;$FOOTER_HEIGHT : 777px;$PURPLE : #905194;$ORANGE : #fbb100;
  • 59. /*********************************************************************** Mixins Module** All general purpose mixins are defined here.**********************************************************************//********************************************************************** =Clearfix*********************************************************************/@mixin clearfix {&:after {clear: both;content: " ";display: block;font-size: 0;height: 0;visibility: hidden;}zoom: 1;}/********************************************************************** =Image replacement** `display` property should be declare on the element, not here* on the mixin. Element must have fixed width and height.*********************************************************************/@mixin img_replacement {text-indent: 100%;overflow: hidden;white-space: nowrap;}
  • 60. /*********************************************************************** Functions Module** Custom functions used by the application**********************************************************************/// Returns unitless number@function remove-unit($number) {$unit: unit($number);$one: 1;@if $unit == "px" { $one: 1px; }@if $unit == "em" { $one: 1em; }@if $unit == "%" { $one: 1%; }@return $number / $one;}// Returns flexible value// Returns `em` by default, accepts `%` as format.@function flex($target, $context: 14, $unit: "em") {$size: remove-unit($target) / remove-unit($context);@if $unit == "em" { @return #{$size}em; }@if $unit == "%" { @return percentage($size); }}// Alias to `flex` function, using `%` as format.@function perc($target, $context) {@return flex($target, $context, "%");}// Alias to `flex` function, using `em` as format.@function em($target, $context: 14) {@return flex($target, $context, "em");}
  • 61. estilos modularizadosem partials
  • 62. app/assets/stylesheets/base/_functions.scss_mixins.scss_variables.scssui/_breadcrumb.scss_carousel.scss_dentedBox.scss_flashMessage.scss
  • 63. /********************************************************************************* UI > Breadcrumb** General styles for the breadcrumb.********************************************************************************/.breadcrumb {font-size: em(12px);line-height: em(21px, 12px);text-transform: uppercase;color: #444;width: 978px;}.breadcrumb a,.breadcrumb a:visited,.breadcrumb a:active {color: #444;text-decoration: none;}.breadcrumb a:hover {color: #444;text-decoration: underline;}.breadcrumb .separator {padding: 0 3px;}
  • 64. /********************************************************************************* UI > Loader** Animated loader for AJAX requests********************************************************************************/@mixin loader_sprite_position($xoffset, $yoffset) {background-position: sprite-position($icon-sprite, loader_sprite, $xoffset, $yoffset);}.loader {width: 25px;height: 25px;display: none;}.loader b {display: block;width: 25px;height: 25px;background-image: sprite-url($icon-sprite);}.loader b,.loader .f1 { @include loader_sprite_position(-10px, -10px); }.loader .f2 { @include loader_sprite_position(-45px, -10px); }.loader .f3 { @include loader_sprite_position(-80px, -10px); }.loader .f4 { @include loader_sprite_position(-115px, -10px); }.loader .f5 { @include loader_sprite_position(-150px, -10px); }.loader .f6 { @include loader_sprite_position(-185px, -10px); }.loader .f7 { @include loader_sprite_position(-220px, -10px); }.loader .f8 { @include loader_sprite_position(-255px, -10px); }
  • 65. geração automática de spritesacelera o desenvolvimento.
  • 66. $icon-sprite: sprite-map("icon/*.png", $spacing: 16px, $repeat: no-repeat, $layout: vertical);
  • 67. $icon-sprite: sprite-map("icon/*.png", $spacing: 16px, $repeat: no-repeat, $layout: vertical);
  • 68. /* Compass sprite function receives the map variable and image as arguments */background: sprite($icon-sprite, arrow_dropdown) no-repeat;/* Compiled CSS */background: url(/assets/icon-s5dab8c2901.png) -40px -158px no-repeat;
  • 69. função de inline imageeconomiza requests.
  • 70. /* Compiled CSS */background: #f5f3fb url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAQCAMAAAAcVM5PAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAlQTFRF5+TW////////4qZUpQAAAAN0Uk5T//8A18oNQQAAACBJREFUeNpiYGBgAgMGBkYog4mJXAbILAiDkVxzAAIMAEMOAPMId2OWAAAAAElFTkSuQmCC) repeat;/* Generates a base64 image */background: #f5f3eb inline-image("bg_dots.png") repeat;
  • 71. (seja criterioso)
  • 72. dica 2módulos: poucas linhas,comportamentos isolados,extensíveis, e testáveis.
  • 73. estrutura base (reset, base styles)gridpadrõesmódulosmódulos contextualizados
  • 74. css do módulo
  • 75. /********************************************************************************* UI > Loader** Animated loader for AJAX requests********************************************************************************/@mixin loader_sprite_position($xoffset, $yoffset) {background-position: sprite-position($icon-sprite, loader_sprite, $xoffset, $yoffset);}.loader {width: 25px;height: 25px;display: none;}.loader b {display: block;width: 25px;height: 25px;background-image: sprite-url($icon-sprite);}.loader b,.loader .f1 { @include loader_sprite_position(-10px, -10px); }.loader .f2 { @include loader_sprite_position(-45px, -10px); }.loader .f3 { @include loader_sprite_position(-80px, -10px); }.loader .f4 { @include loader_sprite_position(-115px, -10px); }.loader .f5 { @include loader_sprite_position(-150px, -10px); }.loader .f6 { @include loader_sprite_position(-185px, -10px); }.loader .f7 { @include loader_sprite_position(-220px, -10px); }.loader .f8 { @include loader_sprite_position(-255px, -10px); }
  • 76. css do módulocontextualizado
  • 77. // On ui/_buttons.scss.bt-wrapper .loader {position: absolute;z-index: 4;right: 20px;top: 50%;margin-top: -9px;}// On modules/_checkoutAddressForm.scss.address-form .cep-input .loader {position: absolute;right: -33px;top: em(29px);}
  • 78. javascript enxuto,auto-contido.
  • 79. // Implements the animated loader for AJAX requests// Loader constructor//// * `placement`: Function that determines the loaders placementns("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();});EDEN.ui.Loader.prototype = {// Properties// ----------// Animation speed (in frames per second)fps : 20,// Fading speedfadeSpeed : 150,// Public methods// --------------
  • 80. testável!
  • 81. describe("EDEN.ui.Loader", function () {var Loader = EDEN.ui.Loader;beforeEach(function () {loadFixtures("loader.html");});afterEach(function () {$("body").find(".loader").remove();});it("accepts instance creation without new operator", function () {var newLoader = Loader();expect(newLoader).toBeInstanceOf(Loader);});it("inits the loader on creation", function () {var loader, oldInit = EDEN.ui.Loader.prototype.init;EDEN.ui.Loader.prototype.init = jasmine.createSpy();loader = new Loader();expect(loader.init).toHaveBeenCalled();EDEN.ui.Loader.prototype.init = oldInit;});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);});});
  • 82. "Mas tem muita coisa quenão dá pra testar, né?"
  • 83. "Mas testes atrapalham aentrega do projeto, né?"
  • 84. a Baby possui 1144 specs deJavaScript até agora
  • 85. falhas no jshint ou nas specsde javascript quebram o build
  • 86. dica 3javascript desacoplado emodularizado
  • 87. mediator: ponto central decomunicação via pub/sub
  • 88. MEDIATOR
  • 89. nenhum módulo temconhecimento do outro
  • 90. MEDIATORMediator, me avisa quandosair o novo do Game ofThrones?Blz
  • 91. MEDIATORMediator, me avisa quandosair o novo do Mythbusters?É nóish.
  • 92. MEDIATORMediator, saiu um eppy novode Game of Thrones.Subscribers, saiu um eppynovo de Game of Thrones!Ae, vou baixar, achoque vai ser feliz e tal=D
  • 93. MEDIATORMediator, saiu um eppy novode Mythbusters.Subscribers, saiu um eppynovo de Mythbusters!Ae, vou baixar!
  • 94. os módulos só conhecemo mediator
  • 95. módulos desacoplados, comcomportamentos específicos eisolados
  • 96. // Code inside ShippingAddressForm_registerInterests : function () {this.element.find(".cep-input").on("keyup paste cut", this._onCepModification.bind(this));},_onCepModification : function (event) {if (this.isCepFilled()) {EDEN.mediator.trigger("shipping-cep-change", event.target.value);} else {EDEN.mediator.trigger("shipping-cep-incomplete", event.target.value);}}
  • 97. // Code inside checkoutModule_registerInterests : function () {EDEN.mediator.on("shipping-cep-change", this._onShippingCepChange, this);this.shippingService.on("get-success", this._onShippingGetSuccess, this);},_onShippingCepChange : function (cep) {this.shippingService.get(cep);}_onShippingGetSuccess : function (data) {EDEN.mediator.trigger("shipping-rate-change", data.rate);EDEN.mediator.trigger("delivery-estimate-change", data.estimate);}
  • 98. // Code inside purchseInfo_registerInterests : function () {EDEN.mediator.on("shipping-rate-change", this._onShippingRateChange, this);EDEN.mediator.on("delivery-estimate-change", this._onDeliveryEstimateChange, this);},_onShippingRateChange : function (rate) {this.updateShippingRate(rate);},_onDeliveryEstimateChange : function (days) {this.updateDeliveryEstimate(days);},updateShippingRate : function (rate) {var formatter = EDEN.currency.formatter;this.element.find(".shipping-rate").text(formatter(rate));this.shippingRate = rate;this.updateTotal();},updateTotal : function () {var total = this.subtotal + this.shippingRate,formatter = EDEN.currency.formatter;this.element.find(".total").text(formatter(total));EDEN.mediator.trigger("cart-total-change", total);}
  • 99. // Code inside installmentSelector_registerInterests : function () {EDEN.mediator.on("cart-total-change", this._onCartTotalChange, this);},_onCartTotalChange : function (total) {this.updateInstallments(total);},updateInstallments : function (total) {// Updates the values}
  • 100. você não precisa sabertudo isso de primeira.
  • 101. addyosmani.com/largescalejavascript
  • 102. aprenda javascript antes dese focar em um framework.
  • 103. performanceclient-side
  • 104. css/javascriptminification/compression
  • 105. lazy-load everything! o/
  • 106. sprites e imagens inlines
  • 107. sass+
  • 108. não abuse de font-faces
  • 109. testes a/b
  • 110. isole os estilos e JS emclasses, partials e módulostotalmente separados
  • 111. <nav id="site-menu" class="site-menu"><div class="site-menu-container"><% if new_header? %><%= render "layouts/open_site_nav" %><% else %><%= render "layouts/site_nav" %><% end %><% unless new_header? %><%= render "layouts/search" %><% end %></div></nav>
  • 112. /******************************************************************************** =Menu A*******************************************************************************/.site-header-old .user-menu {position: absolute;right: perc(261px, $SITE_WIDTH);cursor: pointer;width: 213px;height: 63px;overflow: hidden;z-index: 600;}/******************************************************************************** =Menu B*******************************************************************************/.site-header-new .user-menu {position: absolute;right: perc(261px, $SITE_WIDTH);width: perc(150px, $SITE_WIDTH);height: em(63px);overflow: hidden;z-index: 600;}
  • 113. AB-TESTING.md - comoremover a versão perdedora
  • 114. # A/B Testing on Baby SiteThis document lists all A/B tests currently being run on the project, andshortly introduces the method being used.## Tests currently being run### Site-wide#### Header design version* Test name: `header-version`* Starts at: `ApplicationController`, on `:before_filter`* Goal: When user goes to a success checkout page* Ends at: `orders#success` view* PR/Commits: [#664](https://github.com/Baby-com-br/troy/pull/664)To remove this test:* Remove the `new_header?` method and its `:helper_method` on`application_controller.rb`* Remove the `header_version` method and its `:helper_method` on`application_controller.rb` and ALL its calls.* Consolidate the correct `render` calls on `layouts/_header.html.erb` and`layouts/_site_menu.html.erb`* Remove the `site-header-<%= header_version %>` class on `layouts/_header.html.erb`* Remove the `header-version-<%= header_version %>` class on `layouts/_head.html.erb`,on the `<body>` tag* Remove the `finished` call on `baby-site/app/views/orders/success.html.erb`* On `modules/_mainSearchForm.scss`, remove the entire block related to theloser version, and on the winner version: (1) remove the comment header aboutthe A/B test, (2) unprefix all selectors by removing either `.site-menu` (ifthe old header won) or `.site-header` (if the new header won)* On `layout/_user_menu.scss`, remove the entire block related to theloser version, and on the winner version: (1) remove the comment header aboutthe A/B test, (2) unprefix all selectors by removing either `.site-header-new` (ifthe old header won) or `.site-header-old` (if the new header won)* On `ui/_section_header.scss`, remove the `.header-version-old .section-titles`and `.header-version-new .section-titles` blocks, and use the winner paddingon `.section-titles`.* On `sections/_profile.scss`, remove the `.header-version-old .profile-header .site-menu`and `.header-version-new .profile-header .site-menu` blocks, and use the winner paddingon `.profile-header .site-menu`.* On `layout/_main.scss`, delete the `.header-version-old .site-menu-container` block.
  • 115. shiota, um dev front-endprecisa saber back-end?
  • 116. fulano(a), eu preciso sabercozinhar ou lavar roupa?
  • 117. não, mas ajuda, né? ;D
  • 118. você não precisa ser umnando vieira*.* @fnando - faz design, front-end, manja JS pacas, é um dev Ruby f*odido, e manja de SysOps
  • 119. saber back-endmelhora seu código.
  • 120. saber back-endlhe dá mais controle.
  • 121. saber back-endmelhora a comunicação.
  • 122. quando você deixa de perguntarapenas "como vou fazer isso" epassa a perguntar "como voufazer isso da melhor maneira"...
  • 123. ... você está nocaminho certo.
  • 124. divirta-se. sempre. =)
  • 125. obrigado!slideshare.net/eshiotagithub.com/eshiota@shiota