Slide 1

Slide 1 text

Web Componentsで実現する Hotwireとフロントエンドフレーム ワークの橋渡し 2025.9.26 Kaigi on Rails 2025 Daichi KUDO (@da1chi24)

Slide 2

Slide 2 text

自己紹介 ● Daichi KUDO ○ GitHub @kudoas ○ Twitter @da1chi24 ● Classi 株式会社 ● Ruby歴 3年 ● Startup Angular 運営

Slide 3

Slide 3 text

https://corp.classi.jp/careers/ 「Classi」「tetoru」 は Ruby on Rails で作られています

Slide 4

Slide 4 text

この発表で伝えたいこと ● Web Components で Rails/Hotwire サービスに フロントエンドフレームワークのコンポーネントを 少しずつ導入 できること ● Web Components と Rails の 連携方法 や 活用のヒント

Slide 5

Slide 5 text

この発表の対象者 ● Hotwire に関心がある/すでに利用している人 ● フロントエンドの知識やコンポーネントの資産を 活かして開発したい人

Slide 6

Slide 6 text

この発表では話さないこと ● Hotwire とはなにか ● Hotwire での UI/UX の実現方法

Slide 7

Slide 7 text

Hotwireとは何か知りたい方はおすすめです 猫でもわかるHotwire入門 Turbo編 - zenn


Slide 8

Slide 8 text

Hotwire 実践編はこちらがおすすめです Hotwire or React? 〜Reactの録画機能をHotwireに置き換えて得られた知見〜 高度なUI/UXこそHotwireで作ろう

Slide 9

Slide 9 text

アジェンダ ● Web Components を選択した背景 ● 段階的な導入事例 ● まとめ

Slide 10

Slide 10 text

アジェンダ ● Web Components を選択した背景 ● 段階的な導入事例 ● まとめ

Slide 11

Slide 11 text

新規サービスの立ち上げ 少人数エンジニア・スピード重視

Slide 12

Slide 12 text

新規サービスの立ち上げ 少人数エンジニア・スピード重視 単一の Rails アプリで開発できる Hotwire⚡採用

Slide 13

Slide 13 text

自社サービス間のデザインを統一したい課題 サービスA サービスB サービスC 共通化のために UIコンポーネント を利用している Angular製

Slide 14

Slide 14 text

提供されるコンポーネント例 Storybook - Classi Design System 他にモーダルやカレンダー などのよく利用されるものが 用意されている

Slide 15

Slide 15 text

Classiの一般的なアーキテクチャ Angular SPA Rails API Angular UIコンポーネント Angular SPA Rails API Angular SPA Rails API

Slide 16

Slide 16 text

今回の場合 Rails + Hotwire これができれば理想 Angular UIコンポーネント

Slide 17

Slide 17 text

今回の場合 そのままテンプレートに 埋め込んでも動かない Rails + Hotwire Angular UIコンポーネント

Slide 18

Slide 18 text

今回の場合 Angular UIコンポーネント Angular Rails + Hotwire サービスで管理するものを 増やしたくない

Slide 19

Slide 19 text

橋渡し役の Web Components を採用した Rails + Hotwire Web Components Angular UIコンポーネント

Slide 20

Slide 20 text

Web Components とは Web標準に基づく 新しいカスタムの、再利用可能な、カプセル化された HTMLタグを作成できる Webプラットフォーム APIのセット Introduction - webcomponents.org

Slide 21

Slide 21 text

Custom Element(カスタム要素) 任意の振る舞いを定義したクラスでHTML要素を登録 UIコンポーネントを HTML要素 として使える カスタム要素の使用 - Web API | MDN JavaScript

Slide 22

Slide 22 text

HTML要素なので Hotwire と共存できる サーバーで HTML をレスポンスする 名前: Daichi KUDO メール: example@com テンプレート(ERB)

Slide 23

Slide 23 text

Railsと疎結合で変更に強い HTML標準の インターフェース でやり取りする Rails + Hotwire Web Components Angular UIコンポーネント

Slide 24

Slide 24 text

アジェンダ ● Web Components を選択した背景 ● 段階的な導入事例 ● まとめ

Slide 25

Slide 25 text

コンポーネントを Web Components に変換 Rails + Hotwire Web Components Angular UIコンポーネント

Slide 26

Slide 26 text

コンポーネントを Web Components に変換 Web Components (Custom Element) フロントエンド コンポーネント Rails起動時に登録 フレームワーク・ライブラリ

Slide 27

Slide 27 text

コンポーネントを Web Components に変換 HTML属性/DOMプロパティ Custom Event 入力 出力 Web Components (Custom Element) 変換する実装の詳細はこの発表では割愛します フロントエンド コンポーネント インターフェースは Web標準にマッピング

Slide 28

Slide 28 text

Angular UIコンポーネント Web Components を Rails に導入する Rails + Hotwire Web Components Web Components

Slide 29

Slide 29 text

※実際のサービスに存在する画面ではありません この画面を題材に導入します

Slide 30

Slide 30 text

段階的な導入事例 ● 相互作用しない独立したもの ● Railsからデータを連携するもの ● ユーザー入力を連携するもの シンプルなものから 複雑なものの順に導入します

Slide 31

Slide 31 text

段階的な導入事例 ● 相互作用しない独立したもの ● Railsからデータを連携するもの ● ユーザー入力を連携するもの シンプルなものから 複雑なものの順に導入します

Slide 32

Slide 32 text

アイコン フッター

Slide 33

Slide 33 text

● 標準のHTML要素と同じ ● HTML属性も設定できる 利用方法

Slide 34

Slide 34 text

これだけで導入完了

Slide 35

Slide 35 text

段階的な導入事例 ● 相互作用しない独立したもの ● Railsからデータを連携するもの ● ユーザー入力を連携するもの

Slide 36

Slide 36 text

ヘッダー エラーメッセージ

Slide 37

Slide 37 text

ユーザー情報(ハッシュ) 学校名(文字列) エラーメッセージ(文字列) 表示切り替え(真偽値)

Slide 38

Slide 38 text

Custom Elementへのデータの渡し方 app/views/layouts/application.html.erb

Slide 39

Slide 39 text

Custom Elementへのデータの渡し方 app/views/layouts/application.html.erb HTML属性で渡す 文字列のみ・宣言的

Slide 40

Slide 40 text

Custom Elementへのデータの渡し方 app/views/layouts/application.html.erb DOMプロパティで渡す 柔軟なデータ型・命令的

Slide 41

Slide 41 text

Custom Elementへのデータの渡し方 JSONに変換してエスケープを外す ⚠注意が必要 ⚠ app/views/layouts/application.html.erb

Slide 42

Slide 42 text

ユーザー入力が含まれる場合の脆弱性 Restrictions for contents of script elements - HTML Standard 任意のDOMを挿入できる で script タグを強制終了

Slide 43

Slide 43 text

カスタムデータ属性を利用した安全な渡し方 JSONをエスケープして データ属性に渡す データ属性をパースする Embedding custom non-visible data with the data-* attributes - HTML Standard

Slide 44

Slide 44 text

サービスの骨格が完成

Slide 45

Slide 45 text

段階的な導入事例 ● 相互作用しない独立したもの ● Railsからデータを連携するもの ● ユーザー入力を連携するもの

Slide 46

Slide 46 text

日付入力要素

Slide 47

Slide 47 text

1.2 フォーム要素を生成するヘルパー form_with で生成されるフォームビルダーオブジェクトには、 「テキストフィールド」「チェックボックス」「ラジオボタン」などの一般的な フォーム要素を生成するためのヘルパーメソッドが多数用意されていま す。 通常 Rails でフォームを組み立てる場合 フォーム要素を生成するヘルパー - Railsガイド

Slide 48

Slide 48 text

フォームヘルパーとモデルの連携 Userモデルに紐づいたフォーム

Slide 49

Slide 49 text

フォームヘルパーとモデルの連携 Userモデルに紐づいたフォーム Railsの規約に基づいた HTML属性を付与 生成される HTML フォーム入力の命名規約とparamsハッシュ - Railsガイド

Slide 50

Slide 50 text

最初に試したこと:カレンダーだけを導入する 日付イベント発火 Custom Element フォームヘルパーの input 要素 日付クリック 👇 Custom Event

Slide 51

Slide 51 text

フォームとカレンダーの連携 Custom Element Custom Event の連携 雰囲気だけ見てください

Slide 52

Slide 52 text

フォームとカレンダーの連携 雰囲気だけ見てください 赤い部分が連携のための実装

Slide 53

Slide 53 text

フォームとカレンダーの連携 雰囲気だけ見てください 赤い部分が連携のための実装 毎回連携するのが面倒

Slide 54

Slide 54 text

理由:再利用する単位が間違っていた カレンダー input要素 Rails モデル 面倒なポイント フォームヘルパー Custom Element

Slide 55

Slide 55 text

本来こうした方が再利用しやすい カレンダー input要素 Rails モデル フォームヘルパー Custom Element 日付入力要素として1 つにまとめる

Slide 56

Slide 56 text

目指す形:フォームヘルパーだけで導入できる UI Model連携 フォームバリデーション 機能 デザイン

Slide 57

Slide 57 text

Custom Elements を1つにまとめる デザイン カレンダーと input 要素を 1つにする Custom Element 属性 を input 要素に連携する ステップ1

Slide 58

Slide 58 text

Custom Elements を1つにまとめる デザイン Custom Element 属性 を input 要素に連携する input 要素と 同じ属性を設定できるように するのがポイント ステップ1

Slide 59

Slide 59 text

フォームヘルパーと連携する フォームビルダーをカスタマイズする - Railsガイド フォームビルダーを カスタマイズして ヘルパーを追加できる ステップ2

Slide 60

Slide 60 text

Custom Elment フォームヘルパーを上書きして input を差し替え input 要素の属性を引き継いで Custom Element に差し替える 既存の input 要素 ステップ2

Slide 61

Slide 61 text

フォームビルダー (MyFormBuilder)の実装例

Slide 62

Slide 62 text

フォームビルダー( MyFormBuilder)の実装例 作成した Custom Element に input要素の属性を詰め替える

Slide 63

Slide 63 text

フォームビルダー( MyFormBuilder)の実装例 インターフェースが同じなのでシンプル 作成した Custom Element に input要素の属性を詰め替える

Slide 64

Slide 64 text

builderオプションで 自動的に処理を引き継げる Custom Element を利用するヘルパーが完成 共通で適用したい場合 ActionView::Base.default_form_builder

Slide 65

Slide 65 text

一通り導入完了

Slide 66

Slide 66 text

アジェンダ ● Web Componentsを選択した背景 ● 段階的な導入事例 ● まとめ

Slide 67

Slide 67 text

まとめ ● Web Componentsを利用した事例の紹介 ○ Custom Element とRails は Web標準の仕様で連携可能 ● 利用のヒント ○ シンプルなものから少しずつ導入する ○ カスタムデータ属性で安全にデータを渡す ○ 利用しやすい単位で Custom Element を再設計する ○ Rails の書き味を変えない工夫

Slide 68

Slide 68 text

ご清聴ありがとうございました EOL 2025.9.26 Kaigi on Rails 2025 Daichi KUDO (@da1chi24)