亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

最近Next.js v14發(fā)布,發(fā)布會(huì)的各種梗圖刷爆了國(guó)外前端社區(qū)。

怎么理解 React Server Component 和 Next.js 的關(guān)系

Next.js的諸多特性(比如Server Action、App Router),都是在RSC(React Server Component)基礎(chǔ)上衍生出的。

從名字可以看出,RSC是React的特性。那么,該怎么理解RSC和Next.js的關(guān)系呢?

React團(tuán)隊(duì)的宿愿

對(duì)于前端框架的開(kāi)發(fā)范式,有三個(gè)重要衡量因素:

  • 用戶體驗(yàn)
  • 維護(hù)成本
  • 性能

但是,通常很難做到三者兼顧(具體原因本文不細(xì)究,感興趣的同學(xué)可以看data-fetching-with-react-server-components[1]。

簡(jiǎn)單來(lái)說(shuō),在前端開(kāi)發(fā)中,「IO瓶頸」是影響內(nèi)容渲染速度的重要因素(可以簡(jiǎn)單理解為,前端需要等待請(qǐng)求返回?cái)?shù)據(jù)后,再根據(jù)數(shù)據(jù)渲染內(nèi)容,這期間延遲的時(shí)間就是「IO瓶頸」)。

但是,前端框架能夠掌控的范圍局限在前端,所以無(wú)法對(duì)「IO瓶頸」做出極致優(yōu)化,只能在三個(gè)因素中做出取舍(比如考慮用戶體驗(yàn)與性能時(shí),代碼維護(hù)成本就高)。

React團(tuán)隊(duì)為了同時(shí)兼顧三者,需要對(duì)服務(wù)端擁有更多掌控。這就是RSC誕生的初衷。

但是,大部分React的受眾只是把React當(dāng)作前端view庫(kù),并不會(huì)直接使用RSC相關(guān)功能,所以React團(tuán)隊(duì)選擇和Next.js團(tuán)隊(duì)合作,落地RSC。

此時(shí)我們發(fā)現(xiàn),React有三類受眾:

  1. 普通前端開(kāi)發(fā)者,用穩(wěn)定的React做業(yè)務(wù)開(kāi)發(fā)
  2. 其他合作團(tuán)隊(duì)(比如Next.js團(tuán)隊(duì)),React團(tuán)隊(duì)為他們提供API支持
  3. 喜歡嘗鮮的開(kāi)發(fā)者/團(tuán)隊(duì),愿意嘗試那些可能出現(xiàn)在未來(lái)版本中的特性(通常還不穩(wěn)定)

React團(tuán)隊(duì)針對(duì)這三類受眾,制定了三條版本迭代路徑:

  • Latest路徑
  • Canary路徑
  1. Experimental路徑

我們正常通過(guò)npm i react下載的React包就是「Latest路徑」的打包產(chǎn)物。

通過(guò)npm update react@canary可以替換為canary包,RSC相關(guān)的功能就屬于canary包。

怎么理解 React Server Component 和 Next.js 的關(guān)系

同理,通過(guò)npm update react@xperimental可以替換experimental包。

脫離Next.js使用RSC

在Next.js的App Router模式,所有組件默認(rèn)為服務(wù)端組件(即在服務(wù)端render的組件),只有當(dāng)組件所在文件頂部標(biāo)記了'use client'指令時(shí),該組件是客戶端組件(即在前端render的組件)。

怎么理解 React Server Component 和 Next.js 的關(guān)系

比如下面就是個(gè)客戶端組件:

'use client'
import {useState} from 'react';

function Cpn() {
  const [num, update] = useState(0);
  // ...省略
}

實(shí)際上,這并不是Next.js自己的定義,而是RSC中的規(guī)范。在React文檔中,我們可以看到'use client'與'use server'規(guī)范的定義,其中:

  • 'use client'用于標(biāo)記客戶端組件(在服務(wù)端,默認(rèn)所有組件都是服務(wù)端組件,所以客戶端組件需要專門(mén)標(biāo)記)。
  • 'use server'用于標(biāo)記前端的某個(gè)函數(shù)為Server Action(可以在前端執(zhí)行的服務(wù)端邏輯)。

怎么理解 React Server Component 和 Next.js 的關(guān)系

既然是規(guī)范,那就需要落地。在Next.js中,規(guī)范的落地都被收斂到Next.js框架內(nèi)部實(shí)現(xiàn)了。如果要脫離Next.js使用RSC,就需要我們自己落地規(guī)范。

RSC規(guī)范的落地包括三部分:

  • 服務(wù)端編譯時(shí)
  • 服務(wù)端運(yùn)行時(shí)
  • 客戶端運(yùn)行時(shí)

這三者都被收斂到react-server-dom-webpack[2]包中。

接下來(lái)我們簡(jiǎn)單講下這三部分的作用。

服務(wù)端編譯時(shí)

通過(guò)react-server-dom-webpack/plugin名字中的webpack、plugin字樣能看出,這是個(gè)webpack插件,配置類似如下:

const ReactServerWebpackPlugin = require("react-server-dom-webpack/plugin");

const config = {
  // ...省略其他配置
  plugins: [
    new ReactServerWebpackPlugin({ isServer: false }),
  ],
}

他的作用是識(shí)別項(xiàng)目中的'use client'指令,作用有些類似于「全自動(dòng)React.lazy」。

使用過(guò)React.lazy特性的同學(xué)會(huì)知道,當(dāng)我們通過(guò)React.lazy懶加載組件時(shí),懶加載的組件會(huì)被打包工具(比如webpack)打包成獨(dú)立的chunk。當(dāng)前端需要該組件時(shí),會(huì)通過(guò)Jsonp請(qǐng)求chunk文件。

比如下面代碼中的./Cpn.jsx組件由于懶加載,會(huì)被打包成獨(dú)立的chunk:

import React from 'react';

const LayCpn = React.lazy(() => import('./Cpn.jsx'));

function App(props) {
  return <LayCpn {...props} />; 
}

與React.lazy類似,當(dāng)我們?cè)诮M件所在文件的頂部標(biāo)記'use client'時(shí),并在服務(wù)端組件的子孫組件中使用到該組件,該組件代碼也會(huì)打包成獨(dú)立的chunk。由于這個(gè)過(guò)程是全自動(dòng)的,所以可以稱為「全自動(dòng)React.lazy」。

服務(wù)端運(yùn)行時(shí)

上面講到的編譯產(chǎn)物都是「客戶端組件對(duì)應(yīng)chunk」,所以他們是不會(huì)在服務(wù)端運(yùn)行時(shí)使用的。

服務(wù)端運(yùn)行時(shí)的作用類似SSR,都是給定JSX輸入,經(jīng)過(guò)render后獲得輸出。比如,給定如下輸入:

function App() {
  return <div>hello</div>;
}

對(duì)于SSR,會(huì)獲得字符串'<div>hello</div>'的輸出。

對(duì)于RSC規(guī)范,將輸入傳給react-server-dom-webpack/server導(dǎo)出的renderToPipeableStream方法,會(huì)獲得如下序列化數(shù)據(jù):

0:"$L1"
1:["$","div",null,{"children":"hello"}]

再讓我們看一個(gè)稍微復(fù)雜點(diǎn)的例子:

我們有個(gè)組件Cpn,由于他包含客戶端狀態(tài)(使用了useState),所以只能作為客戶端組件(頂部標(biāo)記'use client'):

'use client'
import {useState} from 'react';

function Cpn() {
  const [num, update] = useState(0);
  // ...省略
}

現(xiàn)在,我們的服務(wù)端組件App返回值中包含了Cpn:

function App() {
  return <div><Cpn/></div>;
}

經(jīng)由renderToPipeableStream方法,會(huì)獲得如下序列化數(shù)據(jù):

0:"$L1"
2:I["./src/app/Test.jsx",["client0","client0.chunk.js"],"Test"]
1:["$","div",null,{"children":["$","$L2",null,{}]}]

可以發(fā)現(xiàn),序列化數(shù)據(jù)中并不包含具體的客戶端組件代碼,而是組件代碼對(duì)應(yīng)的文件(client0.chunk.js),這個(gè)文件就是我們?cè)凇阜?wù)端編譯時(shí)」打包產(chǎn)生的chunk文件。

客戶端運(yùn)行時(shí)

當(dāng)「服務(wù)端運(yùn)行時(shí)」產(chǎn)生的「序列化數(shù)據(jù)」傳遞給前端時(shí),react-server-dom-webpack又出場(chǎng)了,這次使用的是react-server-dom-webpack/client。

這個(gè)包提供了幾個(gè)方法,用于將「從不同數(shù)據(jù)源獲取的序列化數(shù)據(jù)」轉(zhuǎn)換為「合法的React Element」,比如:

  • createFromFetch:通過(guò)fetch方法獲取序列化數(shù)據(jù)。
  • createFromReadableStream:通過(guò)可讀流獲取序列化數(shù)據(jù)。

對(duì)于上述序列化數(shù)據(jù):

0:"$L1"
2:I["./src/app/Test.jsx",["client0","client0.chunk.js"],"Test"]
1:["$","div",null,{"children":["$","$L2",null,{}]}]

經(jīng)由react-server-dom-webpack/client中方法的轉(zhuǎn)換,會(huì)得到一個(gè)React.lazy組件,這樣前端的React就能正常render這個(gè)組件了。

總結(jié)

RSC規(guī)范屬于React特性,來(lái)自于React Canary。規(guī)范的落地可以通過(guò)react-server-dom-webpack包實(shí)現(xiàn)。

整個(gè)工作流程包括三個(gè)階段:

  • 服務(wù)端編譯時(shí),對(duì)應(yīng)react-server-dom-webpack/plugin。
  • 服務(wù)端運(yùn)行時(shí),對(duì)應(yīng)react-server-dom-webpack/server。
  1. 客戶端運(yùn)行時(shí),對(duì)應(yīng)react-server-dom-webpack/client。

在Next.js中,RSC規(guī)范的落地被集成到框架內(nèi)部,做到了開(kāi)箱即用的RSC,并在此基礎(chǔ)上衍生出更完善的功能(App Router)。

參考資料

[1]data-fetching-with-react-server-components:https://legacy.reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html。

[2]react-server-dom-webpack:https://www.npmjs.com/package/react-server-dom-webpack。

分享到:
標(biāo)簽:React
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定