まさ@ブログ書き込み中

自由に生きるための英語、プログラミング、考えごとについて色々書いています。

プロジェクトでStimulusを使って得た知見をまとめる

みなさん、こんにちは。みんなのウェディングのサーバーサイドエンジニアのまさです。

 

この記事は「くふうカンパニー Advent Calendar 2018」の22日目の記事となります。

 

この記事のテーマはStimulusです。すでにStimulusについていろんな記事があるのですが、「RailsエンジニアがJSをちょっと書くなら向いている」という風にざっくりと書かれすぎていて(当初の僕がそうだったように)よくわからなかったので、プロジェクトで3ヶ月ほどStimulusを使ってみて色々得た知見や感じたことについて書いていきたいと思います。

 

また、よくあるStimulusの使い方やサンプルコードなどは他の記事やサイトにあるので、この記事には載せていません。

 

もくじ

 

jQueryの苦い過去

まず、この記事を書いている僕のJS歴を書いておきたいと思います。

 

僕はこのプロジェクトでJSを書き始めるまでは、JSと言えばjQueryを学生の時に3ヶ月ほど仕事で書いたことくらいしかありませんでした。「jQueryで書いた」といってもとにかく目的の動作どおりに動くコードを書いただけで、責務を分けたり、拡張性を考えたコードでは全くありませんでした。そして自動テストをしていませんでした。気づけば、僕の後にコードを読むエンジニアが苦労するようなコードになっていました。

 

いまは、Stimulusを使うことでサーバーサイドエンジニアの僕でも(比較的)ReadableでTestableでFlexibleなコードを書くことができています。

 

Stimulusとは

StimulusはBasecampが作った軽量のJavaScriptフレームワークです。詳しくは公式HPや櫻井さんが今回のアドベントカレンダーの7日目に書いた記事に譲ります。

 

Stimulus: A modest JavaScript framework for the HTML you already have.

 

Rails2年目のさく氏による, stimulus試した実践ガイド - SakuraWi - BLog

 

Stimulus導入の動機

僕が所属しているみんなのウェディングでは、これまではjQueryを使ってJSのコードを書いていました。

 

そんな中エンジニアのトップである1syoさんから「jQuery依存を脱却したい」「これからはJSもテストをしていきたい」という意向を受けて、僕は新しいJSのフレームワーク(やライブラリ)を調査しました。その結果、

 

  1. テストがしやすくなる
  2. 無駄に機能コミコミのライブラリを振り回さずに済む
  3. 酷いコードが減る(酷いコードでも動いてしまうことがなくなる)
  4. Viewがすっきりする  
  5. フレームワークとして覚えることが少ない
  6. 今回のプロジェクトではそんなにゴリゴリViewを書き換えることはない

 

などの観点からStimulusを導入してみました。

 

Stimulusは綺麗なコードを書くための道を用意してくれる

Stimulusが提供するメリットはシンプルで、そのメリットが好影響を与える範囲は意外に大きなものだと思います。

 

Rails脳に合う形で責務を分けられる

Stimulusがやっていることを乱暴にまとめると処理の発火源となるHTML上のコンポーネントとStimulusのコントローラー(JS)を繋げることだけです。

 

僕は具体的な処理は生のJSで書いており、ロジックはモデルクラスに任せ、値の取得やモデルの処理を呼び出し、DOM要素の操作などはコントローラーに任せています。

 

Railsエンジニアにとってこういった設計は親しみやすいものだと思います。Fat Controllerにならないよう責務をモデルに分けることを意識することで、ユニットテストできる範囲が広がっていくという嬉しい副産物があります。

 

Viewを汚さないで済む

jQueryを使ってDOM要素のイベントへのバインディングをしていると、jQueryのためのクラスをHTML追加したりすることになってしまいます。

 

その点、StimulusはHTMLを拡張する形でStimulusのコントローラーとHTMLを繋げてくれるのでViewを汚さずに済みます。同じアクションを呼び出したいのであれば同じdata属性を追加すればいいだけです。

 

このStimulusの特性のおかげで、どのJSの処理がどのHTMLと関係しているのかを追いやすくなり、JSのコードの海にお目当の処理が埋もれていくことを防ぐことができます。

 

Stimulus Wayに乗っかるだけで学習コストを最小限に留めながら拡張性や変更がしやすく、テスタブルなJSのコードを書くことができます。

 

Stimulusのテストはどうすべきか

冒頭に述べた通りStimulusを導入した動機の1つはJSも自動テストをできるようにすることでした。もちろん当社初の試みだったため、Stimulusのどこをどうテストすべきかについても調べながら進めることになりました。

 

結論から言うと、現在はJSのテストはモデルのユニットテストに留めています。DOM要素の操作やコントローラーのテストはしていません。どちらも冗長なものになってしまうと判断したためです。

 

DOM要素のテストは多くのセットアップが必要になる上に、コントローラーのテストも自明のことをテストするようになってしまうからです。

Testing Stimulus - Stimulus Discourse

In Controller unit tests, should you unit test the HTML? - Stimulus Discourse

 

改めてわかったjQueryのいいところ

Stimulus + 生のJSで実装をしていくうちに、特に痛感したjQueryの良いところは「ブラウザ間の差分を吸収してくれる」ということです。

 

JavaScriptの関数(メソッド)の中にはブラウザによってサポートされていない、もしくは部分的にしかサポートされていないものが結構多くあります。特にIE。本当に困ってしまいます。

 

例えば、toggle()の第二引数が取れなかったり、classList.add()に複数の引数を渡せなかったり・・・。よく使うメソッドであればあるほど、生のJavaScriptでは記述量が増えてしまい、冗長になってしまいます。

 

jQueryは簡単にアニメーションを追加できる、イベント管理ができるといった面を意識してしまいがちですが、意外とこういった面においてもメリットがあるのだなと感じました。

 

Stimulusはもっと輝ける

Stimulusを導入したことで効率的に開発を進められている部分がありつつも、まだStimulusを活かしきれていないと思うところもあります。

 

それはTurbolinksとの連携です。実は、当社ではTurbolinksを利用しておりません。これを聞くとStimulusに詳しい方は「まじかよ」と思うかもしれません。

 

StimulusはDOM要素を操作することはできますが、DOMの作成を簡単にしてくれるような便利機能は備わっていません。あくまでそこにあるHTMLをいじることができるだけです。

 

反応性の高いSPAを実現するためにDOM要素を作成することをゴリゴリ行うフレームワークなどがある中でStimulusがこのようなつくりになっているのは、そういったページのレンダリングはTurbolinksに任せることを目指しているからだと言われています。

BasecampはStimulus 1.0 JavaScriptフレームワークをリリースした

 

Turbolinksを使ってレンダリングされたページにStimulusのIdentifierやDescriptorが含まれていて、それによってJSの処理がHTMLと繋がるという感じです。

 

サーバーサイド(Rails)エンジニアがRails Wayに乗っかってJavaScriptを書くことになった時に、Stimulusは本当の力を発揮することになると思います。

 

最後に

長くなりました。ここまで読んでくれた方には「RailsエンジニアがJSをちょっと書くなら向いている」といろんな記事で書いてある理由が少しはわかりやすく伝えられたかなと思っています。

 

今回の記事はここまでです。これがStimulusについて知りたい人に役に立てば幸いです。僕自身もStimulusについては勉強中の身ですので、色々間違っているところがあるかもしれませんので「こういった感じなのかもな」くらいに捉えてくれると助かります。