彼女からは、おいちゃんと呼ばれています

ウェブ技術や日々考えたことなどを綴っていきます

Rails 3.2 の development 環境で javascript が二重に実行されてしまうときの対処

Rails 3.2 を使っていて、development 環境で javascript が二重に実行されてしまうという問題に遭遇しました。production 環境では起きていません。

いろいろいじってみたところ、ようやく解決できたので、メモしておきます。

0. 前提

javascript は下記のように配置されているものとします。

|-- app
    |-- assets
        |-- javascript
            |-- application.js
            |-- foo.js
            `-- bar.js

application.js の中身は下記のとおり。

//= require foo
//= require bar

app/views/layouts/application.html.erb での javascript 呼び出し。

<%= javascript_include_tag "application" %>

config/environments/development.rb では、自動コンパイルする(application.js に統合させない)ように設定しています。

# Expands the lines which load the assets
config.assets.debug = true

1. 現象

アプリケーションにブラウザからアクセスして、ページのソースを表示させると、javascript の読み込み箇所は下記のようになっています。

<script src="/assets/foo.js?body=1" type="text/javascript"></script>
<script src="/assets/bar.js?body=1" type="text/javascript"></script>
<script src="/assets/application.js?body=1" type="text/javascript"></script>

foo.js も bar.js も読み込まれているにも関わらず、読み込まれた application.js の中に foo.js の内容も bar.js の内容も入っているために、あらゆる挙動が二重で行われていました。

本来であれば、読み込まれた application.js は、下記のように(コメントのみ記述されていて)内容を持たないはずです。

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//

;

2. 原因

config.assets.debug = true

と設定した development 環境のみ使っていれば public/assets は空のはずです。

しかし、同じサーバ内で production として assets:precompile したりもしていました。

そのため、public/assets 内に js を統合させた application.js が入っていて、ブラウザがそれを読み込んでいたことが今回の問題の原因でした。

3. 対策

development 環境として使うサーバと、production 環境として使うサーバを分ける。development 環境として使うサーバでは assets:precompile しないという運用にして、そのうえで、development 環境で下記の手順を行えば、解決するはずです。

1. public/asssets/application.js* を削除
2. application.js の //= の箇所を一旦削除(あとで戻すので、控えておく)
3. Web サーバ再起動
4. ブラウザからアクセス
5. application.js の //= の箇所を再度記述
6. Web サーバ再起動

以上です。

おまけ

偶然、下記の記事を見つけたのですが、上のようにやれば、config.assets.debug はそのままで大丈夫だと思います。