REACT服务器组件是什么

什么是 React 服务器组件?

React Server Components 是一种新型态的组件,过去我们熟悉的组件则相对被称为 Client Components,它还是一个实验性质的功能,不过不出意外的话这个功能会是 React 未来发展的方向,如果稳定发布的话之后,也许会改变我们熟悉的 React 开发方式。

在这个模型的底下,组件分为以下三种:

  • Server Components:在 Server Side 渲染的组件,具有访问 DB、文件系统的能力,但无法做事件绑定,所以缺少了「交互性」。
  • 客户端组件:在客户端渲染的组件,拥有交互性。
  • 共享组件:可以在服务器端也可以在客户端渲染,具体是什么组件引入它,如果是服务器组件引入就由服务器渲染,反之则由客户端渲染。

我们可以把这个模型放到下面的 React 组件树中看成它是由 Server Side 与 Client Side 混合渲染的一个树状结构,React 在 Server Side 将 Server Components 渲染好后传给客户端,如果 Server Side 在渲染的过程遇到客户端组件,它会用一个占位符来标注它(请注意它不会实际执行或渲染它),未来让客户端知道这是需要它来渲染的组件。一般来说客户端在接收到 JS捆绑后会进行水合,但是Server Components只能在Server端做渲染,不会在客户端进行水合。

渲染式,橘色为混合服务器组件,蓝色为客户端组件

混合渲染是怎么进行的?

简单分割可以拆分为以下三步骤:

  1. 渲染根
  2. 请求服务器组件
  3. React 运行时渲染

渲染根

浏览器拿到页面 HTML 后,会发出 request 请求主要的 JS 包,也就是说 main.js,这个 JS 包包含了 React Runtime 和 Client Root,Client Root 执行后会一个 Context,这个 Context 可以用来存储 Client侧面的状态。

请求服务器组件

Client Root 的代码被执行后,同一时间,浏览器同时向 Server Side 的某个 API 端点发出一个请求,然后上图的 useServerResponse(以官方示例来说,这个端点是 /react),当然在打这个请求的时候也需要带一些数据过去,可以预见到这些数据会包含一些React Tree的消息,Server Side才知道要渲染哪些组件。server端接受到请求后就会开始进行Server Components的渲染。 服务器器会从服务器组件根开始渲染,并形成主板混合的组件树

这颗组件树会形成类似的混合对象,标记为 React 必要的信息

css 复制代码
module.exports  = { 
    tag:  '服务器根' , 
    props: { ... }, 
    Children: [ 
        { tag:  "Client Component1" , props: { ... } :  Children: [] }, 
        { tag:  "服务器Component1" , props: { ... } :  Children: [ 
            { tag:  "Server Component2" , props: { ... } :  Children: [] }, 
            { tag:  "Server Component3" , props: { ... } : 孩子们: [] },
        ]} 
    ] 
}

刚才说过服务器端在渲染的时候如果遇到客户端组件,只能用占位符做一个注记,这些客户端组件需要送到客户端做渲染,面对React必须将这些信息也送到客户端,所以 React 最后回传的其实是一个可序列化并且带有特殊格式的 JSON chunk 响应,以便之后可以渐进式的在客户端渲染。

其中的英文符号代表不同的数据模型,例如M代表模块(根据客户端组件所需的JS Chunk资讯),S代表符号,E则代表错误,J代表服务器组件渲染出的类似react元素格式的字串,React 会根据这些块响应来渲染对应的 Native Elements 和 Client Components。有兴趣的读者可以再进一步参考React 的源代码

React 运行时渲染

刚刚那些 JSON 响应送到 Client 端后,React Runtime 就接手开始工作,他会根据 chunk 响应的内容渲染出真正的 HTML 组件。例如当它看到代表 Module 的「M」,就会发送请求获取客户端组件需要的 JS Bundle,当浏览器加载 Client Components 的 Bundle 后,React 就可以进行渲染和 Hydration。如果看到代表 Server Components 渲染出的内容的「J」,React 就会将实际元素渲染出来。注意,的是React在传输刚才提到的JSON块响应是采用流式传输的方式,一旦React Runtime不需要等到获得所有数据才能开始做进一步处理。

因此混合渲染的简单流程如下图:

其实以上的流程都只是简化的版本,中间兼容的流程其实需要前面之间非常复杂的交互,有兴趣的可以参考这篇文章,而像Next.js这样的元框架实际上会与模块捆绑器集成,把这些复杂的流程抽象化与简化,让我们未来在使用服务器组件开发时不用面对那么简单复杂的问题,这也是 React 积极与这些框架合作探索这个新功能的原因之一。

React Server 组件带来什么优势?

React Server Components主要解决了以下几个问题:

  • 减少束尺寸
  • 运用服务器端的能力
  • 自动化代码分割

减少依赖的体积

通常在开发前端应用的时候,我们会安装很多依赖包,有些包甚至还没办法做tree-shaking,随着引入的套件变多,应用的包大小也随之增加,造成页面加载的情况下降。

Server Components 因为只在 Server 上做渲染,所以组件的程序代码包不用被下载到客户端,如果套件只被 Server Components 使用(React 官方的范例是一个处理 markdown 语法的套件),就不用担心会增加应用程序整体的包大小。

一个更极端的例子是应用中大部分的组件如果都没有跟用户交互的需求,那这些组件都可以使用服务器组件,这些UI都可以走「浏览接受器JSON块响应,React Runtime接手渲染」的这个模式,这样的话理论上除了 React Runtime,是不需要其他 JS 包的(而 JSON 响应体积大小跟 JS 包不是一个量级,可以忽略不计)。因为 React Runtime 的包大小不会随着应用的扩展而变大,所以这就是官方号称 RSC 为「Zero-Bundle-Size Components」的原因。

运用服务器端的能力

在 React Server Components 中,我们可以直接访问 DB,甚至也可以访问文件系统,简单来说你利用 Node.js 能做到什么,Server Components 就很有可能也做得到(当然现在大多数还是聚焦在数据上)抓取这个应用场景上,但如果脑洞大开,其实要在RSC做一些复杂的干扰也是有可能的,不过就等待未来的发展了)。跨越这样自由集成外部的能力,我们可以解决客户端-服务器路由过多,甚至造成瀑布请求的情况,典型的情景就是透过嵌套的useEffect来调用API获取数据,我们需要等在上层的组件抽取数据并渲染出知道下层组件后,才下层的组件需要什么样的数据,这种模式对出现来说可能会产生很大的影响。

自动化代码分割

在过去我们要做的代码分割必须自己用 React.lazy 搭配 Suspense 或者使用成熟的第三方套件例如可加载组件,这样的缺点就是需要由开发者手动分割、手机确认要分割的边界。

有了 React Server Components,这个麻烦似乎得到了缓解,React 将所有的 Client Components 看作是潜在的代码分割分割点,我们只需要按照分割组件的思维去组织代码,React 会自动帮我们实现代码分割。

javascript 复制代码
 从'./ClientComponent1'导入ClientComponent1 ;function ServerComponent ( ) { return (         <div>             // 客户端组件会自动被代码分割            <ClientComponent1 />         </div>     ) } 

 
    

React 服务器组件的缺点

最常见的缺点就是开发者的学习路径变得更加陡峭了,服务器组件也需要跟模块捆绑器、服务器端做整合才能够使用,在设定上肯定会增加急剧的复杂度。

另外实际开发时拆解组件的时候还要进一步去思考「我这个组件要用服务器组件还是客户端组件?」这不外乎会增加开发者的心理负担。

React 服务器组件与服务器端渲染

这个术语很容易让人产生干扰,SSR 的两个机制是在服务器中渲染一个 HTML 传送到客户端,并在客户端通过 React 运行时进行水合作用,完成之后,页面才是一个可以交互的完整应用。除了初始页面加载外部,后续页面的导航,例如在 Next.js 中穿透 Next/Link 进行页面截图,它其实是走客户端的导航,接下来会调用一个 API 端点去执行 getServerSideProps 函数去抓取需要的数据,但并并不会重新生成一个 HTML。所以说顶层是 SSR 的应用,在导航的时候我们的 web 应用其实就跟一般不是走 SSR 的 SPA 页面行为可以一致了。因此我们发现,SSR 的重点在于「页面的最终渲染」 」。

而React Server Components永远都是在服务器上渲染的,当这些组件需要重新渲染的时候,它们会在服务器端重新做数据抓取,然后重新合并回客户端中已有的React Component Tree。 重点是多个页面中部分服务器组件重新再关联服务器所需数据,同时客户端的状态是可以被保留的。

简单来说两者是完全不同的概念,也不互相冲突,使用服务器组件不一定要走SSR,使用SSR也不一定要用服务器组件,当然两者也可以结合使用,就像后面会介绍的Next.js 13 一样。

(想更多了解两者的区别,可以参考这篇文章。)

使用 Next.js 的服务器组件 13

页面目录→应用程序目录

熟悉Next.js的人应该知道pages是一个特殊的数据夹路径,写在其中的文件会直接对应到接口应用的路由系统,举例来说,/pages/about.tsx会对应到应用的/about页面,/pages/nested/test.tsx 会对应到 /nested/test 页面,这样的方式让我们不用去另外定义路由器,非常的又方便。

以上的模式也被称为「Page Directory」,而接下来的 13 提出了一个实验性的模式------「App Directory」。

Next.js 13 应用程序目录

App Directory 与 Page Directory 在文件安排上最大的区别就是它让与 Page 没有直接相关的文件也可以将路径资料夹放在底下,这样托管的功能是 Page Directory 做不到的,因为只需放入页面资料夹底下的文件,都会自动创建出一个路径出来,所以我们不能把 CSS 文件或者组件文件与页面文件放在一起。在 App Directory 中,真正可以决定页面路由的只有 page.js 这个文件,其次/app/dashboard/page.js 会创建出 /dashboard 的页面、 /app/nested/test/page.js 建立出 /nested/test 页面,其他的文件则不会影响路由结果。

在App Directory中,CSS或测试等文件都可以并置在一起而不会影响应用路由结果

虽然说现在文件可以随意并置,但接下来规定了一些特定的文件与它们的特殊作用:

App Directory 的保留字档案

如果有定义的话,这些文件也将被接下来以特定的层次结构渲染出来,我们稍后同时探索其中的几个文件。

App Directory作为Next.js新版的路由系统,它还提供了一些额外的新功能:

应用程序目录带来的新功能

其中最重要的新功能就属本篇的主角服务器组件了,当然,其他的功能稍后还有各自的段落来介绍(它们也与服务器组件的使用息息相关)。

(Next.js 13以App Directory为起点,其实带来了非常多的新功能与改变,从官方特别是为App Directory做了一个新的文档站点就可以得知这一点。文章中的文章内是不可能讲完所有功能的,因此感兴趣的读者非常推荐自行去阅读看看喔!)

服务器和客户端组件

显然 React 官方最初提供的示例档名来判断一个组件是 Server Component 还是 Client Component (ex: test.server.tsx, form.client.tsx ),在 Next.js 13 App Directory 中,所有的组件默认都是 Server Component ,并且 Server Component 可以是一个异步函数。而当你认为某个组件需要用户交互或者调用 DOM 等 Web API 时,再通过 **"使用客户端" **标记组件为 Client Component。

App Directory 中,组件默认都是 RSC,并且可以是异步函数

穿透在文件开头注记 use client 判定该元件为 Client Component

通过「默认情况下走服务器组件,若有用户交互的需求则走客户端组件」这个原则,结论需要手动在文件名上注记服务器还是客户端组件的方式,我认为可以在一定的编程减少开发者的心理负担。

Next.js 官方文件也推出了 Server 与 Client Component 的使用时机:

服务器组件与客户端组件的使用时机

另外,在 Server Component 与 Client Component 的使用上,Next.js 也提出了一些限制,例如说在 Client Component 里不能直接 import Server Component

而必须以 Children props 的方式建立,因为前面已经提到,服务器端在渲染过程中如果遇到客户端组件,它并不会去实际执行或渲染它,而是把一些信息记起来传给客户端,所以如果是上面的写法,如果执行 Client Component 的文件的话,React 是不会知道它在返回函数中需要去渲染那个 Server Component 的。透过下图 Children 知道 props 这种模式 React 才需要在回传资料首先给客户端在服务器端渲染这个服务器组件,然后React通过这种方式才能在服务器端完成解析树状结构。

另一个限制是虽然服务器组件可以通过 props 的方式传递数据给客户端组件,但这些数据必须是可序列化的,所以像函数或日期对象就不能直接传递给客户端组件。

官方提到了一个词要做「网络边界」,在过去版本的下一个,网络边界存在于 getStaticProps/getServerSideProps 与 Page Components 之间,而在新版本的 App Directory 中,这个边界则又是服务器组件与客户端组件之当你想要跨越网络边界提交数据时,这些数据就必须是可序列化的,这就是为什么服务器组件向客户端组件提交数据有这个限制的原因。

接下来是重组服务器组件与客户端组件的概念,由于 JavaScript 模块是可以被在这两个组件中消耗的,如何去避免只打算在服务器上运行的程序码不小心被用户端执行也是一件很重要的事。举个例子来说:

这个数据获取函数初步看下来是可以被服务器与客户端组件消耗的,但是如果你对 Next.js 比较熟悉的话就会比较锐利,其实发现上面用的环境变量并不是 NEXT_PUBLIC 开头的,按照 Next.js 的。 js 的定义,这个 env 就只能在 Server Side 才能访问到。所以如果这个函数被客户端组件执行,该 env 会得到 undefined,会导致获得错误的执行结果。

为了避免这种客户端与服务器端特定功能误用的问题,Next.js 官方建议使用仅服务器端的 npm 包,它可以抓住当构建时出现误用的情况发生时就可以到错误(反过来的,其实也有 client-only 这个包可以使用)。

通过 server-only 包限制 getData 函数只能被 Server Components 使用

Next.js 官方也建议如果可以的话,请尽量把 Client Components 放到组件树的叶子节点中,这样做的好处是可以尽量减少要传给客户端的 JavaScript 包大小,对于前面应用程序的情况来说是有帮助的。

共享数据是前端应用的一个重要的功能,那么 Server Component 与 Server Component 之间要如何共享数据呢? 讲到共享数据,React 开发者可能会自动关联到 Context,不过很遗憾,在 Server Component 中是无法使用的React Context 的,但我们却可以利用一些设计模式例如 Singleton Pattern 搭配 JavaScript 的模块系统来完成在多个 Server Components 间共享数据。下面的例子就是在演示如何在多个 Server Components 间共享数据库的连线:

以上的内容大致介绍了在 Next.js 13 中是如何整合 Server Components 这个概念,可以发现 Carl React Core Team 最初提供的示例,它已经做出了非常多的修改,例如不用副档名做区别,还有在 Next.js 中目前并没有共享组件的概念,而如果意外不出,等到稳定的版本推出,介绍的使用方式可能又会做出改变,我们必须先有这个认知与想法的话。

数据获取

App Directory 引入服务器组件之后,最大的改变就是数据获取的模式了,而在今天的内容中,针对数据获取我想讨论以下几个重点:

  • fetch() API
  • 在Server Components中进行数据获取
  • 组件级数据获取和缓存
  • 并行和顺序数据获取
  • 静态和动态数据获取

fetch() API

在 Next.js Server Components 中,官方建议使用 fetch() 这个 Web API 布置 async/await 静态数据获取,不过这个 fetch API 并不是以前我们熟悉的 fetch,而是经过封装的版本,它主要多了两个个重要的功能:

  • 自动请求重复数据删除
  • 提供更丰富的选项对象让用户可以确定,使每个请求都可以分别设置缓存和重新验证的规则

而这两点我们会在稍后分别介绍,现在只需要知道在 Next App Directory 中一般常使用 fetch 这个 API 进行数据获取就可以了。

在Server Components中进行数据获取

其实上面的文章在介绍服务器组件时已经提到了,我们可以在服务器组件中进行数据抓取,这样有一些好处,例如:

  • 我们对于后端数据资源有直接的访问权,例如数据库或者文件系统
  • 在服务器端可以避免一些敏感信息泄漏到客户端,例如访问令牌或 API 密钥......等等。
  • 让数据的抓取与渲染在同一个环境中进行,可以减少客户端与服务器端之间来回的交互,也可以尽量减少客户端主线程的工作量。
  • 也许可以在更接近数据源的情况下执行数据获取,减少延迟以优化完成。
  • 减少客户端-服务器之间的瀑布请求(典型的例子是一层又一层的 useEffect)。

在 Server Components 中可以配置 async/await 做数据获取

需要补充说明的是,这并不代表我们就不能在客户端组件做数据抓取,毕竟偶尔还是会有这方面的需求(举例来说,当用户点击时去抓取数据)。不过 Next.js官方如果要的话使用swr或者react-query等第三方库会比较适合。

在过去,在没有使用上述提到的第三方套件的情况下,如果在客户端组件里面我们想要进行数据抓取,并且还想处理加载时跟发生错误时的状态,我们可能会这样写:

单就 Call API 的场景来说其实有点过于复杂。未来 React 官方也有可能会推出支持处理 Promise 并搭配 Suspense 的 use() hook。(详情请参考React RFC)。

它的使用方式很像 async/await,并且可以搭配 Suspense 和 React Error Boundary 使用,所以我们就不用自己定义错误跟加载的状态,同一个架构,在单一组件的方案码简洁众多。

这个新的钩子仍然处于 RFC 的阶段,需要静待它未来的发展了。

组件级数据获取和缓存

在过去的 Next.js 版本中,我们如果要在 Server Side 做数据抓取,需要在页面的根文件中提供一些内置函数才能做到,例如 getServerSideProps、getStaticProps...等等,可以说是数据抓取的思考模式是页面级的,我们需要在页面的时候把数据抓取完再依靠 props 的方式传给底层的组件,但有了服务器组件之后,可以实现更便捷的组件级数据获取。

接下来官方也建议将数据获取的功能并置在需要这些数据的服务器组件旁边,例如上一段类似的例子:

假设我们想要在页面的最上层和页面底下的某个组件共享同一个获取请求获取的数据,我们可以分别在页面组件和子组件都调用这个获取函数,而不是在上层的页面组件提取后通过 props 传到子元素里,所以大家肯定听过的 Prop Drilling 这种多层次传递资料的模式(你可能想到了 React Context,但很遗憾,在 RSC 里面是不能用 Context 的)。你可能又会想,这样不是会打两次请求造成问题吗?还记得前面提到的 Next.js 封装了 fetch API,实作了「自动请求重复数据删除」,这个概念其实就是 Next.js 实作了一个快取,如果发现是重复的请求(同一个渲染周期中),就直接回传快取的结果,而不会再发出一次网路请求。

那如果我们的请求不是穿透fetch API呢?毕竟在Server Components可以访问到的数据源非常多元,假设是直接访问DB呢?要怎么做到自动请求去重?

React 在某个 RFC中提出了缓存功能,可以将确定的函数回传的结果快取起来,只要带入的参数不变,就可以从快取回传值。至于如何使缓存失效,则要等待React 社群对这个 API 未来的进展(目前有说会有专门针对这个 API 的 RFC,但在写这篇文章的时候似乎还没有出来)。

其实只要提过fetch API就可以做到自动请求去重,就是经过这个缓存功能的封装。

值得一提的是,fetch API 针对 POST 请求并不会自动进行请求重复数据删除,因此当我们使用 GraphQL 的 POST 端点进行数据获取时,可以通过缓存功能开启此行为。

并行和顺序数据获取

提到在服务器组件中做数据获取,我们心中闻到了两种模式

  • 并行数据获取
  • 顺序数据获取

蓝色为请求抓取,紫色为渲染

通过并行数据获取, 同一个页面的多个请求可以同时被初始化和加载数据,这样避免瀑布流的方式可以尽量减少总共消耗的时间。

有时你会需要顺序进行的请求,例如你需要将第一个请求拿回数据作为第二个请求的输入,这种方式通常会需要花费数千的时间。

接下来我们来看看在 Next.js Server Components 中分别要怎么实现这两个模式。

并行数据获取

要实现并行数据获取,可以在页面组件发起所有的promise请求,并配置Promise.all等待所有的promise都resolve。

布拉格要注意我们是先开始各个请求再抓取await,所以各个请求可以同时开始抓取数据,避免瀑布式的情况。

但以上这种模式有一个潜在的问题,当其中一个 Promise 需要至少的时间才能解决,因为 Promise.all 的关系,我们会卡在那等待,不会进入返回函数,因此用户在所有请求都解决前面是看不到内容的,这可能对UX来说不是很好的体验。因此我们可以看另一个版本的写法:

对UX更好的并行数据获取

在这个版本中,我们把需要采集比较多时间的数据的承诺丢到下层元件去等待,并用Suspense将该元件包起来,这样在artistData先被解析后,用户可以先看到{artist.name}跟悬念的加载UI,以用户体验的角度来说是比较好的模式。

(关于并行数据获取,官方还提出了一个更进阶的预加载模式,有兴趣的朋友可以再自行看看)

关于顺序数据获取也十分直觉

需要等到上层页面组件先抓取id并确定后才会开始在下层组件做数据抓取。

这种将数据抓取写在下层组件的写法,需要等上层的布局或者页面组件完成抓取后才能够开始,造成瀑布的情况。

静态和动态数据获取

前面提到的数据获取,我们可以更进一步思考数据的种类,一般来说,数据可以分为两种:

  • 静态数据:不会频繁波动的数据,例如部落文章,这类数据就很适合放在快取中。
  • 动态数据:会间隔更动态的数据,例如文章留言。

我们在上面看到了惊人的用 fetch API 提取数据的例子,Next.js 预设会做静态的数据提取,相反 Next 会在构建时做数据提取,并且存到快取中并在之后重用,主要有两个好处:

  1. 减少服务器与资料库的负担
  2. 减少页面的加载时间

也说有些资料是需要间隙更新的,这个时候一律做静态 fetch 就不太好了,开发者应该对这个行为有更高的控制权。刚才已经提到了接下来封装了 fetch API,它其实就可以让我们实现对每一个请求快速取的控制。

通过 fetch API 的第二个对象参数,我们就可以控制每一个请求的快取行为,我们可以发现这些行为跟下一个过去版本的 getServerSideProps、getStaticProps 可以实现 SSR、SSG、ISR 不过非常类似,过去我们只是能够控制页面级别的请求,而在Next13,我们可以以每个请求的角度去思考这件事。

关于 Next.js 13 App Directory 的数据获取,其实还有很多功能没有涵盖到,建议有兴趣的读者进一步阅读官方文件的两篇文章:

数据获取:基础知识 | Next.js

Next.js 13 引入了一种在应用程序中获取数据的新方法。API 已经过简化,以与 React 保持一致......

beta.nextjs.org

数据获取:获取| Next.js

很高兴知道:React 团队目前正在开发这种新的数据获取模型。我们建议阅读...

beta.nextjs.org

流媒体和悬念

Next.js 在 App Directory 中,还引入了 Streaming with Suspense 这个功能。

要了解Streaming是怎么兼容的,我们得先了解SSR的运行机制及其所受的限制。如果过去的页面是采用过去的SSR,需要经过几个步骤,用户才能看到一个完整且能够进行交互的网页:

  1. 在服务器端提取想要的数据
  2. 服务器渲染出 HTML
  3. HTML、CSS、JS的页面被送到客户端
  4. 用户此时可以看到画面,但不能进行互动
  5. React进行水合,赋予UI交互能力

从上图就可以看出这些流程是顺序执行且阻塞的,服务器必须抓取完成所有数据才能渲染 HTML,而在客户端,React 必须等到当前页面中所需要的组件的 JS 代码全部被加载后才能开始进行补水。

Next.js 通过这种方式让用户可以加速看到页面,虽然还是没有交互的,但是以用户体验的角度查看却可以减少用户等待页面加载的时间。

如果我们需要在服务器端抽取大量的数据,那么页面的加载就会变得很慢,用户看到页面的时间会因此被推延。而 Streaming 带来了解决这个问题的机会。

Streaming让我们把页面的HTML分割成多个较小的块,并「渐进式」的把这些块从服务器端传送到客户端。

流媒体

界面可以让完成页面的部分元件可以比较快速地显示,而不用等待所有数据获取都后才能显示任何的 UI。

而 React 的组件模型恰好非常适合 Streaming,因为每个组件我们都可以把它想成一个块,对于网页应用来说比较重要的是拥有优先级的组件(例如说产品的资讯)或者不需要抓获取数据的元件(例如布局)就可以优先传送到客户端让React更早的处理它们。接下来,优先级比较低的元件可以在完成数据获取或复杂计算后再以流式的方式传送到客户端端。

如果你想避免同步的数据抓取块到页面的渲染,造成一些指标分数的表现下降,例如 TTFB、FCP、TTI,那么 Streaming 或许可以给出极大的帮助。

带有流媒体的 SSR

(关于React的Streaming SSR,可以更进一步参考GitHub上的讨论

在 Next.js App Directory 中,我们可以把需要执行一些非同步操作,例如数据获取的元件用 元件包起来,并指定后备的 UI,例如加载 spinner,并在该元件准备好后替换成完整的内容。

对于数据获取来说其实还是一个实验性的功能,Next.js 虽然抢先一步尝试,但也有很多方面还没有很好的解决方案,比如说官方的文件提供的模板都是在 Server Components 中做数据获取并配置Suspense显示加载UI,至于如果要在客户端组件做到类似的事,官方并没有说明如何做到,我们可能需要刚刚提过的React新的"使用"钩子才能帮助处理Promise,而这个功能还在React RFC阶段,未来应该还会充满许多变数。

目前版本遇到限制

我自己实际用 Next 13 App Directory 开发一些副项目后,发现现有的版本实际上遇到了相当多的限制(另外还很容易遇到 Bug 的,不过这先不谈了)。

例如一开始在做技术选型时,我不知想要用自己的 styled-components 这个 CSS-in-JS 的框架,但是后来发现Server Components 目前并不支持运行时的 CSS-in-JS 解决方案

接下来就像在使用很多第三方套件的时候,如果该套件需要用到客户端状态相关的功能,而套件维护者却没有支持客户端组件,我们就需要手动做这件事情才能使用它们。

另外编译的版本对于数据的突变还没有很好的解决方案,例如服务器组件提取了一个TODO列表的数据,用户可以更改每个todo的状态,但目前没有一个很好的方式去触发服务器组件重新抓取新的数据或者更新快取,只能透过刷新的解决方法(看起来我们是极没有效率的从服务器组件根重新抓取一次,而希望的应该是部分的服务器组件重新抓取)渲染),详情可以看官方的文件说明

核心只是大概列出了几点服务器组件在开发上的限制,实际上一定还会随着开发的应用复杂度提升,会遇到更多的问题。这也许代表离服务器组件变成稳定且主流的开发方式,我们还需要再等待一段时间。

未来路线图

关于 Next.js 13 App Directory 目前已经支持的功能以及发行开发的功能,可以参考官方提供的路线图,相信未来支持的功能会越来越稳定和丰富。

应用程序目录路线图 | Next.js

Next.js 13 引入了具有新功能和约定的应用程序目录。随着我们继续迭代 Beta 版、API......

beta.nextjs.org

相关推荐
Ace_31750887761 分钟前
义乌购平台店铺商品接口开发指南
前端
ZJ_3 分钟前
Electron自动更新详解—包教会版
前端·javascript·electron
哆啦美玲4 分钟前
Callback 🥊 Promise 🥊 Async/Await:谁才是异步之王?
前端·javascript·面试
brzhang12 分钟前
我们复盘了100个失败的AI Agent项目,总结出这3个“必踩的坑”
前端·后端·架构
万能的小裴同学19 分钟前
让没有小窗播放的视频网站的视频小窗播放
前端·javascript
小小琪_Bmob后端云1 小时前
引流之评论区截流实验
前端·后端·产品
我科绝伦(Huanhuan Zhou)1 小时前
MOP数据库备份脚本生成工具
前端·css·数据库
海的诗篇_1 小时前
前端开发面试题总结-vue2框架篇(三)
前端·javascript·css·面试·vue·html
Danny_FD1 小时前
在 React 函数组件中实现 `<textarea>` 平滑自动滚动到底部
前端
掘金一周1 小时前
数据脱敏的这6种方案,真香!| 掘金一周 5.29
前端·人工智能·后端