on Rails なフロントエンドコンポーネント指向開発（発表資料）

# はじめに
### 自己紹介
- 株式会社ユニークビジョン所属
- 前職は社内 SE → Web アプリ開発
- 転職時に Ruby on Rail を中心に Web 系の技術を習得
- 普段の仕事では Vue.js メイン


---
# 今日話すこと

---
# フロントエンド開発で得た知見を Rails での開発に活かせないか？

---
# フロントエンドをコンポーネント指向で開発できたら良いなあ...

---
# でも rail 🛤には乗っていたい。ActionView をフル活用したい。

---
# on Rails なフロントエンドコンポーネント指向開発がしたい

---
# どうやって？
- CSS を可能な限り書かない → **Tailwind on Rails**
- views / components / FormHelper の３レイヤーで考える

---
# Tailwind on Rails

---
# Tailwind CSS
- 最近流行っている [CSS ライブラリ](https://tailwindcss.com/)
- CSS をクラスで指定できる
- CSS の 99% は置き換え可能（体感値）
- CSS 管理からの解放
- **スタイルを html 上で表現できる！**

---
# CSS を書かざるを得ないとき
- [ファイルパススコープ](https://tech.basicinc.jp/articles/147)を使う
- 一番外側の要素に `data-xxxx`属性を付与

```erb:app/views/users/show.html.erb
<div data-scope-path="users/show">
  <div class="user-name">
    <%= @user.name %>
  </div>
</div>
```

```scss:app/assets/stylesheets/scopes/users/show.scss
[data-scope-path="users/show"] {
  .user-name {
    // ここに書いた CSS は users/show.html.erb のみに適用される
  }
}
```

---
# views / components / FormHelper の３レイヤーで考える

---
# Atomic Design

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/5f6f2b4a-5732-426b-ad29-4925813d1d32.png)

---
# Rails における対応
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/49065a44-b900-ac0e-23b3-0963e2d1e9fc.png)

- FormHelper [*](https://railsguides.jp/action_view_overview.html#formhelper)
    - `text_field` `options_for_select` など
- View Components [*](https://viewcomponent.org/guide/getting-started.html)
    - react にインスパイアされて誕生した Rails 謹製のコンポーネントインターフェース
- views/
    - `views/users/show.html.erb` のような従来の views ディレクトリ内のページファイル

---
# View Components
- 従来のパーシャルに近い
- パーシャルをコンポーネント志向の文脈で再解釈・拡張したもの
- [セットアップ方法](https://viewcomponent.org/guide/getting-started.html)

---
# View Components
- `rails` コマンドで作成

```shell
bin/rails generate component Example title
```

- 下記のようなファイルができる

```ruby:components/example_component.rb
class ExampleComponent < ViewComponent::Base
  def initialize(title:)
    @title = title
  end

  # このコンポーネント関連のメソッドを自由に定義できる
end
```

```erb:components/example_component.html.erb
<!-- example_component.rb のメソッドを自由に使える -->
<span title="<%= @title %>"><%= content %></span>
```

- コンポーネントを呼び出す時 

```erb:views/home/index.html.erb
<%= render(ExampleComponent.new(title: "my title")) do %>
  Hello, World!
<% end %>
```

---
# FormHelper
```ruby
label(:article, :title)
# => <label for="article_title">Title</label>

text_field(:article, :title)
# => <input type="text" id="article_title" name="article[title]" value="#{@article.title}" />
```

- これ自体が既に Atoms に相当するコンポーネント
- 便利なインターフェース
- ただし**スタイルは含まれない**
- tailwind でスタイルを毎回正確に付けるのは大変
- スタイルを上手く管理できれば完全な存在に

---
# FormHelper のスタイル問題
### どうするか
- グローバル CSS で要素ごとにスタイル定義

### なぜ？ scoped が良いのでは？
- 末端要素のスタイルはプロジェクト全体で共有する必要がある
- 基本的な HTML 要素は数が限られているため、管理の手間が爆発的に増えることはない。

### 注意点
- クラス指定のみ！
- 要素指定だと、意図しない要素にまでスタイルがついてしまう。

### Tailwind で書いてみた例
```scss:application.scss
.btn {
  @apply rounded p-1 cursor-pointer;
}

.btn-white {
  @apply btn bg-white;
}

.btn-outline-blue {
  @apply bg-white border border-blue-500 border-solid;
}

.textarea {
  @apply border border-blue-500 border-solid rounded;
}

```
---
# 時間があればデモ

---
# まとめ
- Rails も少し見方を変えるだけでコンポーネント指向的開発ができそう
- Tailwind で CSS を駆逐しよう
- どうしても CSS を使いたいときは Scoped に書こう
- グローバルな CSS は 基本的な HTML 要素に限り使用可
- ViewComponent を使っていこう