sinatra-assetpackをproduction環境で使う時にの注意点

執筆日:

更新日:

Sinatraアプリケーションで、JSファイルを圧縮するsinatra-assetpackを利用していて、
production環境で動作させようとしたら動かなくなってしまった問題について調査した。

起こったこと

Sinatraを使ってアプリケーションを作っていて、development環境で完成したので、 prorudction環境で動作させようとしたら、jsのエラーが出るようになってしまい、正常に動かなくなった。

アクセスすると、以下のエラーがでる。要はjqueryがないとのこと。

Uncaught ReferenceError: $ is not defined 

jQueryはもちろん読み込ませてるし、なんでproduction環境でだけこのような事象が起きたのか?

ソースコード

sinatraのメインアプリケーションであるapp.rbには以下のように、sinatra-assetpackを利用してjsを読み込んでいる。

assets do
  serve '/js', from: 'public/js'
  serve '/bower_components', from: 'bower_components'

  js :app, '/js/app.js', [
    '/js/index.js',
  ]

  js :libs, '/js/libs.js', [
    '/bower_components/jquery/dist/jquery.js',
    '/bower_components/bootstrap/dist/js/bootstrap.js',
  ]

  js_compression :jsmin
end

layout.erbにはもちろん、libs.jsが先に来るように記述している。

<%= js :libs %>
<%= js :app %>

sinatra-assetpackの挙動

productionでのみ発生する事象なので、改めてsinatra-assetpackのproduction環境時の挙動を確認した。
production環境では、複数のjsファイルを1つのファイルにまとめ、圧縮を行う。

development環境

3つのjsファイルがあったら以下のように3つ別々に読み込まれる。

<script type='text/javascript' src='/js/vendor/jquery.283479.js'></script>
<script type='text/javascript' src='/js/vendor/underscore.589491.js'></script>
<script type='text/javascript' src='/js/app/main.589491.js'></script>

production環境

3つあったjsファイルは1つにまとめられ、また圧縮される。

<script type='text/javascript' src='/js/app.589491.js'></script>

詳細はこちら
rstacruz/sinatra-assetpack · GitHub

事象の理由

ChromeデバッグツールのNetworkでファイルのダウンロード状況を確認してみると意外なことがわかった。 f:id:mosuke5:20150508171833p:plain

画像が小さくて見づらいかもしれないが、 5行目と6行目のapp.jsとlibs.jsで先にlibs.jsを読み込んでいるのに、おそらく圧縮とダウンロードに時間がかかり、
app.jsのほうが先にダウンロードが終わっている。

libs.jsにはjQueryなどが含まれていて、app.js内でjQueryを利用する。
よって、先にapp.jsが読み込まれてしまったことで、jQueryがねーぞ!と怒られてしまったのである。

対策と考慮

sinatra-assetpackなどを利用して、jsを圧縮する際には、 ファイルを1つにまとめたり圧縮したりする時間がかかることを十分に考慮しなければいけない。

あまり賢い手段をは言えないが、libs.jsとapp.jsひとつにまとめることで今回の事象は避けられる。 app.rb

assets do
  serve '/js', from: 'public/js'
  serve '/bower_components', from: 'bower_components'

  js :app, '/js/app.js', [
    '/bower_components/jquery/dist/jquery.js',
    '/bower_components/bootstrap/dist/js/bootstrap.js',
    '/js/index.js',
  ]

  js_compression :jsmin
end

また、事前に圧縮しておいて、ダウンロードだけする状態にしてもいいかもしれない。
rstacruz/sinatra-assetpack · GitHub

記事の内容に関連した相談、仕事依頼したい New

記事の内容やクラウドネイティブ技術に関する相談、仕事依頼を開始しました。
仕事依頼、相談をしてみる

フィードバック

本記事に対して、フィードバックあればこちらのフォームからご記入ください。
記事の内容にフィードバックしてみる

このエントリーをはてなブックマークに追加