✅ 結論
属性 | 説明 | 実行タイミング | スクリプト順序 | HTMLパースブロック |
---|---|---|---|---|
なし | 読み込み完了後すぐ実行 | 即実行 | 保証あり | ❌ ブロックする |
async |
読み込みが終わったものから順次即実行(順序保証なし) | 読み込み完了時点で実行 | ❌ バラバラ | ❌ ブロックしない |
defer |
HTMLのパースが完了した後に全スクリプトを順番通り実行 | HTMLパース後 | ✅ 保証あり | ✅ 非ブロック |
💡 Railsにおける javascript_include_tag
の使い方
RailsでJavaScriptを読み込むときに使うのが javascript_include_tag
。
<%= javascript_include_tag "application" %>
ですが、これだけだとすぐ実行されてHTML描画がブロックされるので、モダンな構成では defer: true
を付けるのが定番です。
<%= javascript_include_tag "application", defer: true %>
また、TurboやStimulusを使う環境でも defer
は相性バツグン!
🚀 Turboとの関係(Turbo Streams / Frames)
turbo-rails
ではJavaScript実行タイミングが重要です。
-
defer: true
にすると Turbo が DOM 構築後に正常に初期化される -
async
にしてしまうと、DOM構築前にJSが実行されてTurboの初期化が失敗するリスクがある
✅ Turbo使用時は defer: true
一択!
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
✍️ Slimで書くなら?(application.html.slim)
doctype html
html lang="ja"
head
meta charset="UTF-8"
title TwitterClone
meta name="viewport" content="width=device-width,initial-scale=1"
= csrf_meta_tags
= csp_meta_tag
= stylesheet_link_tag "application", "data-turbo-track": "reload"
= javascript_include_tag "application", "data-turbo-track": "reload", defer: true
body
- flash.each do |key, message|
.alert.alert-#{key}= message
= yield
⚠️ よくある間違い
🔸 async
を使ってTurboが動かない
→ 原因:DOM構築前にJSが動いてしまう
🔸 defer
を true
にしてないことでDOMブロック
→ 結果:ページ描画が重くなる、FCP(First Contentful Paint)が遅れる
✅ まとめ:defer: true
のメリット
- ✅ ページのHTMLパースが先に進む(表示が速くなる)
- ✅ 複数JSファイルでも順番が保証される
- ✅ Turbo/Stimulusとの相性が良い
- ✅ Rails標準構成と整合性が取れる
🎁 おすすめ構成(Slim + Turbo環境)
= javascript_include_tag "application", "data-turbo-track": "reload", defer: true
この1行だけでパフォーマンス&互換性が大幅アップ!
どなたかのお役に立てば幸いです☺️