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

Você ainda não sabe escrever JavaScript para aplicações Rails

Você ainda não sabe escrever JavaScript para aplicações Rails

Uma palestra com as principais tecnologias e técnicas utilizadas para escrever código JavaScript sano para diferentes tipos de aplicações. Uma viagem às antigas soluções Rails até as atuais e nem sempre suficientes jQuery UJS e Turbolinks. Aprenda sobre componentes auto-discoverable, comunicação através de eventos, modularização e gerência de dependências. Tudo isto sem deixar de fora alguns dos conceitos por trás dos principais frameworks MV* do mercado.

Jean Carlo Emer

August 29, 2014
Tweet

More Decks by Jean Carlo Emer

Other Decks in Programming

Transcript

  1. Você ainda não
    sabe escrever
    JavaScript para
    aplicações Rails!
    @jcemer

    View full-size slide

  2. JavaScript
    para apps
    Rails
    @jcemer

    View full-size slide

  3. http://jcemer.com

    View full-size slide

  4. Código JavaScript melhora a
    usabilidade através da
    adição de interatividade
    (ao menos deveria)

    View full-size slide

  5. 88%
    dos websites utilizam JavaScript
    http://w3techs.com

    View full-size slide

  6. Túnel do 

    tempo

    View full-size slide

  7. [...] é necessário ir ao passado para a
    compreensão de todos os
    questionamentos do tempo presente
    - Historiador Tiago Menta

    View full-size slide

  8. Rails era muito opinativo em
    relação à escrita de
    JavaScript

    View full-size slide

  9. O framework possuía uma
    série de helpers para gerar
    código para Prototype.js

    View full-size slide

  10. Envio assíncrono
    de formulários

    View full-size slide

  11. <%  form_remote_tag  :url  =>  '/'  do  -­‐%>  
           <%=  submit_tag  'Save'  %>  
    <%  end  -­‐%>
    index.erb

    View full-size slide

  12. Rio Grande do Sul
    Porto Alegre

    View full-size slide

  13. <%=  observe_field(:local_estado_id,  
             :update  =>  "local_cidade_id",  
             :url  =>  cidades_options_for_select_path,  
             :with  =>  "estado_id"  %>
    index.erb

    View full-size slide

  14.                name="local[estado_id]">  
    !
     <br/>//<![CDATA[  <br/>    new  Form.Element.EventObserver('local_estado_id',        <br/>!<br/>!<br/>!<br/>//]]>  <br/>
    !@#$%^@!%
    index.html

    View full-size slide

  15. Alto acoplamento do HTML com
    Prototype.js
    Tags scripts espalhadas no markup

    View full-size slide

  16. Existia também o RJS para
    escrever código Prototype.js 

    no back-end

    View full-size slide

  17. Resposta para 

    chamadas Ajax

    View full-size slide

  18. update_page  do  |page|  
       page.insert_html  :bottom,  'list',    
           "#{@item.name}"  
       page.visual_effect  :highlight,  
    'list'  
    end
    controller/action.rb

    View full-size slide

  19. Resposta para 

    chamadas Ajax

    View full-size slide

  20. new  Element.insert("list",    
           {  bottom:  "Some  item"  });  
    new  Effect.Highlight("list");
    response.js

    View full-size slide

  21. Alto acoplamento do código
    back-end com Prototype.js

    View full-size slide

  22. JavaScript não deve estar no
    markup
    Código back-end não deve
    depender de biblioteca front-end.


    View full-size slide

  23. Evolução
    do Rails

    View full-size slide

  24. Tudo aquilo que você está perdendo
    se a sua aplicação ainda não foi
    atualizada

    View full-size slide

  25. Rails 3.0
    Fim das chamadas Ajax através de
    JavaScript inline e dos observers
    https://github.com/rails/prototype_legacy_helper

    View full-size slide

  26. Rails 3.0
    Nascimento do projeto
    Unobtrusive JavaScript
    https://github.com/rails/prototype-ujs

    View full-size slide

  27. Confirmar ação

    View full-size slide

  28. <%=  link_to  "Other  Site",  "url",    
        data:  {  confirm:  "Are  you  sure?"  }  %>
    index.erb

    View full-size slide

  29.  
      Other  Site
    index.html
    Qualquer biblioteca
    pode endereçar a
    funcionalidade

    View full-size slide

  30. Envio assíncrono
    de formulários

    View full-size slide

  31. <%=  form_for  @post,  remote:  true  %>
    index.erb

    View full-size slide


  32. index.html
    Qualquer biblioteca
    pode endereçar a
    funcionalidade

    View full-size slide

  33. Considere que o formulário
    também pode ser enviado
    sincronamente pelo usuário
    E se não executar o 

    JavaScript?

    View full-size slide

  34. Configurar o método 

    de requisição

    View full-size slide

  35. <%=  link_to  "Destroy",  "url",  

                             method:  :delete  %>
    index.erb

    View full-size slide

  36.  
       Destroy
    index.html

    View full-size slide

  37. deletar notícia

    View full-size slide

  38. O usuário irá apenas ler a notícia,
    considere sempre utilizar
    formulários para este tipo de ação
    E se não executar o 

    JavaScript?

    View full-size slide

  39. Um pequeno
    parêntese sobre
    atributos data-*
    (

    View full-size slide

  40. Data attributes são a melhor
    alternativa para armazenar
    informações adicionais de um
    elemento

    View full-size slide

  41. $('.element').data('remote');
    sample.js (jQuery)

    View full-size slide

  42. $('[data-­‐element]').data('remote');
    Recomendado, mesmo
    que afete na performance
    http://jsperf.com/class-vs-data-attribute

    -selector-performance
    sample.js (jQuery)

    View full-size slide

  43. ) Classes do HTML são
    para semântica, o
    JavaScript não deve
    ser baseado nelas

    View full-size slide

  44. Rails 3.1
    Suporte a Prototype.js e RJS é
    removido dando espaço à jQuery

    View full-size slide

  45. jQuery é a biblioteca front-end
    mais adequada da atualidade

    (valorize e aprenda de verdade)

    View full-size slide

  46. As actions ainda podem entregar
    código JavaScript

    View full-size slide

  47. Requisição Ajax

    View full-size slide

  48. $('#photo_<%=  params[:id]  %>').remove();
    destroy.js.erb
    photo.html
         data-­‐method="delete"    
         data-­‐remote="true">Destroy  

    View full-size slide

  49. <%-­‐  if  @contact.errors.any?  %>  
       $('#contact-­‐modal').html('<%=  
    escape_javascript(render(partial:  'form'))  
      )  %>');  
    <%-­‐  else  %>  
       $('#contact-­‐modal').html('<%=  
    !
         
    !
      $('#contact-­‐modal').append('alert-­‐success">Your  message  was  successfully  

    sent  ');  
       setTimeout("$('.close').click();",  2000);  
    <%-­‐  end  %>
    !@#$%^@!%
    create.js.erb

    View full-size slide

  50. Rails 3.1
    Adoção da linguagem CoffeeScript
    que transpila para JavaScript

    View full-size slide

  51. Não usamos CoffeeScript 

    por aqui!
    - muitos de vocês

    View full-size slide

  52. class  Counter  
       constructor:  (@min  =  0,  @max  =  10e9)  -­‐>  
           @current  =  @min  
       next:  -­‐>  
           @current  =  Math.min(@max,  @current  +  1)  
       isFirst:  -­‐>  
           @current  <=  @min  
    !
    class  CounterPlus  extends  Counter  
       goToLast:  -­‐>  
           @current  =  @max
    counter.coffee

    View full-size slide

  53. function  Counter(min,  max)  {  
           this.min  =  min  !=  null  ?  min  :  0;  
           this.max  =  max  !=  null  ?  max  :  10e9;  
           this.current  =  this.min;  
    }  
    !
    Counter.prototype.next  =  function()  {  
           return  this.current  =  

          Math.min(this.max,  this.current  +  1)  
    }  
    !
    Counter.prototype.isFirst  =  function()  {  
           return  this.current  <=  this.min  
    }  
    !
    function  CounterPlus()  {  
    counter.js

    View full-size slide

  54. !
    Counter.prototype.isFirst  =  function()  {  
           return  this.current  <=  this.min  
    }  
    !
    function  CounterPlus()  {  
           Counter.apply(this,  arguments)  
    }  
    !
    function  InheritCounter()  {}  
    InheritCounter.prototype  =  Counter.prototype  
    !
    CounterPlus.prototype  =  new  InheritCounter()  
    CounterPlus.prototype.constructor  =  CounterPlus  
    !
    CounterPlus.prototype.goToLast  =  function()  {  
           return  this.current  =  this.max  
    }

    View full-size slide

  55. Syntax sugar para "classes"
    Arrow functions e fat arrow
    functions para binding com this


    View full-size slide

  56. Não é por nada que o EcmaScript 6
    usa o CoffeeScript como
    referência

    View full-size slide

  57. ♥CoffeeScript

    View full-size slide

  58. Rails 4.0
    Adoção da biblioteca JavaScript
    Turbolinks

    View full-size slide

  59. O Turbolinks objetiva reduzir
    pela metade o tempo de
    carregamento de uma página

    View full-size slide

  60. RUBYCONF


    CONHEÇA OS
    PALESTRANTES
    PROMETE TRAZER
    NOVIDADES E
    ASSUNTOS
    PERTINENTES DA
    ÁREA

    View full-size slide

  61. RUBYCONF


    CONHEÇA OS
    PALESTRANTES
    PROMETE TRAZER
    NOVIDADES E
    ASSUNTOS
    PERTINENTES DA
    ÁREA
    Requisição Ajax pela
    página apontada no link

    View full-size slide

  62. RUBYCONF


    CONHEÇA OS
    PALESTRANTES
    PROMETE TRAZER
    NOVIDADES E
    ASSUNTOS
    PERTINENTES DA
    ÁREA

    View full-size slide

  63. RUBYCONF
    PALESTRANTES
    FÁBIO AKITA

    HANNELI TAVANTE

    JEAN CARLO EMER
    Substituição do conteúdo

    do da página com
    a resposta

    View full-size slide

  64. A barra de endereços é
    atualizada e as páginas
    visitadas são armazenadas
    (voltar à uma página é imediato)

    View full-size slide

  65. Assets devem ficar no e
    precisam ser marcados para que
    modificações sejam monitoradas
    (e recarregada caso preciso)

    View full-size slide

  66. Código JavaScript não será
    executado na troca de páginas

    View full-size slide

  67. Além de, 

    é preciso também esperar por
    $.ready(fn)
    $(document).on('page:load',  fn)
    $(document).on('page:restore',  fn)

    View full-size slide

  68. Widgets e add-on podem não
    funcionar como esperado

    View full-size slide

  69. Suporte para widgets do Facebook,
    Twitter, Google+, Google Analytics,
    AdSense e alguns mais
    http://reed.github.io/turbolinks-compatibility

    View full-size slide

  70. É preciso cuidado dobrado para
    evitar memory leaks

    View full-size slide

  71. A cada transição os events handlers e
    demais callbacks devem ser
    desativados para não interferir na
    performance

    View full-size slide

  72. Código JavaScript pode ser
    executado na troca de páginas
    Widgets e add-ons funcionam de
    acordo depois de ajustados
    Memory leaks podem ser evitados



    View full-size slide

  73. O Turbolinks não permite que
    apenas porções da página sejam
    requisitadas
    (confira o jquery-pajax para isto)

    View full-size slide

  74. Turbolinks funciona bem 

    em websites simples (como o 

    desta conferência) e forma uma 

    boa dupla com UJS

    View full-size slide

  75. Evolua você
    também

    View full-size slide

  76. Rails é framework full-stack para criar
    aplicações, mas você provavelmente
    irá precisar de mais

    View full-size slide

  77. Organização de código JavaScript
    e modularização
    Componentes front-end
    Bibliotecas e frameworks 

    front-end



    View full-size slide

  78. Modularização
    de código 

    JavaScript

    View full-size slide

  79. O JavaScript não possui sistema de
    módulos fazendo com que diferentes
    scripts compartilhem o mesmo escopo

    View full-size slide

  80. file1.js
    file2.js
    Sem a criação de um
    escopo, as variáveis
    ficam expostas
    var  myVar  =  "bla";
    alert(myVar);

    View full-size slide

  81. (function  ()  {  
       var  data  =  {};  
       function  parser()  {  
         
       //  Code  
       }  
    })();
    Immediately-Invoked
    Function Expression
    viabilizam a criação
    de escopos
    http://benalman.com/news/
    2010/11/immediately-
    invoked-function-expression

    View full-size slide

  82. Não polua o escopo global, os
    demais desenvolvedores agradecem

    View full-size slide

  83. Com a criação de escopos com uma
    única responsabilidade, surge a
    necessidade de acessar dependências

    View full-size slide

  84. App.modules.mediabox  =  (function  ()  {  
       var  data  =  {};  
    !
       return  {  
         
       data:  data,  
         
       parser:  //  ...  
       }  
    })();
    Namespaces
    mediabox.js (namespace)

    View full-size slide

  85. Module('modules.mediabox',  

       function  (Mediabox)  {  
           Mediabox.data  =  {};  
         Mediabox.parser  =  //  ...  
       }  
    );
    Biblioteca de módulos
    do Nando Vieira
    http://simplesideias.com.br/
    escrevendo-javascript-modular
    mediabox.js (Module.js)

    View full-size slide

  86. define(  
       [  
           'jquery',    
           'util/counter'  
       ],  
       function  ($,  Counter)  {  
           //  ...          
           return  {  
               Mediabox:  Mediabox,  
               //  ...  
           };  
       }

    );
    mediabox.js (AMD)
    Módulos AMD que
    permitem indicação
    de dependências
    https://github.com/
    jwhitley/requirejs-rails

    View full-size slide

  87. Declaração de dependências
    Path do arquivo como identificador
    do módulo
    Assíncrono por natureza e adotado

    por jQuery e outras bibliotecas



    View full-size slide

  88. [...] it makes code easier to
    understand for others and
    yourself re-visting your own
    code
    - Chris Coyier

    View full-size slide

  89. ES6 Modules e CommonJS Modules
    não possuem suporte adequado 

    ao Asset Pipeline
    (alguém se habilita?)

    View full-size slide

  90. Componentes
    front-end

    View full-size slide

  91. Um componente encapsula
    elementos HTML, CSS e
    comportamento

    View full-size slide

  92. Template, 

    CSS e JS
    Template, 

    CSS e JS

    View full-size slide

  93. Web Components é a
    salvação do front-end,
    use agora!!
    - algum desavisado

    View full-size slide

  94. Web Componentes com Polymer é
    ainda um experimento e não deve
    ser utilizado em produção

    View full-size slide

  95. Mas temos muito o que aprender
    sobre JavaScript com os Web
    Components

    View full-size slide

  96. 1. Instanciação de 

    Componentes

    View full-size slide

  97. main.js
    //  Setup  product  page  
    if  ($('body').is('.page-­‐product'))  {  
       $("[data-­‐draggable]").draggable()  
       $("[data-­‐comments]").comments()  
    }  
    !
    //  Setup  checkout  page  
    if  ($('body').is('.page-­‐checkout'))  {  
       $("[data-­‐draggable]").draggable()  
       $("[data-­‐datepicker]").datepicker()  
    }

    View full-size slide

  98. Componentes podem ser removidos
    ou adicionados necessitando
    manutenção no JavaScript

    View full-size slide

  99. main.js
    //  Setup  product  page  
    if  ($('body').is('.page-­‐product'))  {  
       $("[data-­‐draggable]").draggable()  
       $("[data-­‐comments]").comments()  
    }  
    !
    //  Setup  checkout  page  
    if  ($('body').is('.page-­‐checkout'))  {  
       $("[data-­‐draggable]").draggable()  
       $("[data-­‐datepicker]").datepicker()  
    }

    View full-size slide

  100. Web Components, Angular.js e Dojo
    usam o HTML como referência para
    instanciar componentes

    View full-size slide

  101. Definindo 

    componentes com
    Piecemaker
    https://github.com/jcemer/

    piecemaker

    View full-size slide

  102. Definição de um
    componente
     
       Mediabox  content  

    index.html

    View full-size slide

  103. define(function  ()  {  
       function  Mediabox(container)  {  
           //  ...  
       }  
       return  Mediabox;  
    });
    Chamada do construtor

    com o container
    mediabox.js

    View full-size slide

  104. 2. Data-binding

    View full-size slide

  105. Gerenciar dados no front-end não
    é tarefa simples

    View full-size slide

  106. Trabalhar com models que emitem
    eventos é trabalhoso e passível a erros
    (não entenda mal, Backbone.js)

    View full-size slide

  107. Valor: R$50,00
    Quantidade: 1
    Model 

    quantidade: 1
    script.js

    View full-size slide

  108. Valor: R$50,00
    Quantidade: 3
    Model 

    quantidade: 1
    script.js

    View full-size slide

  109. Valor: R$150,00
    Quantidade: 3
    Model 

    quantidade: 3
    script.js

    View full-size slide

  110. Valor: R$500,00
    Quantidade: 10
    Model 

    quantidade: 10
    script.js

    View full-size slide

  111. Data-binding no

    Angular

    View full-size slide

  112.  
                           ng-­‐init="quantity=1">  
           110  
         
       Valor:  R$  {{price()}}  

    index.html
    function  Basket($scope)  {  
           $scope.price  =  function  ()  {  
                   return  $scope.quantity  *  50;                      
           };  
    }
    main.js

    View full-size slide

  113. Frameworks como Angular.js,
    React, Ember e Knockout.js
    implementam data-binding

    View full-size slide

  114. A EcmaScript e a especificação do
    HTML5 estão evoluindo para
    melhor endereçar data-binding

    View full-size slide

  115. 3. Frameworks

    View full-size slide

  116. Componentes no Angular
    http://jsfiddle.net/api/post/library/pure/

    View full-size slide

  117.  
         
             
               Date:  {{  '2012-­‐04-­‐01'  |  date:'fullDate'  }}  
             
             
               Hi!  
             
         

    Tags são mapeadas
    para templates e
    controllers

    View full-size slide

  118. A partir daqui, o HTML não
    é válido e sem um pouco
    de cuidado...

    View full-size slide

  119. What’s wrong with Angular.js
    https://medium.com/este-js-framework/whats-
    wrong-with-angular-js-97b0a787f903
    What I would recommend instead of
    Angular.js?
    https://medium.com/este-js-framework/what-i-
    would-recommend-instead-of-angular-
    js-62b057d8a9e

    View full-size slide

  120. Retornar do servidor uma página
    em branco ou inválida é um
    desperdício

    View full-size slide

  121. Considere utilizar um framework
    JavaScript quando estiver escrevendo
    uma Rich Internet Application

    View full-size slide

  122. Sempre aprenda a
    fundo antes tudo o que
    for utilizar
    - bom senso

    View full-size slide

  123. Dicas finais para você que
    quer fazer código ainda
    melhor (e está acordado)
    [

    View full-size slide

  124. Estude sobre execução de
    código assíncrono com callbacks
    e promises
    https://speakerdeck.com/jcemer/controle-de-
    fluxo-com-execucao-assincrona
    1.

    View full-size slide

  125. Aceite que o JavaScript do front-end
    da sua aplicação pode dar tanto ou
    mais trabalho que o back-end
    2.

    View full-size slide

  126. ]Obrigado 

    a todos
    criem produtos incríveis
    @jcemer

    View full-size slide