この記事は Agent Grow Advent Calendar 2021 9 日目の記事です。
初めまして。エージェントグローでRuby案件に参画させていただいているKasanoと申します。
以下ツイートより、2021年11月時点ではエージェントグローではRuby(Ruby on Rails)をやっている人は少数派ですが、今回は敢えてRails7の新機能を取り上げてみたいと思います。
エージェントグローの技術者割合、超最新版の作成が完了いたしました。更新日が書かれていない方が最新です!
オブジェクト指向言語が圧倒的に多いですね。Pythonはやはり少ないが、去年と比較して0.7%アップ。 pic.twitter.com/fAotDSLbRZ
— フェアネス伊藤@採用担当 (@atsu_itou) November 23, 2021
基本的にちょっとはRailsを知っている人向けの内容となりますが、Railsを知らない方やちょこっと触ったことがあるという方にも「ほーん。Railsって今そんなことになってのかぁ。」って思っていただければ幸いでございます。
Rails7について
Railsは言わずと知れたRubyの代表的なフレームワークです。
執筆中の2021年12月頭時点で、まだアルファ版ですがrail7.0.0.alpha2
が最新バージョンです。Rails7では主にフロントエンドの管理方法で大きな変化がありましたので、そちらの一部を紹介させていただこうと思います。
さて、Railsのフロントエンド事情の歴史的な経緯も含めた詳細についてはこちらのwantedlyさんのエンジニアさんが書かれた記事が詳しいのですがちょっとハードルが高い……ので、筆者の目線でRails7における変更点を超ざっくり説明します!
従来のようにnode_modulesディレクトリ以下にパッケージをダウンロードして、webpackなどでビルドするような方法1)従来の方法を使い続けることも可能とは別のアプローチで、フロントエンドのパッケージを使うことができるようになります。
この方法だとなんとnodeやnpm自体不要です。なかなかファンキーな変更ですね。これを実現するのに一役買っているのがimportmapです。
importmapってなに
importmapとは何なのでしょうか。
importmapとは別にRailsに限った話ではありません。2)実際、Next.jsなんかでもimportmapが使えるようにする機能がリリースされるとか。
この言い方は正確ではない気がしますが最初のうちは「HTTPの機能」という認識でいい思います。この点は筆者がごちゃごちゃ説明するよりも以下の先人のお知恵をご覧いただいた方が賢明です。
〜以下、後者のブログより引用〜
Import maps はこれまでの Node.js や webpack などの module bundler を用いた開発体験のようにimport _ from ‘lodash’とパッケージ名だけ指定する import を使い続けつつ ES Modules の世界観に引っ越しできる緩衝材みたいなものだと思えばおおむね合ってると思います。
〜引用終わり〜
何はともあれRails7ではimportmap-railsというgem3)Rubyのライブラリのことのお力により、Railsでimportmap機能を簡単に使えるようにしてくれるものです。
これによってブラウザが指定したパッケージをCDN経由でロードして使えるようにしてくれます。
サンプルコード
はい。説明するより実際に動かして見ていただくのが一番良いでしょう。
今回使うサンプルコードを★こちら★に用意しました。どうぞgit cloneして見てやってください。環境は以下の通りです。(別途、anyenvなどでruby 3.0.1の用意をお願いいたします。)
- Rails 7.0.0.alpha2
- Ruby 3.0.1
git cloneしたらコマンド
$ rails s -b 0.0.0.0
を実行し、ブラウザからlocalhost:3000へアクセスしてみましょう。
すると、以下のように Item1 〜 Item4 についてドラッグ&ドロップでソートができるようになっています。これはsortable.jsというjsのライブラリが使えているためです。sortable.js自体の細かい説明は割愛します。
従来のやり方でsortablejsを使う場合は、
$ npm install sortablejs
とコマンドを叩いてnode_modulesディレクトリ以下にsortable.jsがダウンロードされ、自プロジェクトで使う場合はそれを使うのが一般的でしょう。
しかし今回のサンプルコードを見ても、npm installに使うpackage.jsonはどこにもありません。node_modulesディレクトリは通常gitignoreに設定されるので無くて当然
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js">
みたいな単にHTMLにCDNを埋め込んでいるコードもありません。ではsortable.jsは一体どこから取ってきて利用しているのでしょうか?
その答えは、サンプルコードの
にあります。
app/views/layouts/application.html.erbの
<%=javascript_importmap_tags%>
で、importmap.rbに記載されている各パッケージをincludeしてくれています。sortablejsはCDN経由でブラウザが取得してくれて使えるようにしてくれているんです。
<script type="importmap"...
というのがあります。これがimportmapの正体です。$ bin/importmap pin <パッケージ名>
config/importmap.rb
に追加されます。依存するパッケージがあればそれも一緒に追加してくれます。<script type="importmap">
にパッケージを書くこと「ピン留め」というため、このような名前になっているようです。import _ from 'sortable.js'
とするだけでsortablejsを使うことができます。結局importmapって何のメリットがあるの?
①HTTP2の仕様により通信のパフォーマンスが良くなりユーザー体験の向上に繋がる
webpackとかのバンドラーで作った大きいサイズのjsファイルを1つどーんと送るより、小さいサイズのファイルをHTTP2による1ストリームで何個も送る方が高速らしいです。が、そんなに高速にならないという反論もあるので実際のところはまだよくわからないという印象です。
②開発時にいちいちフロントエンドのファイルをビルドしなくていい
webpackとかdev-server起動しておいてjsファイルを更新するたびに再ビルドする必要がありますからね、それに時間を取られないのは逆に新鮮です。
importmap-railsの問題点?
認識している問題点は以下3つです
① 更新の必要があるパッケージがわからない
npmやyarnでのパッケージ管理では、auditやoutdatedというサブコマンドで脆弱性が見つかったパッケージや、更新できるパッケージを簡単に探すことができます。これによってシステムの脆弱性対応など担保できるので筆者もよく使っております。しかしimportmap-railsでは調べた限りそのような機能がまだ無いようです。一応importmap-railsのissueにはこの問題が上がっておりなんとかしようとしてくれているようです。CDNを使う前提だとローカルにそのパッケージがあるわけでは無いこともあり、なかなかこの辺りの解決が一筋縄ではいかないようですね。。。
②そもそも比較的新しいブラウザでないとimportmapは使えない
古いバージョンのブラウザだと使えないようです。(このあたりの対応状況に関するわかりやすい資料が見つからなかった)
③ReactやTypescriptなどは結局トランスパイルが必要
importmapでReactを動かすのはDHHさん4)Railsを作ったすごい人がどっかでデモしてくれてた気がしますが、正式には難しいようです。
ですので、暫くはwebpackやsprocketsなどでjsをビルドしてincludeする従来の手法がまだまだ現役だろうなぁという印象です。あとはCDNから使うのってセキュリティ的に大丈夫なん?という人も一定数いるような気がします。
さいごに
以上、駆け足になりましたがRails7 × importmapの紹介でした。importmapがバンバン使われるようになるのはまだ先の話だと思いますが、新しい技術を早めにキャッチアップして選択肢として知っておくことは重要ですよね。これからも情報収集を怠らずに精進して参ります。
なお、冒頭に記載した通りエージェントグローではRubyist募集中です!もちろんRubyist以外のエンジニアさんも募集しております。 🙂
以上、ありがとうございました。