自主的20%るぅる

各々が自主的に好き勝手書くゆるふわ会社ブログ

Rail7でのimportmapを紹介【Agent Grow Advent Calendar 2021:9日目】

この記事は Agent Grow Advent Calendar 2021 9 日目の記事です。

初めまして。エージェントグローでRuby案件に参画させていただいているKasanoと申します。

以下ツイートより、2021年11月時点ではエージェントグローではRuby(Ruby on Rails)をやっている人は少数派ですが、今回は敢えてRails7の新機能を取り上げてみたいと思います。

基本的にちょっとは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経由でブラウザが取得してくれて使えるようにしてくれているんです。

次にブラウザのデベロッパーツールなどでheadタグ内を見てみましょう。<script type="importmap"...というのがあります。これがimportmapの正体です。
Rails(importmap-rails)でimportmapによって使いたいパッケージを指定するのは以下のコマンドです。
$ bin/importmap pin <パッケージ名>
このpinコマンドで指定したパッケージがconfig/importmap.rbに追加されます。依存するパッケージがあればそれも一緒に追加してくれます。
ちなみにpinというのは<script type="importmap">にパッケージを書くこと「ピン留め」というため、このような名前になっているようです。
importmapのおかげで、import _ from 'sortable.js'とするだけでsortablejsを使うことができます。

結局importmapって何のメリットがあるの?

Railsでimportmap使って何が嬉しいかというと以下2点かなと思っています。私の理解度が乏しいので以下2つしか分かってないです。

①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以外のエンジニアさんも募集しております。 🙂

以上、ありがとうございました。

参考記事

注訳はこちら

注訳はこちら
1 従来の方法を使い続けることも可能
2 実際、Next.jsなんかでもimportmapが使えるようにする機能がリリースされるとか。
3 Rubyのライブラリのこと
4 Railsを作ったすごい人
Let’s share this article!

{ 関連記事 }

{ この記事を書いた人 }

Kasano

エージェントグローでRuby案件やってます。
趣味は献血です。不足しがちなO型を提供したい、、、が、最近脈が早くて献血できないことが多いので困ってます。

記事一覧