Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Deep Dive into React Stream/Serialize
Search
mugi / Hajime Mugishima
April 30, 2024
Programming
2.4k
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
560
サイボウズフロントエンドの活動から考える探究と発信
mugi_uno
1
250
フロントエンドエキスパートチームの解散は 「いい話」なのか?
mugi_uno
8
2.6k
サイボウズフロントエンドの横断活動から考える AI時代にできること
mugi_uno
4
2.2k
令和7年版 あなたが使ってよいフロントエンド機能とは
mugi_uno
14
7.4k
New Order in Cascade Sorting Order
mugi_uno
3
4.5k
Next.js App Router での MPA フロントエンド刷新
mugi_uno
40
26k
コロナ禍 Frontend おさらい
mugi_uno
1
510
Toyama.rb
mugi_uno
1
250
Other Decks in Programming
See All in Programming
TS 7.0 で baseUrl が使えなくなった今、パスエイリアスをどうするか
bicstone
2
600
Crash Auto Pipelines
veronikapj
1
410
graphql-ruby を Spinel で速くしようとした話
mtsmfm
0
140
ActionController meets Protocol Buffers
sorah
1
800
TanStack Vue Query と Pinia Colada から学ぶ非同期状態の型設計
aoshi
0
650
flutter_test のその先へ — Flutter アプリの LLM 機能に「評価」という品質保証を
kosukesaigusa
0
200
Apple Intelligenceとオンデバイス時代の到来
yahir0
0
240
LLM 101: Exploring LLMs, Starting with Tokens.
dalinaum
0
100
[JA] Domain Modeling with Vanilla Rails: 「操作」から再考するRailsの設計論
yasaichi
4
1.9k
AI-Powered Domain-Driven Design
ziobrando
0
430
Railsのためのパスキー実践入門 〜マルチテナントSaaSでの意思決定〜
utakaha
4
3.8k
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
2k
Featured
See All Featured
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Scaling GitHub
holman
464
140k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The Spectacular Lies of Maps
axbom
PRO
1
1.1k
Making the Leap to Tech Lead
cromwellryan
135
10k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3.1k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
1
300
4 Signs Your Business is Dying
shpigford
187
23k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
780
A Soul's Torment
seathinner
9
3.9k
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
480
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/ αΠϘζͷϑϩϯτΤϯυΛ࠷ߴʹ͢ΔؒΛืूதͰ͢ʂ