はじめに
ReactとRuby on Railsについての考察を期待している人へ
ごめんなさい。React周辺技術をゆる〜くまとめだけの記事です。最後に軽く感想だけ書いています。
普段からReactの開発を行っている人へ
ここに書かれている内容はすでにご存知のはずなので読まなくても大丈夫です。
背景
私は普段Ruby on Railsでどちらかというとバックエンド寄りの開発をしています。
最近とあるReactのコードを読む機会がありました。私自身は過去にReactでコードを書いた経験もあるのですが、2020年頃のことなので結構前です。
でも「まあ読めるだろう」と久しぶりにReactのコードを読み始めたのですが、周辺技術が色々と進化していてコードを読むどころではなく「これは何?」というのを知るところから始めなくてはなりませんでした。2020年当時から存在していたものもありますが、今回調べたことを軽くまとめておくことにしました。
以下、周辺技術のゆる〜いまとめです。
React関連
React
大人気のフロントエンドライブラリー。新世代のJQueryと呼ぶ声もあるようです。AngularやVue.jsが懐かしい感じがします。
関数コンポーネント
Reactコンポーネントの記述の仕方。従来、JavaScriptのクラスとしてコンポーネントを定義するクラスコンポーネントがありましたが、それに加えて関数でもコンポーネントを定義することができるようになりました。最近は関数コンポーネントの方が推奨されているようです。
React Hooks
従来のReactクラスコンポーネントではコンポーネント内で状態管理やライフサイクルメソッドを使うことができました。関数コンポーネントではそれができませんが、React Hooksを使うことで関数コンポーネント内でも状態管理やライフサイクルメソッドを使うことで実現できるようになります。
Remix
Reactをベースにした急成長中のフルスタックWebフレームワークです。ReactフレームワークといえばNext.jsが有名ですがRemixには次のような特徴があります。
- React Routerを開発した人たちが作り始めたフレームワーク
- Githubのスターは28.6K(Next.jsは124.0Kなので23%程度)
- サーバーサイドレンダリング、ネステッドルーティング、並列データフェッチによる快適なユーザー体験
- Web標準への準拠(Form、クッキー、セッションなどお馴染みの技術要素)
- フルスタックデータフローによりサーバー側とクライアント側の処理を同一コード上で記述できる
- ビルド時にクライアント側とサーバー側のコードが分離される(興味ある方はこちらを参照してください。https://remix-docs-ja.techtalk.jp/discussion/server-vs-client)
- マルチランタイム対応(Node、Webworker、Deno)
- マルチホスティングサービス対応(Cloudflare、Pages、Vercel、Netlify、セルフホスティング)
- ホットモジュール置換による快適な開発用サーバー
- 今後、本家のReact RouterとRemixは統合予定(https://remix.run/blog/merging-remix-and-react-router)
- ShopifyがRemixと提携し、ShopifyアプリはRemixで開発するようになった
思想・考え方・キーワード
私が読んだRemixのコードと直接関係するわけではないのですが、React周りを調べているとちょくちょく次のワードが引っ掛かったので紹介しておきます。
T3 Stack
T3 Stackは、Theo氏によって提唱されたWeb開発技術スタックです。次の思想をベースにしています。
- simplicity(簡潔さ)
- modularity(モジュール性)
- full-stack typesafety(フルスタックの型安全)
特に型安全性について強くその必要性を主張しています。
上記の考えを基にしたツールが公開されています。コマンドラインからいくつか質問に答えるだけで、次のような技術スタックをベースにしたアプリの雛形を作ることができるようになっています。
- TypeScript
- Next.js
- tRPC
- Prisma
- TailwindCSS
- NextAuth.js
私が読んだReactのコードでは、TypeScript、Remix、tRPC、Prisma、TailwindCSS、RemixAuthといった技術スタックを使用していました。
Monorepo(モノリポ、モノレポ)
複数のプロジェクトやライブラリを一つのリポジトリで管理するアプローチです。プロダクトやライブラリの数だけリポジトリを用意した方がきっちりと管理できそうに思えますが、リポジトリが増え続けると横断的な開発やメンテナンスが難しくなることから、Goolge、Meta、Xなどのテックカンパニーで採用されています。
「Why Google Stores Billions of Lines of Code in a Single Repository」という動画でその理由が解説されています。
WAI-ARIA
WAI-ARIA(Web Accessibility Initiative - Accessible Rich Internet Applications)は、ウェブコンテンツやウェブアプリケーションをよりアクセスしやすくするための技術仕様です。視覚障害や運動障害を持つユーザーがスクリーンリーダーやキーボードを使ってウェブコンテンツを利用する際に役立ちます。
ホスティングサービス
AWSやFirebaseなどたくさんのホスティングサービスがありますが、React界隈ではさらに多くのホスティングサービスで賑わっています。その理由にNext.jsなどのReactフレームワークと手軽に連携できることや、無料・安価ではじめることできることなどが魅力のようです。
Vercel、Cloudflare、Netlifyなどのサービスがあります。
特にVercelはNext.jsの開発を行っていることもありNext.jsとの親和性は高いようです。一方、それによってNext.jsで開発したものが他のホスティングサービスで動作しないこと(ベンダーロックイン)を危惧する声も少なからずあるようです。
エッジコンピューティング
中央集中のCloudだけでなく、エンドユーザーから物理的距離の近いエッジ(CDN)などで軽めのプログラムを低遅延で実行する仕組み。中央Cloudの負荷低減やエンドユーザーへの高速レスポンスを提供します。前述のVercelやCloudflareなどのホスティングサービスがエッジコンピューティングに対応していてNext.jsやRemixといったフレームワークがそれらを活かせるようになっています。
Webアプリケーションのユーザー体験がどんどん向上しているので、その処理を中央のCloudだけで行うよりも効率的なようです。
ライブラリなど
Prisma
Node.jsやTypeScript上で動作するORM(Object Relation Mapper)サービスです。Ruby on RailsでいうところのActiveRecordといった感じでしょうか。プログラムからデータを操作するためのクエリビルダー。データベースのスキーマを管理するマイグレーション。データベースのデータを操作するための管理画面などから構成されています。githubのスター38.4KとJS向けのORMとして人気を誇っています。オープンソースのORMだけでなく有償のSaaSも展開しています。
tRPC
tRPC(TypeScript リモートプロシージャーコールの略)はTypeScriptで書かれたAPI呼び出しのためのパッケージです。API呼び出しをTypeScriptの型で定義し、サーバーとクライアントでその型を共有します。
任意のスキーマライブラリを選べる・コード生成なし、といった特徴があります。API呼び出しの型安全性の向上とコードエディタでの入力補完といったメリットがあります。
サーバーとクライアントで型情報を共有することから、特にモノリポでの開発効率が高くなるようです。
Zod
TypeScriptで書かれたスキーマ定義とバリデーションを行うライブラリです。前述のtRPCのスキーマライブラリとして利用可能です。React Hook Formなどど連携してフォームのバリデーションを行うことができるようです。
パッケージ管理ツール
JavaScriptで書かれたコードをまとめたパッケージについて、パッケージの検索、インストール、アップグレード、アンインストールや、パッケージ間の依存関係の解決を行うためのツール。Node.js向けにnpm、yarn、pnpmなどがあります。npm以外は互換性に注意する必要があるようです。
npm
Node.jsに同梱されていて標準で使うことができます。
yarn
npmを改良したサードパーティ製のパッケージ管理ツールでnpmより高速に動作をします。
pnpm
こちらもnpmを改良したサードパーティ製のパッケージ管理ツールですが、インストール速度の向上、ディスク容量の節約(シンボリックリンクの活用)、node_modulesの厳格さ(不必要なものを入れない)といったことに焦点が当てられています。
ビルドツール関連
JavaScriptのファイルをまとめてウェブアプリケーションからのリクエスト数を減らします。ファイルをまとめながらTypeScriptからJavaScriptへ変換するトランスパイラを呼び出したりもします。WebpackやViteなどがあります。
Webpack
バンドラーの老舗。初版は2014年ということなので10年選手ですね。
Vite
2020年に登場。動作が高速であることや標準でTypeScriptやJSXをサポートしていることから人気が高まっています。
Prettier
フォーマッターの一種でコードの見た目を整えます。インデントの付け方、行の折り返しなどを一定のルールに沿って自動で整形します。JavaScript、TypeScript、HTML、CSS等々、多くの言語をサポートしています。設定項目が少ないことが特徴の一つで、設定項目が少ないということはPrettierを使っているだけで、ある程度業界標準のコードフォーマットになることが期待できます。一方でチームや個人のフォーマットの好みなどをカスタマイズする余地はあまりありません。
Eslint
静的解析ツールでコードの品質をチェックします。構文エラーを検出したり、バグになりそうなところを指摘してくれたり、コーディング規約に合ってるかといったことをチェックしたりすることができます。JavaScript、TypeScript、JSXなどに対応しています。フォーマッターの機能も有しているので部分的にPrettierと被るところがあるようです。
Linter
静的解析ツールの総称。
(EslintはJavaScriptの標準規格であるECMAScript向けのLinterということかな?)
lint-staged
Gitのコミット前に自動でLinterを自動で通すようにするツールです。
nano-staged
lint-stagedと似たような機能で処理速が速いことが特徴のようです。
テスト関連
Jest
JavaScriptテスティングフレームワークです。React・Jestのどちらもメタ社が開発していることもあって、ReactのテストならJestという流れができている気がします。React以外のVue.jsやSvelteなどのフレームワークやTypeScriptのテストにも使えます。
React仮想DOMツリーの差分からデグレーションを検知するスナップショットテストがあり、Reactとの親和性が高いようです。他にもモックテストが容易であるとか、細かな設定不要で動作したり、コードカバレッジが含まれていたり、といった特徴があります。
ビジュアル回帰テスト(VRT)
Webアプリケーションなどにおいて、コードの変更を行う前後で視覚的にどのように変化するのか確認するテスト。事前に基準となる画像を取得・保持しておき、コードの変更後に画像を取得します。そして基準となる画像と画像イメージを比較することで視覚的な変更点を検知します。ツールとしてPlaywright、Lost Pixel、Chromaticなどがあります。
Playwright
マイクロソフト社によって開発されたブラウザテストとWebスクレイピングのためのツールです。クロスブラウザ、クロスプラットフォームで高速に動作することが特徴です。標準でNode.js、Python、Java、.NETがサポートされています。
Lost Pixel
Web UIのビジュアル回帰テスト(VRT)のためのツール。Playwrightベースで構成されています。SaaSとオープンソースで提供されていてSaaSの方はホビー利用は無償ですがビジネス利用は有償です。マスキング機能があり、機密情報やランダム要素などの領域をテスト対象外とすることもできます。
LightHouse
Googleが無償で提供しているWebページを分析・診断するためのツールです。パフォーマンス、ユーザー補助、SEO、Googleのおすすめ方法といった4つの観点でページをスコア化してくれます。Chromeの拡張機能としても提供されていますが、Chromeの開発者ツールにも標準装備されています。負荷テストツールではないので注意してください。
UI関連
Radix-UI Primitives
Radix UIは、Next.jsのVercel社も採用しているヘッドレスUIコンポーネントです。ヘッドレスUIとは、ユーザーインターフェイス(UI)コンポーネントのロジック部分のみを提供し、スタイリングやデザインを含まないコンポーネントライブラリのことを指します。
Radix Primitives は WAI-ARIA((アクセシビリティ向上の目的でW3Cが定めた仕様)のガイドラインに準拠しています。(https://www.radix-ui.com/primitives/docs/overview/accessibility)
Radix-UI Themes
Primitiveにスタイルを含めたパッケージです。
TailwindCSS
CSSを一から実装するのではなく、予めユーティリティーとして用意されたCSSを組み合わせてHTMLへ適用していきます。CSSを定義する必要がない点が楽ですが、HTMLに適用されたコードを見るとインラインスタイルほどではないにしろ、HTMLのコードが乱雑に見えます。
Shadcn
Radix-UIとTailwindCSSを使ったUIコンポーネントのコードを生成します。ShadcnはUIコンポーネントライブラリではありません。Shadcnそのものを自身のプロジェクトにnpmで依存関係として組み込むのではなく、Shadcnを使って生成したコードを組み込みます。生成されたコードはRadix-UIとTailsWindCSSを使ったコンポーネントなので、必要であればさらにカスタマイズすることが可能です。
Storybook
React UIコンポーネント開発支援ツール。Storybookを使用するとUIコンポーネントをビジネスロジックやコンテキストから切り離して「UIカタログ」として一覧できるようになります。またビジネスロジックがなくても、見た目や振る舞いを確認することができるので、UIコンポーネントの開発をスムーズに行うことができます。
Fontsource
Googleフォントやその他フリーのフォントをnpmモジュールとしてJavaScriptプロジェクトにインストールすることができるようにするパッケージです。
Ruby on Rails開発者としての感想
周辺技術を調べていくうちに「Ruby on Railsの立ち位置が危うくなるのかも?」と感じました。
それは、私が読んだコードがReactのフルスタックフレームワークで書かれたものだったからです。(ここでのフルスタックとはフロントエンドとバックエンドをカバーするという意)
小規模開発やスタートアップといった開発において、開発者が一気通貫で作り上げたいような場面で、ReactフルスタックフレームワークとRuby on Railsが開発の手軽さで競合しているように思いました。
ここ数年で次のような変化が起きているようです。
ReactとTypeScriptの普及に伴って、フロントエンドとバックエンドで異なる技術スタックを使うのではなく、TypeScriptを中心とした型安全性という考え方のもと、開発者がフロントエンドとバックエンドで分断されることなくシームレスにフルスタック開発ができるようにしたいという考えが広まっているように思います。
一般的なシステム設計においては疎結合が良いとされることが多いのですが、フルスタックの開発環境においてはスキーマ定義やモノリポジトリなどを利用し、余分なレイヤーを省いて密結合にして、それによって高い開発効率を得ることが好まれているように感じました。
分業体制で開発しなければならないような大規模システムならまだしも、スタートアップ的な規模の開発であればフロントエンドからバックエンドまで少人数のエンジニアが一気通貫で開発したくなるのは理解できます。これまではRuby on Railsがそういったニーズの受け皿になっていたように思いますが、Reactの普及によってAPIモード専用になってしまうかもしれないという岐路に立たされているRuby on RailsよりもTypeScript単一の世界の方が良いのかもしれません。Ruby on Railsの大規模デベロッパーであったShopifyがReact Remixへ傾倒しているのは偶然ではないのでしょう。
個人的にはどうしてもJavaScriptに対してコードの読み書きの難しさを感じてしまいます。また言語仕様に増改築感があってあまり好きになれません。しかし、そうだとしてもフルスタックのTypeScriptであれば学習・教育コストの低減や、開発中に複数の開発言語を切り替えることによる頭の中のスイッチングコストの低減、また開発エコシステムが一種類で済むなど、「単一」であることのメリットは大きいのかもしれないと思いました。
P.S.
どうせ「単一」で行くのであれば、TypeScriptではなくRubyでやりたいなぁ。WebAssemblyのruby.wasmを使って、ブラウザ上でもRubyのコードを動かして、それを使ってReactiveなUIを書いて、そのままシームレスにサーバーサイドもRubyのコードで記述する。もしもそんな環境があったら・・・楽しそうだけど誰も使わないか。