Introduction
If you are using React Server Components, inspecting RSC payloads might be important for you.
Google Chrome is a powerful tool. You can inspect the GET request for these payloads, as well as the responses, in the Network tab. Sometimes, a message "Failed to load response data" is displayed, and I'm not sure why. In such cases, I usually use "Copy as cURL" and paste the command into the terminal.
1curl 'http://localhost:3000/page3?_rsc=8nwf1' \2 -H 'Accept: */*' \3 -H 'Accept-Language: en-US,en;q=0.9,ja;q=0.8,pl;q=0.7' \4 -H 'Connection: keep-alive' \5 -H 'Next-Router-State-Tree: %5B%22%22%2C%7B%22children%22%3A%5B%5B%22id%22%2C%22page3%22%2C%22d%22%5D%2C%7B%22children%22%3A%5B%22__PAGE__%22%2C%7B%7D%5D%7D%2Cnull%2C%22refetch%22%5D%7D%5D' \6 -H 'Next-Url: /page3' \7 -H 'RSC: 1' \8 -H 'Referer: http://localhost:3000/' \9 -H 'Sec-Fetch-Dest: empty' \10 -H 'Sec-Fetch-Mode: cors' \11 -H 'Sec-Fetch-Site: same-origin' \12 -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36' \13 -H 'sec-ch-ua: "Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"' \14 -H 'sec-ch-ua-mobile: ?0' \15 -H 'sec-ch-ua-platform: "macOS"' \16 --compressed
I run this command and get the following response. This is a RSC payload.
10:["N157NNKhIC8b0k4urA243",[["children",["id","page3","d"],[["id","page3","d"],{"children":["__PAGE__",{}]}],"$L1",[[],"$L2"]]]]23:I{"id":1443,"chunks":["272:static/chunks/webpack-bf6fccfdfe35d157.js","971:static/chunks/fd9d1056-2581dce591ac5cde.js","864:static/chunks/864-b23738e09c185fe9.js"],"name":"","async":false}34:I{"id":8639,"chunks":["272:static/chunks/webpack-bf6fccfdfe35d157.js","971:static/chunks/fd9d1056-2581dce591ac5cde.js","864:static/chunks/864-b23738e09c185fe9.js"],"name":"","async":false}41:["$","$L3",null,{"parallelRouterKey":"children","segmentPath":["children",["id","page3","d"],"children"],"loading":"$undefined","loadingStyles":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","template":["$","$L4",null,{}],"templateStyles":"$undefined","notFound":"$undefined","notFoundStyles":"$undefined","childProp":{"current":["$L5","$L6",null],"segment":"__PAGE__"},"styles":[]}]52:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","link","2",{"rel":"icon","href":"/favicon.ico","type":"image/x-icon","sizes":"16x16"}]]68:"$Sreact.suspense"79:I{"id":7772,"chunks":["233:static/chunks/233-f9c6a8ef9ae4b8c3.js","531:static/chunks/app/[id]/page-d4e2ada29cefa5fc.js"],"name":"Client4","async":false}86:["$","div",null,{"children":["$L7",["$","$8",null,{"fallback":["$","div",null,{"children":"Preparing"}],"children":["$","$L9",null,{"children":"$La"}]}]]}]95:null10b:I{"id":2233,"chunks":["233:static/chunks/233-f9c6a8ef9ae4b8c3.js","531:static/chunks/app/[id]/page-d4e2ada29cefa5fc.js"],"name":"Client1","async":false}117:["$","div",null,{"children":["This is Light Server Component",["$","div",null,{"children":["$","$Lb",null,{"title":"Light Component"}]}]]}]12a:["$","div",null,{"children":"Heavy Server Component"}]
Can you read this payload? I can but I don't want. I created rscq CLI tool to make this payload easier.
10--------------------2 N157NNKhIC8b0k4urA2433 children4 id5 page36 d7 id8 page39 d10 map[children:[__PAGE__ map[]]]11 $L112 $L213--------------------0143--------------------15 272:static/chunks/webpack-bf6fccfdfe35d157.js16 971:static/chunks/fd9d1056-2581dce591ac5cde.js17 864:static/chunks/864-b23738e09c185fe9.js18--------------------3194--------------------20 272:static/chunks/webpack-bf6fccfdfe35d157.js21 971:static/chunks/fd9d1056-2581dce591ac5cde.js22 864:static/chunks/864-b23738e09c185fe9.js23--------------------4241--------------------25 <$L326 childProp={map[current:[$L5 $L6 <nil>] segment:__PAGE__]}27 segmentPath={[children [id page3 d] children]}28 template={29 <$L4>30 </$L4>31 }3233 parallelRouterKey={children}34 >35 </$L3>36--------------------1372--------------------38 <meta key=039 charSet={utf-8}40 >41 </meta>42 <meta key=143 name={viewport}44 content={width=device-width, initial-scale=1}45 >46 </meta>47 <link key=248 rel={icon}49 href={/favicon.ico}50 type={image/x-icon}51 sizes={16x16}52 >53 </link>54--------------------2558--------------------56 "$Sreact.suspense"57--------------------8589--------------------59 233:static/chunks/233-f9c6a8ef9ae4b8c3.js60 531:static/chunks/app/[id]/page-d4e2ada29cefa5fc.js61--------------------9626--------------------63 <div>64 $L76566 <$867 fallback={68 <div>69 Preparing70 </div>71 }7273 >74 <$L9>75 $La76 </$L9>77 </$8>78 </div>79--------------------6805--------------------81 <nil>82--------------------583b--------------------84 233:static/chunks/233-f9c6a8ef9ae4b8c3.js85 531:static/chunks/app/[id]/page-d4e2ada29cefa5fc.js86--------------------b877--------------------88 <div>89 This is Light Server Component9091 <div>92 <$Lb93 title={Light Component}94 >95 </$Lb>96 </div>97 </div>98--------------------799a--------------------100 <div>101 Heavy Server Component102 </div>103--------------------a
It's gotten better, hasn't it?
I developed it partly for fun. This tool is beta. As of now, it doesn't even display its version, help information or anything else. It simply parses the payload and displays the result.
Usage
1curl .... | rscq
https://github.com/horita-yuya/rscq