雑多開発ブログ(仮)

RailsのbootstrapでUncaught TypeError: Cannot read property 'fn' of undefined at setTransitionEndSupport エラーが発生する 他。

ローカルで動くHTML,CSS,JavascriptRailsで動かそうとしたらJSが大量にエラーを吐いていました。ChromeのF12でConsleを確認すると f:id:lilacxi:20181124151114p:plain いろいろとエラーが出てますね....。でてきたエラーは

  • Uncaught TypeError: Cannot read property 'fn' of undefined at setTransitionEndSupport - bootstrap.min.js
  • Uncaught ReferenceError: jQuery is not defined - 他js

これらのエラーは同じ原因によって発生しているようです。

原因 jQueryが読み込まれる順番が遅い

RailsではAssetspipelineによってjsやcssが一つのファイルとして纏められます。

railsguides.jp

javascriptをまとめる順番はassets/javascript/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, or any plugin's
// vendor/assets/javascripts directory 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
// compiled file. JavaScript code in this file should be added after the last require_* statement.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require_tree .

最後の//= require_tree .でassets/javascript内のjsをファイル名の順番で読み込んでいるようです。

cccabinet.jpn.org

ここを見るとbootstrapはjQueryとPopper.jsを先に読み込む必要があります。しかし//= require_tree .は名前順に読み込むので、名前がそのままだと

  1. bootstrap.js
  2. jQuery.js
  3. Popper.js

という順番で読み込まれてしまいます。どうやらこれのせいで「Uncaught TypeError: Cannot read property 'fn' of undefined at setTransitionEndSupport 」エラーは発生しているようです。以下のリンクでも同様のエラーが発生していたようです。

github.com

他のJSの「Uncaught ReferenceError: jQuery is not defined」エラーもjQueryを前提としているのにjQueryより先に読み込まれていることによるエラーのようです。

これを解消するにはapplication.jsで読み込む順番を明示してあげる必要があります。

解消方法

application.jsのrequire部分に以下のように書き加えます。

前略
//
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require jquery-min
//= require popper.min
//= require_tree .

//= require_tree .の前に//= require jquery-min //= require popper.minと書くことによってjQuery,popper.jsを読み込んだ後に他のjsファイルを読み込んでくれます。このように他のjsの前提となっているファイルは//= require_tree .の前に書くようにすればいいですね。もしくは全てのjsを順番を明示して読み込むのもアリだと思います。