やりたいこと
- es6を使う。coffee scriptとはサヨナラ〜
- bootstrapを使う。
- bootstrap datetimepickerを使う。(追記)
- font-awesomeを使う。
- webpackでjs、css(scss、sass)ファイルを管理する。
bootstrapはjqueryに依存しているので、jqueryも設置します。
jqueryに依存してないbootstrap.nativeもあるが、既存の資産でjqueryを使うところが多いので、しばらくはjqueryとes6を共存した方がいいと思いました。
作業者がjqueryには慣れているが、es6には慣れてないことも1つの理由です。
bootstrap datetimepicker(追記:2017年12月20日)
bootstrap datetimepickerを使う場合は、Eonasdanのbootstrap datetimepickerではなくこれをforkしてbootstrap4用に直したbootstrap4-datetimepickerを使います。
% yarn add bootstrap4-datetimepicker
そして、application.jsやapplication.cssに追加します。
... snip ...
import 'bootstrap/dist/js/bootstrap'
import 'moment/moment'
import 'bootstrap4-datetimepicker/src/js/bootstrap-datetimepicker'
import 'moment/locale/ja'
Eonasdanのbootstrap datetimepickerはbootstrap3に合わせたものでbootstrap4で使うとカレンダーは表示されませんでした。時間設定の部分は表示されます。
moment/locale/jaはカレンダーを日本語化してくれるものです。
... snip ...
@import '~bootstrap4-datetimepicker/build/css/bootstrap-datetimepicker';
jsとcssを読み込む経路が異なります。気をつけてください。
rails-ujs(追記:2017年12月20日)
link_toでmethod: :deleteが効かない場合があります。
ruby on rails 5.0まではjqueryに依存していてこれはjquery-ujsで処理してくれるものでしたが、5.1以降ではもうjqueryに依存していないので、純粋なjavascriptで書いたrails-ujsを使います。
% yarn add rails-ujs
application.jsにも追加します。
... snip ...
import Rails from 'rails-ujs'
Rails.start()
プロジェクトの生成
% rails new sample -B -C -S -T --skip-coffee --skip-turbolinks --webpack -d mysql
オプションの説明はrailsだけを叩くと表示されるので、簡単に説明します。
-Bはプロジェクト生成と共にbundle installすることをスキップします。
-CはAction Cableをスキップします。
-SはSprocketsをスキップします。
-Tはminitestをスキップします。私はRSpecの方なので、スキップしますが、minitestが良いならスルーしてください。
--skip-coffeeはcoffee scriptをスキップします。es6を使います。
--skip-turbolinksはturbolinksをスキップします。最初から使ったことないです。
--webpackはSprocketsの代わりにwebpackを使います。
-d mysqlはデータベースとしてmysql(mariadb)を使います。
ライブラリの設置
group :development do
... snip ...
gem 'pry-rails'
gem 'annotation'
gem 'foreman'
end
pry-railsとannotationはあった方がいいですね。
webpackを使う場合、railsのアプリケーションサーバーだけではなくwebpack-dev-serverなども起動しなければなりません。
開発環境でそれぞれ起動することは面倒なので、一緒に起動するためにforemanを使います。個人的には5年ぶりに使いますが、まだ残されていました。
この以外にも開発に役に立つgemはもっとありますが、この記事では「やりたいこと」に集中したいと思うので、この位で始めます。
% cd sample
% bundle install --path vendor/bundle
私はrbenvとrbenv-gemsetを使っていますが、開発環境ではvendor/bundleにgemを設置しています。
多数のrailsバージョンやgemを設置することが多く、一種の習慣みたいになりました。
vimとctagsでomni補完機能を使っていてGemfile.tagsのファイルサイズを最小化するためです。
プロジェクトごとに使っているgemが異なるので、管理的な面でもこうした方がいいです。
vendor/bundleは容量が大きくなりやすいので、バージョン管理の対象外にしましょう。
次はwebpackerを設置します。webpackerはwebpackをrailsで利用するために作られました。
これからjsライブラリの管理にはwebpackを使います。
% rails webpacker:install
npmの代わりにyarnを利用してbootstrapとfont-awesome、bootstrapの依存パッケージであるjqueryとtether、popper.jsなどを設置します。
bootstrapの場合、バージョンを明示しないとbetaバージョンが設置されますが、色々と異なる部分がありましてややこしくなるので、alphaバージョンの最新バージョンを設置します。
% yarn add bootstrap@4.0.0-alpha.6 font-awesome jquery tether popper.js
設定
Sprocketsを使う場合はAsset pipelineを使う時と同じ手順なので、assetsの配下でjsやcssを管理しますが、webpackの場合はjavascriptの配下で管理することになります。
app
├── assets
│ ├── config
│ │ └── manifest.js
│ ├── images
│ ├── javascripts
│ │ └── application.js
│ └── stylesheets
│ └── application.css
├── javascript
│ ├── packs
│ │ └── application.js
│ └── stylesheets
│ └── application.scss
├
「app/javascript/stylesheets」は私が改めて追加したことなので、好みのディレクトリ名で作って使ってください。
@import '~bootstrap/dist/css/bootstrap';
$fa-font-path: "~font-awesome/fonts";
@import '~font-awesome/scss/font-awesome';
「$fa-font-path: "~font-awesome/fonts";」がない場合、fontを見つかりませんというエラーが表示されます。
githubのwebpackerのissuesで見つけました。
次はapplication.jsです。
/* eslint no-console:0 */
// 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.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
console.log('Hello World from Webpacker')
import 'stylesheets/application'
import 'bootstrap/dist/js/bootstrap'
webpackの場合は「webpack.config.js」設定ファイルを使っていますが、webpackerでは「config/webpack/environment.js」になります。
環境ごとにdevelopment.js、test.js、production.jsファイルが用意されていますが、これらのファイルはenvironment.jsファイルを読み込みます。
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
Tether: 'tether',
'window.Tether': 'tether',
Popper: ['popper.js', 'default']
})
)
module.exports = environment
$やjQueryなどよく使われるaliasを全部指定する必要があります。
Tetherの場合も同様です。
webpackの処理によるoutputはapplication.jsとapplication.cssです。
これらのoutputでレイアウトファイルを修正しましょう。
<!DOCTYPE html>
<html>
<head>
<title>Sample</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<%= csrf_meta_tags %>
<%= stylesheet_pack_tag 'application', media: 'all' %>
<%= javascript_pack_tag 'application' %>
</head>
<body>
<%= yield %>
</body>
</html>
stylesheet_link_tagとjavascript_include_tagの代わりにstylesheet_pack_tagとjavascript_pack_tagを使っていることに注目してください。
起動
railsのアプリケーションサーバーとwebpack-dev-serverをまとめて起動するためにforemanを利用します。
foremanを利用するためには設定ファイルが必要で、デフォルトの設定ファイルの名前がProcfileです。
他の名前にする場合は、オプションで指定する必要があります。
rails: rails s -p 3000
webpack: bin/webpack-dev-server
次のコマンドで実行すると、puma(railsのアプリケーションサーバー)とwebpack-dev-serverが一緒に起動されます。
% bundle exec foreman start
因みに、以下のようにする場合は起動できませんでした。
% bundle binstubs foreman
% bin/foreman start
確認
bootstrapがちゃんと表示されるのか確認してみましょう。
まず適当なcontrollerとviewファイルを作ります。
% rails g controller hello world
generatorで生成したworld.html.erbを開いて、下記のように入力してください。
<div class='container-fluid'>
<div class='row'>
<i class="fa fa-exclamation-triangle fa-3x"></i>
</div>
<div class="alert alert-success" role="alert">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
<div class="alert alert-info" role="alert">
<strong>Heads up!</strong> This alert needs your attention, but it's not super important.
</div>
<div class="alert alert-warning" role="alert">
<strong>Warning!</strong> Better check yourself, you're not looking too good.
</div>
<div class="alert alert-danger" role="alert">
<strong>Oh snap!</strong> Change a few things up and try submitting again.
</div>
<div class='row'>
<i class="fa fa-list fa-3x"></i>
</div>
<!-- Provides extra visual weight and identifies the primary action in a set of buttons -->
<button type="button" class="btn btn-primary">Primary</button>
<!-- Secondary, outline button -->
<button type="button" class="btn btn-secondary">Secondary</button>
<!-- Indicates a successful or positive action -->
<button type="button" class="btn btn-success">Success</button>
<!-- Contextual button for informational alert messages -->
<button type="button" class="btn btn-info">Info</button>
<!-- Indicates caution should be taken with this action -->
<button type="button" class="btn btn-warning">Warning</button>
<!-- Indicates a dangerous or potentially negative action -->
<button type="button" class="btn btn-danger">Danger</button>
<!-- Deemphasize a button by making it look like a link while maintaining button behavior -->
<button type="button" class="btn btn-link">Link</button>
</div>
タイピングする必要はありません。
bootstrapのサイトでexampleが用意されているので、コピペしてください。
- https://v4-alpha.getbootstrap.com/components/alerts/#examples
- https://v4-alpha.getbootstrap.com/components/buttons/#examples
font-awesomeのサイトにもexampleが用意されているので、ご参照ください。
綺麗に表示されました。
画面サイズを変更して見ましょう。
Developer Toolsのconsoleにてエラーがないことも確認してください。