RCC 与 RSC 的环境隔离
前言
我们知道,在 React Server Component 环境下,渲染的运行时永远都是在 server 的,而在 RCC 中,两者环境都可能存在。为了控制一个库的引用方只能处于某种环境中,而在另一个环境中报错,我们可以使用 client-only
或者 server-only
库。
Next.js 是最先支持 React Server Component 的,并且遵循了 server-module-conventions rfc 下文都以 Next.js 展开。
这个 rfc 中指出,在 package.json
中 exports
字段新增了 react-server
导出,这个字段的导出位置只会被 RSC 中的引用链使用。
例如,client-only/package.json
是这样定义的。
react-server
会写在第一行,优先被识别。那么在 RSC 组件中引用 client-only
的话实际引用的就是 ./error.js
,这个时候就会报错。
实际使用场景
在全新的 React 架构中,RSC + RCC 两种环境的结合已经是常态了。那么对于库来说,需要同时兼容两种环境下的使用方式就需要这个特征了。
这里我们已 next-intl 为例,这是一个 i18n 的库。这个库的使用方式在 RSC 中还是在 RCC 中都是相同的。例如
在 RCC 中,我们这样去使用 useTranslations
。
在 RSC 中,我们这样去使用 useTranslations
。
你可能发现了,这两种环境下,使用的方法是一样的,方法的导出也是一样的。但是你注意到了,在 RSC 中是不能用 hooks 的,但是这里却没有问题。
这里就设计到了前面提到的 server-module-conventions 了,在 RSC 中导入的 useTranslations
其实并不是一个 hook 而只是一个普通的方法,只不过为了保证方法调用的一致性,名称也是保证了一致。
继续挖掘 next-intl
的 package.json
发现他的 exports
是这样定义的。
而在 RSC 中真正指向的其实是 https://github.com/amannn/next-intl/blob/main/packages/next-intl/src/react-server/useTranslations.tsx,这些都是对 RSC 下的实现。
在业务中使用场景
这里列举一个最近遇到的场景,关于需要在两个场景下区分 ofetch 实例。我们知道,在 Next.js 的 RCC 和 RSC 下获取 Cookie 的方式是不一样的,另外在预渲染页面时请求的接口总是在 RSC 下发出的,我们或许需要在请求发出时,附加一些请求信息,比如鉴权相关的 header、user-agent、或者转发真实请求者的 IP 信息等等。
这种情况下,我们可以针对两个环境编写两个不同的实例。
首先,建立一个内部包。例如 packages/fetch
。
建立 package.json
。
编写 fetch.server.ts
用于 RSC。
编写 fetch.client.ts
用于 RCC。
现在,两者都有了相同的方法,并且都导出了。那么我们就可以在业务中使用了。为了更好的 TypeScript 支持,我们需要修改 "moduleResolution": "Bundler"
。对了,别忘记,在 package.json
中 link 这个依赖。例如这里,"@shiro/fetch": "link:./packages/fetch"
添加到项目的 package.json
的 dependencies
中。
使用为:
最后更新于 2024/7/26 16:15:59
本书还在编写中..
前往 https://innei.in/posts/tech/my-first-nextjs-book-here#comment 发表你的观点吧。