RailsとWebComponentsが組み合わされる事例紹介
もともとRailsを使っていたバックエンド中心のエンジニアで、あるときWebComponentsに興味があり、色々調べていたら、意外とRailsやその関連するものでWebComponentsが利用されていることがわかりました。
弊社でのWebComponentsの利用事例を交えながら、
意外とRailsとWebComponentsは組み合わせて使われているのだなということを知ってもらえると幸いです。
RailsのTubroはそもそもWebComponentsでできている
Turbo Frames Turbo StereamsでWebComponentsは利用されています。
RailsHelperではTurbo Framesは下記のように設定されますが、実態としては下記が出力されます。
<!-- Rails Helper -->
<%= turbo_frame_tag 'message_id' do %>
<h1>My message title</h1>
<p>My message content</p>
<a href="/messages/1/edit">Edit this message</a>
<% end %>
<!-- html -->
<turbo-frame id="message_1">
<h1>My message title</h1>
<p>My message content</p>
<a href="/messages/1/edit">Edit this message</a>
</turbo-frame>
また、Turbo Streamsはブロックで囲んだ内容が `<template>`タグ囲まれます。
``` html
<!-- erb -->
<%= turbo_stream.update "followers" do %>
<div id="followers">
<%= @user.followers.count %>
</div>
<% end %>
<turbo-stream action="update" target="followers">
<template>
<div id="followers">
This div will be appended to the element with the DOM ID "messages".
</div>
</template>
</turbo-stream>
後は実際にTurbo Frames, Turbo Streamsのコード見ると一目瞭然ですね。
GitHub Elements
GitHubでもRailsとTurbo、WebComponentsは活用していて、
GitHub Elementsというリポジトリがあり、GitHubや関連サービスでも利用されているようです。
OSSになっているのでよければこちらもご覧ください。
弊プロダクトでどのように使っているか
そんな感じで、フロントエンド中心のWeb開発に懐疑的な意見を持つ、RailsでもWebComponentsを活用してフロントエンドスタックが実装されていることがわかりました。
私たちのプロダクトでは、Stimulus.jsの代わりにWebComponentsを活用しています。
この時、具体的にどのようにしてWebComponentsを使ったコンポーネントを作成しているのかを記載していきます。
ちょっとした動きを実現するWebComponentsを作成する
例えば、セレクトボックスに対して下記のような簡単なWebComponentsを定義して、
query-type属性に定義されたパラメータをつけてページ遷移を行うようにしています。
このような利用方法はStimulusの代替となる利用方法かなと思っています。
export class OrderSelector extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.queryType = this.getAttribute('query-type');
this.addEventListener('change', this.onChange.bind(this));
}
onChange(e) {
const changedValue = e.target.value;
const url = new URL(window.location);
const params = new URLSearchParams(url.search);
params.set(this.queryType, changedValue);
window.location.replace(url);
}
}
<order-selector query-type="order">
<% = select_tag :order, options_for_select(@order_types, params[:order]) %>
</order-selector>
無限スクロール
一覧画面で利用するような簡単な仕様の無限スクロールもWebComponentsで実装しました。
これはDHHがgistsでStimulusで実装したものをWebComponentsで再実装したものです。
Stimulus
WebComponents
turbo-railsのようにHelperで使いやすく
WebComponentsで実装されているので、erbにタグをそのまま書いてもいいのですが、
Turbo StreamsのようにWebComponentsの内部で template
タグを使ったりしていて、
ついつい template
タグを書きそびれてしまったりということもあるので、
下記のようにRails Helperを実装しておき、Railsからも利用しやすいようにしています。
def menu_modal_content(class_name:, &block)
tag.menu_modal_content(class: class_name, data: {stop: stop}) do
tag.template do
yield
end
end
end
<%= menu_modal_content do %>
<li>
<%= link_to '編集する', edit_blog_path(blog), target: "_blank" %>
</li>
<li>
<%= link_to '非公開にする', draft_blog_path(blog), method: :post %>
</li>
<% end %>
まとめ
このように身近にWebComponentsはデザインシステムやUIの共通化意外にも存在価値があって、
意外にもRailsや周辺プロダクトで活用されていることがわかりました。
他にもRailsとWebComponentsの活用事例がありましたら教えてください!
Discussion