本記事はこんな方に向けて書いています。
・RailsでJavascript / CSSのファイルが読み込まれる仕組みを知りたい人
・application.jsにある「=require_tree .」の謎を知りたい人
・マニフェストについて知りたい人
今回はRailsでどのようにしてJavascriptやCSSのファイルが読み込まれるのか解説していきます。この仕組みを知ることで、「はあ?Javascriptのコード書いたのに動かないんだけど!」「CSS効かなくね?」という不具合が起きにくくなります。
Contents
『アセット(=Asset)』とは、JavascriptやCSS、画像データをまとめたものを指します。Railsで用意されている『Sprocket』というライブラリが、アセットを読み込むことでJavascriptが動いたり、画像が読み込まれます。
「読み込むファイルのリスト」に基づき、Sprocketはアセットを読み込みます。「読み込むファイルのリスト」が『マニフェスト』です。
Railsには、デフォルトで2つのマニフェストが用意されています。そのため、皆さんは「マニフェスト作らなきゃ!」なんて意識する必要もありません。
2つのマニフェストとは、下記ファイルのことを言います。
- /app / assets / javascripts / application.js
- /app / assets / stylesheets / application.js
- Javascript / CSSのバンドル(まとめる)はSprocketを使用
- 画像は / app /assets /imagesに格納
この2つのファイルの中身に基づいて、Sprocketはアセットを読み込んでくれます。またSprocketはassetsフォルダ配下のJavascriptとCSSファイルを1つにまとめたもの&assets / images配下の画像を / publicフォルダ配下にコピーします。
ただ、ここまでの話はあくまでRails 5での話です!!
最新のRails 6では、マニフェストファイルの場所やアセットファイルの取り扱いがSprocketからWebpackerに切り替わっています。
- /app / javascripts / packs / application.js(変更)
- /app / assets / stylesheets / application.js
- Javascriptの読み込みはSprocketからWebpacker(変更)
- 画像は / app /assets /imagesに格納
特にJavascriptを読み込む方法やマニフェストの書き方は、Rails5とRails6で大きく違うので注意です!
例えばマニフェストファイルの書き方をみてみましょう。
[Rails5の場合]
/app / assets / javascripts / application.jsの内容
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
[Rails6の場合]
/app / javascripts / packs / application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
Turbolinks.start()
ActiveStorage.start()
これだけみてもマニフェストファイルの書き方や内容が大きく変更されていることが分かります。
Rails5の場合、JavascriptのバンドルはSprocketが行っていたので、Sprocketの独特な記法(//= require)が使われています。
しかしRails6の場合、JavascriptのバンドルはWebpackerが行うので、「import」や「require」を使います。
この違いを知らないと割とハマりやすいので要注意です!
次の章からマニフェストファイルの中身を詳しく解説していきます。
ではRails6版のapplication.jsを見てみましょう。
アプリを作成した段階で、下記の内容が書かれています。
コードには分かりやすいように、コメントを入れています。
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
// rails-ujsの読み込み
import Rails from "@rails/ujs"
// turbolinksの読み込み
import Turbolinks from "turbolinks"
// activestorageの読み込み
import * as ActiveStorage from "@rails/activestorage"
// actioncableの読み込み
import "channels"
// 上で読み込んだものを起動
Rails.start()
Turbolinks.start()
ActiveStorage.start()
上のようにimportを使う場合もあれば、requireでかかれることもありますが意味としては同じです。
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
次にRails 6版のapplication.cssを見てみましょう。
*= require_tree .
*= require_self
application.cssはSprocketによってバンドルされます。そのためSprocketの「=require」という形で読み込みを行っています。
「=require_tree .」は/ app / assets / stylesheets以下のスタイルシートフォルダを読み込むという意味になります。
「=require_self」は自分自身(application.css)を読み込むという意味になります。
次はViewでapplication.jsやapplication.cssを読み込む方法について解説していきます。読み込む場所は、/ app / views /layouts /application.html.erbです。
デフォルトでは下記のような内容になっています。
<!DOCTYPE html>
<html>
<head>
<title>SampleApp</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
</body>
</html>
スタイルシートの読み込みについて知ろう
まずCSS(スタイルシート)は、「stylesheet_link_tag ‘ファイル名’」によって読み込まれます。CSSのフォルダは/app / assets / stylesheets配下におくので、Sprocketによりバンドルされることになります。
仮に/ app / assets / javascriptsフォルダ配下にスタイルシートのファイルを置いた場合、Webpackerによりバンドルされます。その場合は、「stylesheet_pack_tag ‘ファイル名’」で読み込む必要があります。
「stylesheet_link_tag ‘ファイル名’」と「stylesheet_pack_tag ‘ファイル名’」はおなじみの「<link rel=”stylesheet” href=”XXX”>」の形に変換されます。
Javascriptの読み込みについて知ろう
一方でJavascriptのフォルダはRails 6では、assets / javascripts / packsフォルダ配下におくのでWebpackerによりバンドルされます。
その場合は「javascript_pack_tag ‘ファイル名’」メソッドにより、javascriptファイルを読み込むことになります。
Rails5のように、/ app / assets / javascriptsフォルダにjavascriptファイルを置いた場合、バンドルはSprocketが行うので、「javascript_include_tag ‘ファイル名’」と表記が変わるので、ファイルの置き場所は非常に重要になります。
「javascript_pack_tag ‘ファイル名’」と「javascript_include_tag ‘ファイル名’」は最終的に、おなじみの「<script src=”XXXX”></script>」に変換されます。
これまでの話を最後にまとめておきます。
ファイルの置き場を変えると、読み込み方が変わるので注意して扱いましょう!!
[Stylesheetのバンドル]
・Stylesheetのファイルが/app / assets / stylesheets配下
ファイルはSprocketによりバンドルされる。
読み込みは、「stylesheet_link_tag ‘ファイル名’」
・Stylesheetのファイルが/app / assets / javascripts / packs配下
ファイルはWebpackerによりバンドルされる。
読み込みは、「stylesheet_pack_tag ‘ファイル名’」
[Javascriptのバンドル]
・Javascriptのファイルが/app / assets / javascript配下
ファイルはSprocketによりバンドルされる。
読み込みは、「javascript_include_tag ‘ファイル名’」
・javascriptのファイルが/app / assets / javascripts / packs配下
ファイルはWebpackerによりバンドルされる。
読み込みは、「javascript_pack_tag ‘ファイル名’」
コメントを残す