Help us understand the problem. What is going on with this article?

Rails 5.1を使うならSprocketsは捨ててwebpackを使おう

More than 1 year has passed since last update.

やりたいこと

  • 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に追加します。

app/javascript/packs/application.js
... 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はカレンダーを日本語化してくれるものです。

app/javascript/stylesheets/application.css
... 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にも追加します。

app/javascript/packs/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)を使います。

ライブラリの設置

Gemfile
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」は私が改めて追加したことなので、好みのディレクトリ名で作って使ってください。

app/javascript/stylesheets/application.scss
@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で見つけました。

https://github.com/rails/webpacker/issues/619

次はapplication.jsです。

app/javascript/packs/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ファイルを読み込みます。

config/webpack/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でレイアウトファイルを修正しましょう。

app/views/layouts/application.html.erb
<!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です。
他の名前にする場合は、オプションで指定する必要があります。

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を開いて、下記のように入力してください。

app/views/hello/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が用意されているので、コピペしてください。

スクリーンショット 2017-12-14 15.56.30.png

font-awesomeのサイトにもexampleが用意されているので、ご参照ください。

http://fontawesome.io/icons/

綺麗に表示されました。

スクリーンショット 2017-12-14 16.41.23.png

画面サイズを変更して見ましょう。

スクリーンショット 2017-12-14 16.41.55.png

Developer Toolsのconsoleにてエラーがないことも確認してください。

スクリーンショット 2017-12-14 15.57.37.png

park-jh
プルスタックエンジニアになれるまで頑張ろう。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away