Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Deep Dive into React Stream/Serialize
Search
mugi / Hajime Mugishima
April 30, 2024
Programming
2.3k
8
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Deep Dive into React Stream/Serialize
2024/04/30 Node学園
https://nodejs.connpass.com/event/315443/
mugi / Hajime Mugishima
April 30, 2024
More Decks by mugi / Hajime Mugishima
See All by mugi / Hajime Mugishima
AIと乗り切った1,500ページ超のヘルプサイト基盤刷新とさらにその先の話
mugi_uno
2
450
サイボウズフロントエンドの活動から考える探究と発信
mugi_uno
1
170
フロントエンドエキスパートチームの解散は 「いい話」なのか?
mugi_uno
8
2.5k
サイボウズフロントエンドの横断活動から考える AI時代にできること
mugi_uno
4
2.1k
令和7年版 あなたが使ってよいフロントエンド機能とは
mugi_uno
14
7.3k
New Order in Cascade Sorting Order
mugi_uno
3
4.4k
Next.js App Router での MPA フロントエンド刷新
mugi_uno
40
26k
コロナ禍 Frontend おさらい
mugi_uno
1
490
Toyama.rb
mugi_uno
1
230
Other Decks in Programming
See All in Programming
VibeCodingからAgenticWorkflowへ
starfish719
0
170
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
200
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
960
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
200
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
3.8k
Built Our Own Background Agent at LayerX #aidevex_findy
layerx
PRO
9
4.8k
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
510
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
140
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
230
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.8k
型も通る、synthも通る、それでも危ない 〜AIのCDKの権限とコストを機械で検証する〜 / It Passes Type Checks, It Passes Synth Checks, but It’s Still Risky — Automatically Verifying Permissions and Costs in AI’s CDK —
seike460
PRO
1
530
torikago - Ruby::Boxで照らすモジュラモノリスの実行境界
se4weed
1
330
Featured
See All Featured
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
Tell your own story through comics
letsgokoyo
1
1k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
980
Paper Plane
katiecoart
PRO
2
52k
Designing for humans not robots
tammielis
254
26k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.5k
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
260
Amusing Abliteration
ianozsvald
1
240
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
420
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
330
Transcript
%FFQ%JWFJOUP3FBDU4USFBN4FSJBMJ[F /PEFֶԂ )BKJNF.VHJTIJNB$ZCP[V*OD
!NVHJ@VOP )BKJNF.VHJTIJNB $ZCP[V*OD 'SPOUFOE&YQFSU5FBN
લఏࣝ
3FBDUͱ4USFBN w 3FBDUWҎ߱ɺ4USFBNܦ༝ͰͷϨϯμϦϯάΛαϙʔτ w /PEF4USFBNSFOEFS5P1JQFBCMF4USFBN w 8FC4USFBNSFOEFS5P3FBEBCMF4USFBN w "QQ3PVUFSͰ෦తʹར༻͍ͯ͠Δ vercel/next.js
- src/server/app-render/app-render.tsx
34$1BZMPBEͱ4FSJBMJ[F%FTFSJBMJ[F w 4FSWFS$PNQPOFOUͷϨϯμϦϯά݁Ռ 34$1BZMPBEͱݺΕΔܗͰ4USFBNʹ͞ΕΔ w Ұ෦ͷσʔλಠࣗͷܗࣜͰ4FSJBMJ[F%FTFSJBMJ[F͞ΕΔ FH$MJFOU$PNQPOFOUʹ͞ΕΔ1SPQTͳͲ createFromReadableStream() renderToReadableStream() Server
Browser 34$ϨϯμϦϯά݁Ռ 34$1BZMPBE Stream Serialize Deserialize 34$1BZMPBE ϨϯμϦϯάIZESBUF
؆୯ͳαϯϓϧΞϓϦΛ༻ҙͯ͠ΈΔ w "TZOD$PNQPOFOUͷϖʔδ w ͭͷ$MJFOU$PNQPOFOU w 1SPNJTFΛ͢ w ยํޭɺยํࣦഊ w
VTF Ͱ1SPNJTFΛػ w 3FGSFTI#VUUPO ˠSPVUFSSFGSFTI ΛݺͿϘλϯ
w SPVUFSSFGSFTI ͷޙʹ%FW5PPMTͰ֬ೝ 4USFBNͷதʁ
4USFBNͷதʁ ढจʜʁ w SPVUFSSFGSFTI ͷޙʹ%FW5PPMTͰ֬ೝ
͜ͷηογϣϯͷςʔϚ w 4USFBNͷத͕ͳΜͱͳ͘ಡΊΔΑ͏ʹͳΔ w 4FSJBMJ[F%FTFSJBMJ[F͕ԿΛͬͯΔ͔ͪΐͬͱΘ͔Δ w ࢲ࠷ۙ·Ͱढจʹݟ͑ͯͨͷͰ͖ͬͱେৎ
ҙ w "QQ3PVUFSճͰ͕͢ɺ࣮΄΅3FBDUͷͰ͢ w ͓ͦΒ࣮͘Ͱ͙͢ʹཱͭͰ͋Γ·ͤΜ ʢσόοάͱ͔Ͱͨ·ʹ͑Δ͔ʣ
4USFBNσʔλͷجૅࣝ
4USFBNσʔλͷجૅࣝ
$IVOL w جຊߦʹ$IVOL w *% 5BH 3PXͷߏ 4USFBNσʔλͷجૅࣝ
w ߦʹෳ$IVOLؚ͕·ΕΔέʔε͋Δ w όΠφϦσʔλͷ߹αΠζ͕ࢦఆ͞Ε͓ͯΓɺ ޙଓνϟϯΫ͕࿈͍݁ͯ͠Δ w %FW5PPMTͳͲͰݟΔ߹ʹҙ͕ඞཁ 4USFBNσʔλͷجૅࣝ *%ͷ$IVOL͕*%ͷ$IVOLͷඌͱ࿈݁
*% w $IVOLΛҰҙʹಛఆ͢ΔΩʔ w ਐ w ࢀর࣌ͷඥ͚ͮʹར༻ w ॱংෆఆ 4USFBNσʔλͷجૅࣝ
5BH w σʔλͷछผऔΓѻ͍ํΛද͢ w * ) 5 & % 8
3 1ͳͲଟ͕͘ଘࡏ w ଟ͘಄จࣈʢ**NQPSU %%FCVHͳͲ w ແ͍߹3FBDUπϦʔؔ࿈͔୯७ͳσʔλ ίʔυ্Ͱl.PEFMzͱݺΕΔ 4USFBNσʔλͷجૅࣝ
w σʔλຊମ w 5BHʹԠͯ͡ॲཧ͞ΕΔ w େ+40/4USJOH 4USFBNσʔλͷجૅࣝ 3PX PS$IVOL
;FSP$IVOL ศ্ٓɺຊࢿྉͰ͜͏ݺͼ·͢ʣ w *%ͷ.PEFM$IVOL͕ϨϯμϦϯάͷى w $MJFOUଆͰͷඳը˺;FSP$IVOLͷඳը w ಡΉͱ͖*%ͷ$IVOL͔Βݟ͍ͯ͘ͱྑ͍
4USFBN5BHͷྫ
*ˠ*NQPSU w ΫϥΠΞϯτίϯϙʔωϯτͷ*NQPSU༻$IVOL w XFCQBDLͰ͋Ε@@XFCQBDL@SFRVJSF@@͕ݺΕΔ w *NQPSU͖͢ϑΝΠϧίϯϙʔωϯτใΛؚΉ 7:I[9842,["360","static/chunks/app/sample/ page-7f3480f94493b7cb.js"],"SuccessClient"] [
9842, ["360", "static/chunks/app/sample/page-7f3480f94493b7cb.js"], "SuccessClient" ] ※rowΛܗͨ͠ͷ
&ˠ&SSPS w Τϥʔใ$IVOL w 1SPEVDUJPO࣌EJHFTUͷΈͱͳΔ b:E{"digest":"193452068"} b:E{"digest":"193452068","message":"Error: PROMISE REJECTED","stack":""} Development
Production
5ˠ5FYU w CZUFΑΓେ͖͍จࣈྻผͷ$IVOLͱͳΔ w 5ͷޙʹαΠζ͕ਐͰ༩͞ΕΔ w ˣQBE4UBSU BCDEF Λ1SPQTʹͨ͠߹ͷྫ
8:T7d0,abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeab cdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdea bcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde....(লུ) ※"7d0" → 2000
5ˠ5FYU w $IVOLΛ͚Δཧ༝ίʔυ্ʹίϝϯτʹॻ͍ͯ͋Δ w +40/ͱͷೋॏΤϯίʔυύʔεΛආ͚ΔͨΊ w Τεέʔϓ͕ଟ͍จࣈྻͷ߹ʹίϯύΫτʹ͢ΔͨΊ
4USFBNͱ4FSJBMJ[F
4FSJBMJ[F%FTFSJBMJ[Fͷجຊ w .PEFM$IVOLͷ4FSJBMJ[F%FTFSJBMJ[Fɺ ࣮+40/TUSJOHJGZ͓Αͼ+40/QBSTFΛݺΜͰ͍Δ͚ͩ w ͦΕͧΕSFQMBDFSSFWJWFSΛͯ͠มॲཧΛΧελϚΠζ͍ͯ͠Δ packages/react-client/src/ReactFlightClient.js ※Deserializeଆ packages/react-server/src/ReactFlightServer.js ※Serializeଆ
;FSP$IVOLΛ͍ͯΈΔ [ "Hd4i-EanmGD0JpIffHyHC", [ [ [ "", { "children": ["sample",
{ "children": ["__PAGE__", {}] }] }, "$undefined", "$undefined", true ], [ "", { "children": [ "sample", { "children": ["__PAGE__", {}, ["$L1", "$L2", null]] }, [ "$", "$L3", null, { ... ˞ՄಡੑͷͨΊܗͨ͠ͷ
[ "Hd4i-EanmGD0JpIffHyHC", [ [ [ "", { "children": ["sample", {
"children": ["__PAGE__", {}] }] }, "$undefined", "$undefined", true ], [ "", { "children": [ "sample", { "children": ["__PAGE__", {}, ["$L1", "$L2", null]] }, [ "$", "$L3", null, { ... w શମ+40/4USJOH ;FSP$IVOLΛ͍ͯΈΔ
[ "Hd4i-EanmGD0JpIffHyHC", [ [ [ "", { "children": ["sample", {
"children": ["__PAGE__", {}] }] }, "$undefined", "$undefined", true ], [ "", { "children": [ "sample", { "children": ["__PAGE__", {}, ["$L1", "$L2", null]] }, [ "$", "$L3", null, { ... #VJME*% w Ϗϧυ͝ͱͷ*% w ݱࡏͷϏϧυͱࠩҟ͕͋Δ߹ɺ .1"φϏήʔγϣϯʹΓସΘΔ ;FSP$IVOLΛ͍ͯΈΔ
[ "Hd4i-EanmGD0JpIffHyHC", [ [ [ "", { "children": ["sample", {
"children": ["__PAGE__", {}] }] }, "$undefined", "$undefined", true ], [ "", { "children": [ "sample", { "children": ["__PAGE__", {}, ["$L1", "$L2", null]] }, [ "$", "$L3", null, { ... w จࣈྻͰ͔Β࢝·Δͷ ಛघͳ4FSJBMJ[F%FTFSJBMJ[F͕ඞཁͳͷ ;FSP$IVOLΛ͍ͯΈΔ
ͷಡΈํ $L3
ͷಡΈํ $L3 ಛघͳ4FSJBMJ[FΛࣔ͢ϚʔΧʔ
ͷಡΈํ $L3 4FSJBMJ[F%FTFSJBMJ[Fͷछྨ
ͷಡΈํ $L3 छྨʹԠͨ͡มʹ༻͍Δσʔλ ଞ$IVOLͷ*%ͳͲ
ಛघͳ4FSJBMJ[F%FTFSJBMJ[F
4FSJBMJ[FՄೳͳͷ IUUQTKBSFBDUEFWSFGFSFODFSFBDUVTFDMJFOUTFSJBMJ[BCMFUZQFT 3FBDUυΩϡϝϯτVTFDMJFOUͷઆ໌ΑΓൈਮ ɾ'PSN%BUB ɾ#MPC ɾ3FBEBCMF4USFBN ɾ"TZOD*UFSBUPS ࢀߟ কདྷతʹαϙʔτ͞Εͦ͏ͳͷ
4FSJBMJ[FՄೳͳͷ IUUQTKBSFBDUEFWSFGFSFODFSFBDUVTFDMJFOUTFSJBMJ[BCMFUZQFT 3FBDUυΩϡϝϯτVTFDMJFOUͷઆ໌ΑΓൈਮ ɾ'PSN%BUB ɾ#MPC ɾ3FBEBCMF4USFBN ɾ"TZOD*UFSBUPS ࢀߟ কདྷతʹαϙʔτ͞Εͦ͏ͳͷ ୯७ͳ+40/͚ͩͰରԠෆՄͳͷΛؚΉ
ˠಛघͳ4FSJBMJ[F%FTFSJBMJ[F͕ඞཁ
4FSJBMJ[F%FTFSJBMJ[Fͷ۩ମྫ
3FBDU&MFNFOU w 3FBDU&MFNFOU5VQMFͷܗʹ4FSJBMJ[F͞ΕΔ w ઌ಄ཁૉ͕ͷΈͷ5VQMF͕3FBDU&MFNFOUͱஅ͞ΕΔ w 5VQMFɺˠ5ZQFˠ,FZˠ1SPQTͷॱং [ "$", "$L7",
"key-1", { "description": "abcde", "date": "$D2024-04-24T15:01:40.265Z", "promise": "$@8" } ] Ͱݻఆ EJWͳͲͷ5ZQFPS *NQPSU$IVOLͷࢀর Ϧετඳը࣌ͳͲͷLFZ 1SPQT
Ұ෦ͷݻఆ w +BWB4DSJQUݻ༗ͷͰ+40/ͰදݱͰ͖ͳ͍ͷ $Infinity $-Infinity $NaN $-0 $undefined Infinity -Infinity
NaN -0 undefined ˞ ͪͳΈʹɺϩδοΫ্Ͱͷ࣍ͷ̍จࣈͰఆ͞Ε͓ͯΓɺ ্هͷ߹*/Vͷ࣌Ͱॲཧ͕ذ͍ͯ͠Δɻ
%BUF w % %BUFΦϒδΣΫτͷUP+40/ ࣮ߦ݁Ռ w %FTFSJBMJ[F࣌OFX%BUF Ͱ%BUFΦϒδΣΫτʹ͞ΕΔ $D2024-04-13T08:10:15.385Z
$MJFOU$PNQPOFOU -B[Z w - *NQPSU$IVOL*% w 4FSWFSଆͰɺ4FSJBMJ[Fͱಉ࣌ʹ*NQPSU$IVOLඞͣ࡞ΒΕΔ $L7 7:I[9842,["360","static/chunks/app/sample/ page-7f3480f94493b7cb.js"],"SuccessClient"]
Chunk ReactFlightServer - serializeClientReference *NQPSU$IVOLͷ࡞ૹ৴ - *%ͷܗʹγϦΞϥΠζ
$MJFOU$PNQPOFOU -B[Z w $MJFOUଆͰ3FBDUMB[ZͰ *NQPSU$IVOLΛػ͢Δܗʹ%FTFSJBMJ[F ReactFlightClient - parseModelString
'VODUJPO 4FSWFS"DUJPO w ' 4FSWFS"DUJPOใͷ$IVOL*% w Ϗϧυ࣌Ͱ4FSWFS3FGFSFODFͱͯؔ͠ʹ*%͕ൃߦ͞Ε͍ͯΔ $F8 .next/server/server-reference-manifest.json 8:{"id":"7de9e92d780a000fa18feb74a7ec9a83a73ddc8f","bound":null}
{ "node": { "7de9e92d780a000fa18feb74a7ec9a83a73ddc8f": { "workers": { "app/page": "(rsc)/./node_modules/(লུ)" }, ... Chunk
'VODUJPO 4FSWFS"DUJPO w $MJFOUଆͰɺ֘*%Λͱʹ 4FSWFSଆʹϦΫΤετΛ͛Δ৽ͨͳؔͱͯ͠%FTFSJBMJ[F DSFBUF4FSWFS3FGFSFODF1SPYZ ܦ༝Ͱ $MJFOUଆͰ࣮ߦՄೳͳؔΛऔಘ
1SPNJTF w ! 1SPNJTFใͷ$IVOL*% w ࢀরઌ$IVOLʹ3FTPMWF3FKFDUͷใؚ͕·ΕΔ $@9 9:"PROMISE RESOLVED" Chunk
1SPNJTF w 4FSWFSଆͰ4FSJBMJ[Fରͷ1SPNJTF͕ղܾ͢Δͱ4USFBNʹૹ৴ w $MJFOUଆͰ*%͕߹க͢Δ$IVOLΛػ͢Δ ReactFlightServer - serializeThenable() ReactFlightClient -
parseModelString() ※chunkࣗମ͕thenable
কདྷతʹ͑Δ͔͠Εͳ͍ػೳ
$POTPMFͷ4FSWFSˠ$MJFOUϦϨʔ w <'MJHIU>*OTUSVNFOUUIF$POTPMFJOUIF34$&OWJSPONFOUBOE3FQMBZ -PHTPOUIF$MJFOU 🔗IUUQTHJUIVCDPNGBDFCPPLSFBDUQVMM w FOBCMF4FSWFS$PNQPOFOU-PHTϑϥά͕ඞཁͰ͋Γɺ /FYUKTW࣌Ͱඇαϙʔτ w
։ൃ࣌ͷརศੑ্ͷͨΊͷػೳ w 4FSWFSଆͰͷDPOTPMF࣮ߦ࣌ʹ4USFBNܦ༝Ͱ$MJFOUଆʹྲྀ͢ ˠ$MJFOUଆͰಉ͡DPOTPMFͷϝιουΛ࣮ߦ͠ϩάΛग़ྗ͢Δ w 4USFBN5BH8ʢ$͡Όͳ͍ͷʜʁʣ
packages/react-server/src/ReactFlightServer.js w 4FSWFSଆͰDPOTPMFͷϝιουʹύονΛ͍ͯͯΔ $POTPMFͷ4FSWFSˠ$MJFOUϦϨʔ
3FBEBCMF4USFBN"TZOD*UFSBUPSͷ4FSJBMJ[F w <'MJHIU>&ODPEF3FBEBCMF4USFBNBOE"TZOD*UFSBCMFT 🔗IUUQTHJUIVCDPNGBDFCPPLSFBDUQVMM w FOBCMF'MJHIU3FBEBCMF4USFBNϑϥά͕ඞཁͰ͋Γɺ /FYUKTW࣌Ͱඇαϙʔτ w 4USFBN5BHʹ3
S 9 Y $͕Ճ͞Ε͍ͯΔ w 3 94USFBNͷ։࢝ S Y#:0#4USFBNͷαϙʔτ࣌ $4USFBNͷऴྃΛද͢ w 4FSWFS$PNQPOFOU4FSWFS"DUJPOͰ 4USFBNΛऔΓճͤΔΑ͏ʹͳΔ͔ʁ
·ͱΊ
w গ͠ಡΊΔΑ͏ʹͳͬͨΑ͏ͳؾ͕͢Δ ಄ͷ4USFBNΛ͏Ұ
·ͱΊ w 4USFBN5BHʹҙ͢Δͱ$IVOLͷछྨͷผ͕ͭ͘ w 4FSJBMJ[F͞ΕͨσʔλΛݟΔͱछྨඥ͚ͮͷ͕ͭ͘͠ w ͋ͱ3FBDUࣗମͷίʔυΛಡΊͳΜͱ͔ͳΔؾ͕͢Δ w 4FSJBMJ[F%FTFSJBMJ[FͷίʔυΛݟͯΈΔͱɺ ࠓޙ"QQ3PVUFSʹདྷͦ͏ͳػೳ͕ಁ͚ͯݟָ͖͍͑ͯͯ͠
https://cybozu.co.jp/recruit/ αΠϘζͷϑϩϯτΤϯυΛ࠷ߴʹ͢ΔؒΛืूதͰ͢ʂ