Next13服务端组件尝鲜:这才是真的React18

1,918 阅读3分钟

Next13

上周的Next Conf带来劲爆的turbopack,相信不少小伙伴都关注到了。其实这次的Next Conf还有一大主角,Next.JS 13 - 我愿称之为真.React18

在Next13中,许多React18的特性都得到了解锁:

本文主要介绍前三个内容,体验下Next13服务端组件带给前端的冲击(可能开启真的大前端时代了

如何开始体验Next13

NextJS提供完整的文档,目前还在Beta状态, beta.nextjs.org/docs/gettin…

使用下面Cli脚本马上开始体验Next13

npx create-next-app@latest --experimental-app

React服务端组件

先看Next13的重头戏,也是2020年React团队新开的坑RSC,Next13中终于可以使用了。

在Next13中,app目录下的组件默认都是服务端组件,在服务器中渲染好再返回到浏览器(默认没有交互,不需要水合)。有了服务端组件,我们可以在React应用中用同一套React语法,混合使用服务端组件和客户端组件。

image.png

为什么需要服务端组件

  • React服务端组件中可以使用Nodejs的各种能力
  • 在服务端组件中发起请求,可以在请求返回HTML前,就完成数据的读取。相比原来JS应用从服务端传送JS资源到客户端,React完成渲染后再向服务端请求数据,大幅减少FCP(首次内容绘制时间)
  • 有效减少传送到浏览器的JS包体积
  • 传统SSR的各种优势(SEO友好,首屏渲染快)

异步服务端组件

在服务端组件中,可以直接在组件中使用async/await,获取到数据后,传给客户端组件。这也是Next13推荐使用这种方式读取数据。

async function getData() {
  const res = await fetch('https://api.example.com/...');
  // 返回值不需要序列化 可以return Date, Map, Set.
  return res.json();
}

export default async function Page() {
  const name = await getData();

  // 数据传递到客户端组件,会被序列化
  return <ClientCompoent name={name} />;
}

通过异步服务端组件,我们可以复用一切Nodejs中已经存在的能力,延展React组件的边界,如:

  • 充当BFF层,来向后端获取数据
  • 使用RPC向后端获取数据
  • 直接使用ORM框架例如prisma,从DB中获取数据 (小应用一把梭,新时代的PHP)
  • 直接从消息队列中消费数据,例如使用KafkaJS从Kafka中获取数据

目前的限制

  • 服务端组件中渲染另一个异步服务端组件目前会有TS告警,因为async函数返回值是Promise,当前Promise的值不能作为JSX去渲染,需要React组件TS类型更新支持
  • 不能在客户端组件去渲染服务端组件(所以客户端组件应该尽量靠近整个应用的叶子节点)

客户端组件

客户端组件即原来我们写的运行在浏览器的React组件,需要'use client'标识。

'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

新的Hook use

Next13的客户端组件中,可以使用use同步式的去处理异步方法,对标服务端组件的await。 如下面的getDate这个异步函数,既可以在服务端组件中通过await拿到数据,也能复用到客户端组件中通过use去拿到数据

async function getData() {
  const res = await fetch('https://api.example.com/...');
  return res.json();
}
'use client';

export default function Page() {
  const name = use(getData());

  return <h1>{name}</h1>;
}

服务端组件和客户端组件应该怎么选择?

用途服务端组件客户端组件
从服务端获取数据尽量不要
读取服务端静态资源
保存敏感数据,如tokens,API,keys
大体积的JS依赖
交互和事件监听
状态和生命周期(useState, useReducer, useEffect())
浏览器API
自定义Hooks涉及状态和生命周期
React类组件