成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

怎么理解 React Server Component 和 Next.js 的關系

開發(fā) 前端
Next.js的諸多特性(比如Server Action、App Router),都是在RSC(React Server Component)基礎上衍生出的。從名字可以看出,RSC是React的特性。那么,該怎么理解RSC和Next.js的關系呢?

大家好,我卡頌。

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

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

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

React團隊的宿愿

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

  • 用戶體驗
  • 維護成本
  • 性能

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

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

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

React團隊為了同時兼顧三者,需要對服務端擁有更多掌控。這就是RSC誕生的初衷。

但是,大部分React的受眾只是把React當作前端view庫,并不會直接使用RSC相關功能,所以React團隊選擇和Next.js團隊合作,落地RSC。

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

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

React團隊針對這三類受眾,制定了三條版本迭代路徑:

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

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

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

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

脫離Next.js使用RSC

在Next.js的App Router模式,所有組件默認為服務端組件(即在服務端render的組件),只有當組件所在文件頂部標記了'use client'指令時,該組件是客戶端組件(即在前端render的組件)。

比如下面就是個客戶端組件:

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

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

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

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

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

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

  • 服務端編譯時
  • 服務端運行時
  • 客戶端運行時

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

接下來我們簡單講下這三部分的作用。

服務端編譯時

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

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

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

他的作用是識別項目中的'use client'指令,作用有些類似于「全自動React.lazy」。

使用過React.lazy特性的同學會知道,當我們通過React.lazy懶加載組件時,懶加載的組件會被打包工具(比如webpack)打包成獨立的chunk。當前端需要該組件時,會通過Jsonp請求chunk文件。

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

import React from 'react';

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

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

與React.lazy類似,當我們在組件所在文件的頂部標記'use client'時,并在服務端組件的子孫組件中使用到該組件,該組件代碼也會打包成獨立的chunk。由于這個過程是全自動的,所以可以稱為「全自動React.lazy」。

服務端運行時

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

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

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

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

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

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

再讓我們看一個稍微復雜點的例子:

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

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

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

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

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

經(jīng)由renderToPipeableStream方法,會獲得如下序列化數(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ù)中并不包含具體的客戶端組件代碼,而是組件代碼對應的文件(client0.chunk.js),這個文件就是我們在「服務端編譯時」打包產(chǎn)生的chunk文件。

客戶端運行時

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

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

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

對于上述序列化數(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)換,會得到一個React.lazy組件,這樣前端的React就能正常render這個組件了。

總結(jié)

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

整個工作流程包括三個階段:

  • 服務端編譯時,對應react-server-dom-webpack/plugin。
  • 服務端運行時,對應react-server-dom-webpack/server。
  1. 客戶端運行時,對應react-server-dom-webpack/client。

在Next.js中,RSC規(guī)范的落地被集成到框架內(nèi)部,做到了開箱即用的RSC,并在此基礎上衍生出更完善的功能(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。

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2023-05-26 08:13:49

RSCNext.js開源

2024-11-25 07:39:48

2025-01-17 09:29:42

2022-10-13 18:54:57

JavaScriptQwikReact

2024-03-04 07:33:39

RemixReact框架

2025-03-19 08:06:31

2025-03-17 03:00:00

2024-12-20 07:30:00

重定向服務器端指令Next.js

2020-12-14 11:40:27

Next.js SSRReact

2023-11-07 11:47:59

2025-02-03 00:00:35

2024-12-13 08:37:32

2024-09-20 15:37:02

2024-05-09 09:01:03

2024-04-28 10:56:34

Next.jsWeb應用搜索引擎優(yōu)化

2024-09-04 10:27:53

2024-02-05 11:55:41

Next.js開發(fā)URL

2024-03-05 19:17:37

2023-05-31 07:29:46

2021-11-26 10:29:24

jsRemix開源
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜看片网站 | 伊人在线视频 | 久久久久久高潮国产精品视 | 99re视频在线观看 | 国产视频一区二区 | 国产精品久久久久一区二区三区 | 午夜免费福利电影 | 日本欧美在线观看视频 | 中文字幕第十五页 | 日本成人中文字幕 | 亚洲精品美女视频 | 国产ts人妖系列高潮 | 国内久久| 日韩图区 | 91久久精品一区二区三区 | 国产精品视频久久 | 欧美精品一区二区三区在线 | 国产精品99久久免费观看 | www四虎影视| 国产精品免费看 | 日韩在线观看一区 | 婷婷国产一区 | 欧美片网站免费 | 国产在线一区二区三区 | 日韩精品一区二区三区中文在线 | 久久99精品久久久久久青青日本 | 中文字幕av高清 | 成人在线免费观看视频 | 国产欧美一区二区三区在线看 | 欧美一区 | 欧美一级在线 | 欧美综合久久久 | 国产福利视频 | 亚洲少妇综合网 | 在线免费观看成人 | 日韩高清中文字幕 | 91精品国产综合久久久久久蜜臀 | 97精品超碰一区二区三区 | 巨大黑人极品videos精品 | 人人澡人人射 | 欧美videosex性极品hd |