React Conf 2024 全部観る
気温も段々と涼しくなり、Next.js 15 も正式に発表されたので、React の知識をアップデートしていく機運が高まってきた。ここでは今年の 5 月に開催された React Conf 2024 の動画をすべて視聴し、その感想を記していく(React Native については疎いため雑に流す予定)。
以下が React Conf 2024 のプレイリスト:
React の公式 Blog に Recap の記事があった、これもざっと読んでおくと良さそう:
なお、React Conf 2024 には公式アプリが存在する。以下がアプリのリポジトリ:
以下で iOS と Android アプリをダウンロードできる:
まずはハイライトの動画、微妙にテンションが上がる。Guillermo Rauch や Kent C. Dodds などお馴染みのメンツが登場していた:
React Conf Keynote (Day 1)
Meta から 4 人、Vercel から 2 人という濃いメンツで開幕:
- Meta
- Joe Savona
- Mofei Zhang
- Lauren Tan
- Sathya Gunasekaran
- Vercel
- Andrew Clark
- Josh Story
まずは Joe Savona から React の目的について語られる。こういうのを改めてちゃんと言語化するのは良いこと:
Make it easy for anyone to build great user experiences.
UX については以下のように説明される:
- User Experience (UX)
- Fast startup
- Responsive interactions
- Delightful extras and polish
そして easy for anyone の部分は以下のように説明される:
- Developer Experience (DX)
- Low barrier to entry
- High productivity
- Ability to scale
なお Joe Savona は 2010 年頃に日本で開発者としてのキャリアを開始し、そこで生の HTML や CSS、jQuery などを書いて IE6 と戦っていたというプチ情報も開示された。
- Agenda
- State of React
- React 19
- What's Next
2023 年全体で、React は合計 1,025,630,896 回 npm からダウンロードされた。
Stack Overflow Developer Survey 2023 の結果によると、初学者が学んだことのあるフレームワークで React は 36.66% の第 2 位だった:
なお、第 1 位は Node.js で(?)、Next.js は第 6 位だった模様。
React の成功に伴いあらゆるライブラリが用意されるようになったが、選択肢が多いことはユーザーに選択を強いることでもある。ので、ユーザーが迷わないように、React は以下のフレームワークをおすすめしている:
- Remix
- RedwoodJS
- Next.js
- Expo
https://react.dev/learn/start-a-new-react-project の内容と比較すると、Gatsby が姿を消しているのが興味深い。
- React 19
- Server Rendering & Suspense
- Hydration
- Actions
- JSX Improvements
https://react.dev/blog/2024/04/25/react-19#support-for-metadata-tags 以下にあるメタデータの hoisting の話。メタデータを確定させるコンポーネントにそのままタグを配置できるようになるという意味で composability が上がるよねという話で、確かにそうだと思う。ただ、実際にはこういう書き方はせずフレームワークに委ねることになるかな。
続いてスタイルの composability の話で、https://react.dev/blog/2024/04/25/react-19#support-for-stylesheets に対応する。これもスタイルシートを必要としているコンポーネントとそれをロードするタグが同居できたほうが良いよね、という内容。CSS の場合は読み込み順序が重要だが、それは precedence
で指定できる。FOUC を回避したり、duplication を取り除いたりといったお世話を React がしてくれる。
async scripts のコンポーネントとの同居や (https://react.dev/blog/2024/04/25/react-19#support-for-async-scripts)、リソースのプリロードに関連する API の追加 (https://react.dev/blog/2024/04/25/react-19#support-for-async-scripts) の話が続く。
Hydration に関するエラーが diff 付きで見やすくなるらしい、良き:
続いて Actions の話。フレームワーク無しで使ってクライアントサイドでも利用できるというのは、普段データの mutation にしか使っていなかったので抜けていた視点だ。
Actions are not exclusive to Server Components frameworks - they also work on the client, even without a framework.
First-class pattern for asynchronous updates in response to user input
Remix からの影響への言及:
Remix inspired a resurgence of action-based APIs in JS frameworks
既存の HTML action と JS のイベントハンドラーに関する pros と cons が語られる:
- HTML action
- pros
- Simple "reload everything" model
- Works without JS
- cons
- Limited feedback to user input
- Hard to add client behavior
- pros
- Event handler
- pros
- Instant feedback to user input
- Mix client and server behavior
- cons
- Async data management is hard
- Not interactive until JS loads
- pros
<form action={checkoutAction} />
<form onSubmit={onCheckout} />
と表面的には違いがないが、決定的な違いとして
- Interactive before hydration
- Built-in support for essential UX patterns like optimistic updates, with just a few lines of code
あたりが言及されている。
JSX の改善として forwardRef はもういらなくなるよ、という https://react.dev/blog/2024/04/25/react-19#ref-as-a-prop の話。
続いてパフォーマンスの話、コンパイラ関連の話題が続くと思われる。
どうでもいいが、Sathya 氏は yarn を使っていて、Meta ではパッケージマネージャーはやはり yarn で統一されているのだろうか。
Compiler の定義:
A compiler is a program that translates code from a source language to a traget language
Fine-Grained Reactivity が DX を損なわずに達成できる、といういい話。How React compiler sees your code の図は誰かに説明するときに使えそう:
続いては Meta での実例の話。まず、既存コードを並べ、どれだけ momeization のために費やしており、readability が低下しているかをビジュアルに表現している(赤と白の部分がコアロジックと関係ない部分)、つらい:
Meta ではこういうつらみが React Compiler により既に取り除かれていますよという例として、Instagram と Quest Store の話が出てくる。
コードから認知負荷が取り除かれるだけでなく、パフォーマンスも向上した:
ドキュメントへの誘導:
React Compiler Working Group
React Router や Remix を作っている Ryan Florence の話が続く。タイトル的にはフレームワークなしの裸の React ってことだろうか?
Remix が Shopify に吸収されて、理想と現実をバランスよく取り込めていることが語られる。
https://react.dev/learn/start-a-new-react-project#can-i-use-react-without-a-framework では
However, if you’re building a new app or a site fully with React, we recommend using a framework.
とあるけど、フレームワークを使いたくない、もしくは CRA などで作ったフレームワークを使っていないアプリはたくさんあるよね、これをどうモダンにすればいいか、という話っぽい。
話を聞いていて思い出したけど、ちょっと前に話題になったリブランディングの話か:
なるほど、CRA などで作られた React Router を使っているアプリをモダンにするためには、
React Router + Vite Plugin = Remix
という等式(?)から、Remix に移行してもらえばよいと考えていたが、多くの人たちにとってこれは rewrite に感じられ、規模の大きなアプリにとっては厳しくなる。そこで、
React Router + Vite Plugin = React Router v7
と Remix を React Router に置き換えてしまえば、作業内容はフレームワークの導入ではなくパッケージのメジャーバージョン更新となり、心理的障壁が減る。だから Remix に誘導するのではなく React Router の方に寄せていく、と。そうすればレガシーなアプリに
- Automatic code splitting
- Simplified data loading
- Form Actions, Server actions
- Simplified pending states
- Optimistic UI
- Server rendering
- Static pre-rendering
- RSC
等の恩恵をもたらすことができる。
Remix が React Router になる、というざっくりした話だけを聞いたときは「どうして?」と思ったし、npm のダウンロード数的に React Router が圧倒的に多いのでそこに乗っかりたいのかなとか邪推したけど、「既存のレガシーアプリを救いたい」みたいな話なのであれば一応腑に落ちるかも。
マイグレーションのデモでは clientLoader を使って useState を削除していっており気持ちいい。
SSR や RSC への移行についてもデモで示されている。RSC の方は JSX を loader に移動するだけで動いており素晴らしい。
実際、いくら React がフレームワークを使えと言っても、シンプルな SPA とフル機能の Next.js の中間に落とし込みたいシーンはたくさんあるはずなので、それらの間を incremental に行き来できるようにしたいというモチベーションは理解できるなあ。
続いては、少し前まで Vercel にいた Lydia Hallie による React 19 に関する話。
一気に総ざらいするっぽく、情報量が多そう。
- UI をブロックせず、レスポンシブなままに状態を更新するための useTransition において async function を渡せるようになった
- Actions(async transitions を使用する関数)の導入
- フォームに与える Actions の結果を管理するための useActionState の導入
-
action
とformAction
props の追加、後者で前者とは別個の Action を紐づけることができる - 親のフォームの状態を取得できる useFormStatus の導入
- Optimistic Update をおこなうための useOptimistic の導入
- React Server Components の導入
- Promise や Context を取り扱うための use の導入
- Server Actions の導入
- ref を prop として渡せるようになった(https://react.dev/blog/2024/04/25/react-19#ref-as-a-prop )
- ドキュメントのメタデータをコンポーネントに配置できるようになった(https://react.dev/reference/react-dom/components/title と https://react.dev/reference/react-dom/components/link と https://react.dev/reference/react-dom/components/meta )
- スタイルシートのサポート(https://react.dev/reference/react-dom/components/link と https://react.dev/reference/react-dom/components/style )
- リソースのプリローディング API の導入(https://react.dev/reference/react-dom#resource-preloading-apis )
フォーム関連は Next.js と絡めてどう使うべきなのか自分の中でもしっかり整理できていないので、コードを書いてベストプラクティスを探っていかないといけない。
Sam Selikoff 氏はインフルエンサーというか教育系の人という認識で正しいんだろうか、めちゃくちゃ良く見かけるのだがいまいちわかっていない。
デモを通じて新しい API のありがたさを実感しよう、的な流れの模様。
startTransition により複数の非同期処理呼び出しの coordination ができるよという話。
内部での state 更新のタイミングが即時反映されないよという話。
イベントハンドラーをクライアントサイドのアクションに変更して startTransition を削除して、同様の coordination が達成される話。
startTransition を削除し isPending が使えなくなったので、代わりに useFormStatus を使う。
useActionState によりここまでの流れをまとめる。
useActionState によるエラー管理。
useState がなくなって嬉しいよねという話:
useOptimistic により optimistic update を導入する。
Server Component + Server Action に変えていく。
React 19 in Action という感じで、これまでまとめ的に紹介されてきた機能の一部をデモする感じだった。上に書いた内容の具体的な使い方を見られるのでコードをまず確認したい人はこれから見るのが良さそう。
続いてはポテト氏こと Lauren Tan による React Compiler の話。たぶんこの方は日本語も知っていて、なので poteto にしている気がするのだが、いつかこの名前にしている理由を聞いてみたい。
「コンパイラ、本当に動くの?」という疑問に答えるために、
- Adding the compiler to your app
- Writing new code
- Building intuition
の流れでデモをする。
デモのターゲットは Dan Abramov がバリバリ実装している Bluesky の現役のアプリ。Expo で作られていても使えるよとのこと。
まずは babel-plugin-react-compiler@beta
をインストールして Babel のセットアップ:
コンパイラが有効化されている場合、React Developer Tools 上でコンパイラにより最適化されたことを示す Memo というマークが表示される(左がコンパイラ有りのアプリ、右はなし):
コンパイラの説明をするために、変数の依存関係を可視化したりする VS Code 拡張を自作したらしい、素晴らしい:
useMemo の依存をコンパイラがより正確に検知してくれることが示される。
続いて Writing new code のお題として dislike button を追加するらしい、面白い。
Rules of React を破った際に eslint-plugin-react-compiler
が警告してくれるということと、こういうコードはコンパイラがスキップしてくれるという話(また、スキップされた箇所以外はちゃんと最適化される):
コンパイラに対応するためにも、日頃から Rules of React に沿ったコードをきちんと書くことを意識しましょうという話:
npx react-compiler-healthcheck
により、コンパイラ対応がどれくらい大変かを教えてくれるらしい。これはドキュメントにも書かれていない気がするし知らなかった:
コンパイラがどのようにコードを見ているかのイメージ:
- What does React Compiler Optimize?
- Skipping re-renders
- Skipping expensive calculations
React Compiler Working Group への誘導:
めちゃくちゃ説明が上手いし話も面白いし、Overview を伝えるために細かいことを飛ばす塩梅がよかった。
なお、同じことをやってみようかと Bluesky のコードを見てみたらすでに React Compiler が導入されていた:
みんな大好き Dan Abramov。なお、日本人は彼のことを Dan 先生と呼んでいる気がするが、自分は宗教的理由により Dan だけだと Dan Kogai を想起してしまうため、必ずフルネームで呼んでいる。
「過去の自分が書いたスクリプトをもとに、今の自分が舞台上で話している」という何気ない構造が上手く RSC の話につながるようになっていて、これはさすがに惚れる:
クライアントで fetch していたデータをサーバーサイドで取得するようにして、それをシリアライズしてクライアントに渡すようにする、という話をまず React について一切触れず誰でも理解できるプレーンな JS の範囲でデモしておりイケメンすぎる。エッセンスをできる限りわかりやすい言葉に置き換えて説明する技術が Dan Abramov は異常に優れていて、このトークにも現れている。
この「複数の環境をまたいだ多段階計算を React ならもっと上手くできるよ」という感じでコンポーネントを導入していく。
最後は「準備していたスクリプトをもとにこのトークをやり遂げたので、予定していた多段階計算は完了しました」みたいな感じで最初の話につなげてオシャレに終わる。Dan Abramov のように話せるエンジニアはやはり稀有だと思う。
日本語だと uhyo 氏の
が最高の解説で、これを読めば RSC についてこの講演よりもより深く理解はできるのだが、やはり言い回しの敷居が高く、React に不慣れなエンジニアにも上手く伝えられているのは Dan Abramov だなと思う。
Theo の解説もあった、色々解説してもらいながら観たい人はこちらもおすすめ:
Evan Bacon 氏、名前はよく見るがあまり詳しくない。Expo の人で Router を作っている模様。
Universal RSC により、ウェブと iOS と Android すべてのプラットフォーム向けに RSC の機能を提供するらしい。やり取りしているデータやサーバーサイドはどうなっているのか全然想像できないがすごい。
やり取りしているデータは RSC ペイロードっぽい?色々な UI がブリブリ動いていてすごかった。今度 Expo 触ってみたいなあ。
続いては最近 Cloudflare に吸収された PartyKit の Sunil Pai。PartyKit と絡めてリアルタイムアプリと RSC の話なのかな。
時差ぼけしていてしかも AirPods をなくしてしまい微妙に凹んでいるっぽいw
前半の話はこのブログ記事と同じような話っぽい:
サーバーレス環境で
let counter = 0;
function onRequest(request: Request) {
if (request.method === "GET") {
return new Response(counter);
} else if (request.method === "POST") {
counter++;
return new Response(counter);
}
}
のようなコードを書いても、毎回環境がリセットされるのでカウンターが機能しない。これは言語の直感に合わないよね、と。
この問題を解決するには外部にストレージを用意する必要があるが、管理の手間が増えるし、この問題を解決するための方法としては大げさすぎる。
class Counter {
value = 0;
onRequest(request: Request) {
if (request.method === "GET") {
return new Response(this.value);
} else if (request.method === "POST") {
this.value++;
return new Response(this.value);
}
}
}
のように書けるとしたら良さそうだが、Cloudflare の Durable Objects がまさにそれだという話。
で、RSC を statefull にしたい、さらにその state を Server Action からも扱えるようにしたい、みたいな話につながっていくのか。
context も使いたい、と。
こういう問題意識をもとに、react-party というライブラリを作っていて、そこでは上の Durable Objects のコードと同じように
import {
useState,
useReducer,
createContext,
useContext,
ReactServer
} from "react-party";
export class MyServer extends ReactServer {
render() {
return <App />;
}
}
のようにして書けると、なるほど。
react-party のまとめ:
既存のフレームワークと組み合わせて使えるようになる予定らしい:
Josh Story 氏は Vercel のエンジニア、キーノートの話の続きをやるのかな。
React が交通整理をやってくれると:
React coordinates so your application can compose
具体的には以下のような感じで title や link を colocation できるようになる:
ただ、スタイルとかはまだわかるものの、タイトルってコンポーネントの外部世界の話で、積極的に colocate すべきものではない気がする。あくまでコンポーネントツリーの末端でしかタイトルを確定できない場合のエスケープハッチ的に使ったほうがいいかも。
colocation という言葉に引っ張られたけど、React Helmet とか外部のライブラリがユーザーランドで無理矢理頑張っていた感は確かにあるので、React 側で吸収してくれるのは普通に嬉しい。
ボットやクローラーなどのツールにとっては head 内に spec に沿って適切にデータがあると嬉しいが、UX のために即時にストリームでレスポンスを返したいという気持ちとぶつかる。React は両者をバランスさせ、なるべく spec に沿って要素を head に配置することを試みるが、ストリーム中に見つかったものについては body 内に配置する、という話。
async script による実行順序の reodering の話(https://react.dev/reference/react-dom/components/script )、リソースのプリロードの話(https://react.dev/reference/react-dom#resource-preloading-apis )、フォントや画像、スタイルシートなどを優先度高く取得する話。ここらへんのパフォーマンスの話は自分の理解が曖昧なので、
- https://web.dev/learn/performance/optimize-resource-loading
- https://web.dev/learn/performance/resource-hints
とかを一度読んでからもう一度ドキュメントを確認したほうが良さそう。
<link> や <style> をコンポーネント内に置ける話。precedence で読み込みの順序を指示できたり、UI がストリームされる場合でもいい感じに FOUC を排除してくれたり、Suspense 境界で必要なスタイルシートがロードされることを保証してくれたり、といった話題が続く。
色々書いたけど、このあたりを全体的に React がお世話してくれるということらしい。このあたりは完全に理解して記事とかにまとめたいなあ。
Charlotte Isambert 氏は BAM という会社で React Native 開発をしている人らしい。React のルールをわざと破ってみようという面白そうな話。
以下のルールを破ってみると:
- Only call Hooks at the top level
- Only use Hooks from React functions
if 文の中に useState を置くと何が起こるかという話。useState を呼ぶと linked list が作られ、各ノードで状態が管理される。初回のレンダリングでは if 文の中は実行されないため quantity に対応するノードが作成されない。そしてボタンを押して ingredient に値がセットされると、if 文の中の useState が実行されるが、これは 2 番目の呼び出しであるため、needsPurchase の値を参照してしまう。そして最後の useState の箇所で参照先のノードがないためエラーが発生する:
通常の関数としてコンポーネントを呼び出してはいけないという話。renderIngredient は FlatList の中で ingredients にマップされるとして、通常の関数呼び出しとなるため状態が FlatList のものと認識される。ここで addIngredient により ingredients の中身が追加されると、上の話と同様に 3 回目の useState で存在しないノードを参照してエラーとなってしまう:
これらのルール自体は
にあるが、どうしてそうなのかというのを Fiber のレベルで説明する面白い話だった。
最後に React 内部のアルゴリズムに興味がある人向けに参考文献が示されていた。Build your own React は自分も昔読んだが素晴らしい記事だったのを覚えている。
これらの実装の詳細は変化し得るためそれほど重要ではなく、ルールに従った良いコードを書くことが重要ですよ、というのも最後に触れていた。
Amy Dutton 氏。RedwoodJS についてはまったく触ったことがないのだが、今どんな感じになっているんだろうか(そして使う日は訪れるんだろうか...)。
この 20 年でアプリケーション開発は大きく姿を変えたが、データを CRUD するという核心は変わっていないという話。
https://www.puzzmo.com/ というアプリは RedwoodJS により作成されているらしい。なおこのアプリの作成者は以前 TypeScript チームにいた orta 氏などの模様。
RedwoodJS が他のフレームワークと一線を画す点として、DB が同梱されている点だとする。このあたりは最初の話とつながる。データレイヤーは以前は GraphQL と結合していたが今はそうではないらしい。
yarn rw g cell Sample
みたいなコマンドにより cell というモデル(?)のようなものを生成できるらしい。めっちゃ Rails っぽい。
cell 生成コマンドにより、下記のようなデータを取得するためのクエリと、データの Loading、Empty、Failure、Success に対応するコンポーネントが生成されるらしい。なるほど全然想像と違ったけど結構面白いかも 👀
export const QUERY = gql`
query {
posts {
id
title
body
createdAt
}
}
`
export const Loading = () => <div>Loading...</div>
export const Empty = () => <div>No posts yet!</div>
export const Failure = ({ error }) => (
<div>Error loading posts: {error.message}</div>
)
export const Success = ({ posts }) => {
return posts.map((post) => (
<article>
<h2>{post.title}</h2>
<div>{post.body}</div>
</article>
))
}
RSC 対応版は QUERY が下記のようになるらしい:
export const data = () => {
return { products: db.products.findMany() }
}
File-Based Routing じゃなくて、Router 用のファイルに全部記述していくスタイルらしい。どこに Auth が入るかとか 1 ファイルで見渡せていいかも。
Storybook とかテスト用フレームワークも入っているらしい。
Starter Kits とかとの違いとして、それらは一度プロジェクトを scaffold したら依存の管理とかはこちらの責務だが、RedwoodJS なら yarn rw upgrade
でできると。まあそうかもしれないが、これはこれで実際はつらみがありそうだけど。
まったく事前情報がなかったので新鮮で面白かった。仕事で使うことは当分ないと思うけど、個人プロジェクトとかなら少し触ってみたいかも。
https://www.npmjs.com/package/@redwoodjs/web とか見てみてるとダウンロード数は 12219 とかなので、全然使われてないな...
司会は chantastic こと Michael Chan。Meta と Vercel の人たち(Dan Abramov は Bluesky だけど)への質問コーナーでめちゃくちゃ楽しみ。
- Michael Chan
- Joe Savona
- Mofei Zhang
- Lauren Tan
- Dan Abramov
- Andrew Clark
- Josh Story
- Ricky Hanlon
- Jason Bonta
最初の 20 分くらいは React Compiler の話。現在は Memoization 関連に焦点を当てているがもっと様々な方向性に活かされる予定ということや、Babel プラグインは単に既存アプリケーションへのバインディングの端緒という位置付けで、SWC など他のツールのサポートも追加予定であること、などなど。