DockerでRailsチュートリアルのローカル開発環境構築 - WebpackでBootstrapとFont Awesomeを導入 -

# はじめに 

Dockerでローカル開発環境構築を行い、Railsチュートリアルを再走しております

- Railsチュートリアル最新版（2020.8.6現在）に対応のRails 6
- Dockerを使用し、開発環境の再現が可能
- なるべくローカル環境にインストールしない

 
今回はRailsチュートリアルの5章に相当する部分です

3章, 4章の内容は特に問題になりませんが、

5章  **5.1.2** BootstrapとカスタムCSS の部分でいよいよWebpackの沼に突入して行きます

具体的にはgemを利用せず, YarnとWebpackでBootstrapやFont Awesomeを導入、管理します

加えてテストを書くことが増えるのでその辺りをRSpecで置き換えて進めていきます

5章終了時のブランチはfilling-in-layoutです
https://github.com/dev-naokit/sample_app_on_docker/tree/filling-in-layout

第一回
[DockerでRailsチュートリアルのローカル開発環境構築（Rails 6 + PostgreSQL + Webpack) - Qiita](https://qiita.com/daddy_hacker/items/99225bf3d8665ecfdec2)

第二回
[DockerでRailsチュートリアルのローカル開発環境構築 - RSpec導入 & CircleCIでHerokuデプロイ- - Qiita](https://qiita.com/daddy_hacker/items/7036f05c0f236be8806a)

個人開発アプリ
[mdClip ＜オンラインmarkdownエディタ＞](https://mdclip.xyz/)



Dockerのコンテナ上で操作する場合はターミナルのコマンドを適宜

```
$ docker-compose run app ...
```

もしくは

```
$ docker-compose exec app ...
```

で置き換えてください。



# BootstrapとFontawesomeの導入

Rails 6ではJavaScriptのモジュールバンドラとしてWebpackが導入されていますが、
画像やCSSに関しては従来のSprocketがアセットパイプラインとして使用され、
JavaScriptのみをWebpackでコンパイルするようになっています



## application.html.erb

`<head>`の内容を書き換えます

`app/views/layouts/application.html.erb`

```erb
<head>
  <title><%= full_title(yield(:title)) %></title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  # （下の行を追記）webpackがCSSを扱えるようにする
  <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  # JavaScriptはデフォルトでwebpacerが pack フォルダをコンパイルして出力している
  <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  <!--[if lt IE 9]>
      <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js">
      </script>
    <![endif]-->
</head>
```



## YarnでBootstrapをインストール
> <追記>
**この記事のTroubleshootやこの先の記事でも触れますがBootstrapのバージョンが異なることで、CSSのセレクタやHTMLのクラスを書き直す必要が出てきます。よほどこだわりが無ければオリジナルのRailsチュートリに合わせる方が良いかと思います**
>
`yarn add`でpackegeのバージョンを指定する
>
```
yarn add package-name@1.2.3
```
>
７章のTroubleshoot
[コンテナ上のデバッグ環境構築 - DockerでRailsチュートリアルのローカル開発環境構築 - - Qiita](https://qiita.com/daddy_hacker/items/00f9f5f4b04014025d37#troubleshoot)
Yarn公式
[yarn add | Yarn](https://classic.yarnpkg.com/ja/docs/cli/add/)



`jquery`と`popper`はBootstrapに必要なパッケージ
Font Awesomeもあとで必要になるのでインストールします
（'@fortawesome'は誤字ではありません）

```
yarn add bootstrap jquery popper.js @fortawesome/fontawesome-free
```

インストールされたモジュールは
`package.json`で確認できます



## application.js

`app/javascript/packs/application.js`

以下を追記します

```javascript
require("bootstrap");
require("@fortawesome/fontawesome-free");
```

`require('jquery')`も併記するような情報もありましたが、
Bootstrapが自動的に`require('jquery')`してくれるようでココには記述不要です

私も色々不具合を検証している過程で
`require('jquery')`がなくてもjqueryがロードされることに気づいたのですが
jqueryの多重起動はJavaScriptの動作不具合につながることもあるようで、
現状はこのまま進めます

（下に参考記事を貼っておきます）



## environment.js

jQueryをどこからでも呼び出せるようにする

`config/webpack/environment.js`

```javascript
const { environment } = require('@rails/webpacker')
var webpack = require('webpack');

environment.plugins.append(
    'Provide',
    new webpack.ProvidePlugin({
        $: 'jquery/src/jquery',
        jQuery: 'jquery/src/jquery',
        Popper: ['popper.js', 'default']
    })
)

module.exports = environment
```

こうすることで毎回`import $ from 'jquery';`と書かなくて良くなるとのことです



## CSS

`app/javascript/stylesheets/application.scss`(新規作成)

以下追記

```scss
@import '@fortawesome/fontawesome-free/scss/fontawesome';
@import 'bootstrap/scss/bootstrap';
```



## application.js

`app/javascript/packs/application.js`

以下を追記します

```javascript
import '@fortawesome/fontawesome-free/js/all';
import "../stylesheets/application.scss";
```



## 参考

[Rails 6: Webpacker+Yarn+Sprocketsを十分理解してJavaScriptを書く: 前編（翻訳）｜TechRacho（テックラッチョ）〜エンジニアの「？」を「！」に〜｜BPS株式会社](https://techracho.bpsinc.jp/hachi8833/2020_01_16/85940)

[Rails 6+Webpacker開発環境をJS強者ががっつりセットアップしてみた（翻訳）｜TechRacho（テックラッチョ）〜エンジニアの「？」を「！」に〜｜BPS株式会社](https://techracho.bpsinc.jp/hachi8833/2019_11_28/83678)



# CSSの扱いについて

JavaScriptだけでなく画像やCSS、全てをWebpackでコンパイルすることも可能なようです



現状はSprocketによるアセットコンパイルと、Webpackerが共存している状況に変わりはなく

`app/javascript/stylesheets/...`をコンパイルした内容が`<head>`内の

```erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

で出力され

`app/assets/stylesheets/...`をコンパイルした内容が同じく`<head>`内の

```erb
  <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

に出力されている状況です

つまりチュートリアル通り`assets`内のCSS, SCSSを編集しても、
`packs`内のCSS, SCSSを編集してもビューに反映される状況が出来上がっています

BootstrapやFont Awesomeのstyleは後者によってimportされ、コンパイル、ビューに反映されています

今後チュートリアルをすすめる上でどちらのStylesheetを編集しても問題ないと思いますが
`<head>`内での呼び出しの順序くらいは気に留めて置いたほうがいいかもしれません

**ちなみに、`packs`内でCSSを編集する場合、`webpack-dev-server`のHot reloadの恩恵を受けられます
具体的には、変更保存した場合に自動的にブラウザがリロードされ、即座に(やや遅延あり...)変更内容を確認できます**

Railsチュートリアルの流れで`custom.scss`を作成する場合
`app/javascript/packs/application.js`に以下を記述すれば大丈夫です

```
import "../stylesheets/custom.scss";
```
（私はこの仕様で進めてみます）

# Troubleshoot
##
### Bootstrapのスタイルがおかしい
おそらくヘッダー周りが上手く表示されないと思います
Bootstrapのバージョンの違いによるものでこちらの記事の通りインストールすると
Bootstrapの最新版ver. 4.5(2020.8.7現在)が導入されます
(Railsチュートリアルでは3.4.1)

navbar-inverseというタグがBootstrap 4では使用できなくなっていますので

```html
  <header class="navbar navbar-expand-md bg-dark navbar-dark bg-dark">
```
で置き換えるなど細かな修正が必要です
修正を加えたこの章終了時のBranchを公開する予定ですが

`yarn add`の際にバージョンを指定するといった対策も可能です

## テストRSpec関連

### `assert_...`をどう書き換えるか？

そのまま使えます

[「RSpecでも assert xxx って書いてテストしたい」=> すぐできます！ - Qiita](https://qiita.com/jnchito/items/84d75aed6a797fcb7ffa)

### ApplicationHelperをテストでも使えるように...

`include ApplicationHelper`を個別の`_spec.rb`ファイルに記述

もしくは、`spec/rails_helper.rb`に記述
各`_spec.rb`でrequireされているので、個々に記述する必要はないはずです


# おわりに

この部分はRails 6環境で個人アプリ開発にあたり、最も苦労しました

身の丈に合わない内容で誤りを含むかもしれませんが

Railsチュートリアルの環境構築だけでなく、Rails 6環境でアプリ開発を行う方の一助になれば幸いです