07 July 2014

    自宅サーバーにdeployment

    TweetWatchがとりあえず完成したので、自鯖(Apatch)で動かしてみたらjQueryの一部(画面描画時$(document).ready()の処理だけ)が上手く動かなかったので動くようになったまでの顛末を書きます(Rails 4.0.2, ruby 2.0.0p353)。
    コードは以下の通りです

    #app/assets/javascripts/users.js
    $(document).ready(function(){
        $.ajax({
            url: '/tweets/check', 
            data: {},
            dataType: "script"
        }).done(function(data, status, xhr) {
        }).fail(function(xhr, status, error) {
            alert('Error Occured(' + error + ')');
        });
    });
    

    処理の内容はあまり関係ないと思いますが、jQueryからcontrollerのメソッドを呼び出し、サーバースクリプトが動いているかどうかをチェックして画面にstatusを表示する処理をしています。このusers.jsがdevelopment環境では動くのにproduction環境では動かないという現象に悩まされました。動くようになるまでに辿った作業を順に箇条書きにしてみると以下のようになります。

    1. Apache+Passenger環境でうまく動かないので、以下の設定でwebrickでproduction環境を試す。特にwebrick用の設定とも言えるserve_static_assets = trueがdevelopment環境との大きな違い

    
        #config/environments/production.rb
        config.assets.compile = false
        config.assets.js_compressor = :uglifier
        config.serve_static_assets = true
        config.assets.digest = true
        config.assets.debug = true
    

    rake assets:precompile RAILS_ENV=production
    rails s -e production

    2. 変化が無かったのでjquery-turbolinks gemを追加してみる

    
        #Gemfile
        gem 'jquery-turbolinks'  <- 追加
    

    bundle install

    
        #app/assets/javascripts/application.js
    //= require jquery
    //= require jquery_ujs
    //= require bootstrap
    //= require users.js
    //= require turbolinks
    //= require jquery.turbolinks     <- 追加
    //= require highcharts/highcharts
    //= require highcharts/highcharts-more
    //= require highcharts/highstock
    //= require_tree .
    

    rake assets:precompile RAILS_ENV=production
    rails s -e production

    ※<a href=https://github.com/kossnocorp/jquery.turbolinks/blob/master/README.md>jquery-turbolinksのドキュメント</a>

    3. jquery-turbolinks gemを追加してもダメだったので、今度は逆にturbolinksを無効にしてみる

    
        #Gemfile
    #    gem 'turbolinks'         <- コメント化
    #    gem 'jquery-turbolinks'  <- コメント化
    
    
        #app/assets/javascripts/application.js
    //= require jquery
    //= require jquery_ujs
    //= require bootstrap
    //= require users.js
    //= require turbolinks            <- この行を削除
    //= require jquery.turbolinks     <- この行を削除
    //= require highcharts/highcharts
    //= require highcharts/highcharts-more
    //= require highcharts/highstock
    //= require_tree .
    

    bundle install

    
        #app/views/layouts/application.html.erb
        #変更前
      <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
      <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
        #変更後
      <%= stylesheet_link_tag    "application", media: "all" %>
      <%= javascript_include_tag "application" %>
    

    rake assets:precompile RAILS_ENV=production
    rails s -e production

    4. turbolinksは関係なかったので、関係ないと思ったけど今度はcoffee scriptに変えてみる

    jqueryとturbolinks両イベント対応の書き方
    
    #app/assets/javascripts/user.js.coffee
    $(document).on 'ready page:load', ->
      url = '/tweets/check'
      dfd = $.ajax
        url: url
        format: 'script'
        data: {}
        method: 'get'
      promise = dfd.promise()
      promise.done((data, status, xhr) ->
      )
      promise.fail((xhr, status, error) ->
        alert(error)
      )
    
    jqueryイベントとturbolinksイベントを分けた書き方
    
    #app/assets/javascripts/user.js.coffee
    ready = ->
      url = '/tweets/check'
      dfd = $.ajax
        url: url
        format: 'script'
        data: {}
        method: 'get'
      promise = dfd.promise()
      promise.done((data, status, xhr) ->
      )
      promise.fail((xhr, status, error) ->
        alert(error)
      )
    
    $(document).ready(ready)
    $(document).on('page:load', ready)
    

    rake assets:precompile RAILS_ENV=production
    rails s -e production

    5. どっちのcoffee scriptでもダメなので、こんどは正常に動作しているdevelopment環境の設定をproduction環境と同じにして確認。

    
        #config/environments/development.rb
        config.assets.compile = false
        config.assets.js_compressor = :uglifier
        config.serve_static_assets = true
        config.assets.digest = true
    

    デフォルトでは書かれていない上記設定をdevelopment環境の設定ファイルに追加してrails s -e developmentすると、めでたく?production環境と同じくページload時のjqueryだけが発動しない現象が再現しました。結局config.assets.compileがtrueかfalseかで動作が変わるようです。念のためdevelopment環境でconfig.assets.compileの値だけを書き換えて現象の発生の有無を確認しました。
     でも本番(production)環境でconfig.assets.compile = trueにして運用することは、重くなるので普通はしないと思いますし、結局config.assets.compile = falseのままではturbolinksの有効・無効に関係なく、このjqueryを発動させることは出来ませんでした。

    6. 何か方法はないかとテンプレートファイルに直接jqueryを直書きしてみたところ

    
    #app/views/users/show.html.erb
    <%= javascript_tag do %>
    $(document).ready(function(){
        $.ajax({
            url: '/tweets/check', 
            data: {},
            dataType: "script"
        }).done(function(data, status, xhr) {
        }).fail(function(xhr, status, error) {
            alert('Error Occured(' + error + ')');
        });
    });
    <% end %>
    

    これでdevelopment環境でもproduction環境でもページ読み込み時のjqueryが正常に動作しました。
    config.assets.compile = falseでdevelopment,production両方の環境で動きます。いろいろ環境を弄りましたが元の環境からjqueryをテンプレートに直書きするように変えるだけで他は変更しなくてよかったみたいです。turbolinksが有効でも無効でも大丈夫です

    結論
    「$document.readyイベントを使うjqueryが動作しない時は、テンプレートに直書きしてみる。」

     ※ネットの情報を漁っていると、jquery-turbolinks gemを使えば解決するというものが多いのですが、document.readyイベントに関してはそういうわけにはいかないようです。



    blog comments powered by Disqus