– それはサーバーサイド・レンダリングではありません。
2020年は誰にとっても狂気の年であった。 この年末のホリデー シーズンでは、React チームは最近、React Server Components を使用して React アプリを構築する新しい方法に関するエキサイティングな研究を発表しました。
React Server Components はまだ開発中で、製品化にはまだ推奨されていないことを心に留めておいてください。 この機能は完全にオプションであり、現在と同じようにコンポーネントを書くことができます。
1時間の講演とデモはここで見ることができますが、重要な部分を強調して説明した5分間のガイドがここにあります。
また、Reactの新しいコンポーネントが今後のデザインシステムでどのような役割を果たすのか気になる方は、
React Server Componentは、Reactアプリのパフォーマンスを改善する目的でサーバーサイドでレンダリングされるReactコンポーネントを記述する方法です。
Reactでアプリケーションを開発する際に直面する問題の1つは、ユーザーが要求したページ/データが利用可能になるのを待つ間に、ネットワーク要求の数が一般的に多くなることです。
たとえば、今日のデータ フェッチに対する共通のアプローチは、useEffect
フックを使用して API を呼び出すことです。
useEffect(() => {
axios.get("URL HERE")
.then((response) => {
// set data into state setData(response.data);
})
.catch((error) => {
console.log(error);
});
}, );
それについては何も問題はありませんが、このデータ取得アプローチでは、ユーザーにとって意味のあるものを表示するために、常にある程度の時間がかかります。
もう 1 つの問題は、もちろんバンドル サイズです。 最小化、コード分割、デッド コード除去は、React アプリケーションのバンドル サイズを縮小するために使用される手法のいくつかの例です。 なぜでしょうか? バンドルサイズが大きいと、ダウンロードに時間がかかるからです。 誰もが高速なデバイスと高速なインターネットを利用できるわけではありません。
React Server Components は上記の2つの問題とその他の多くのことを解決するために役に立ちます。
How React Server Components work
React Server Components はまだ実験段階のため、この機能の実装詳細は変更される可能性があります。 それでも、デモを見ることで、そのコア コンセプトのいくつかをつかむことができます。
最初に気づくのは、package.json
ファイルに実験的なバージョンを持つパッケージがいくつかあることです。
"react": "0.0.0-experimental-3310209d0",
"react-dom": "0.0.0-experimental-3310209d0",
"react-fetch": "0.0.0-experimental-3310209d0",
"react-fs": "0.0.0-experimental-3310209d0",
"react-pg": "0.0.0-experimental-3310209d0",
"react-server-dom-webpack": "0.0.0-experimental-3310209d0",
react
, react-dom
, react-server-dom-webpack
は React Server Component を有効にする実験的なバージョンを使用しており、react-fetch
, react-fs
, react-pg
は入出力システムとの対話に使用するラッパー パッケージ群(これらは React IO ライブラリと呼ばれます)
次のポイントは、このデモは Express.Xpress によって駆動されていることです。これは、コンポーネントをレンダリングするためにサーバーが必要であるため、理にかなっています。 しかし、これはまた、Server Components が JavaScript 環境でのみ動作するということなのでしょうか? Go、Java、およびその他のサーバーサイド環境ではどうでしょうか。
将来的には、他の環境にも対応するかもしれませんので、この点はひとまず置いておいて、
もちろん、これらの実装詳細は、将来的に研究が進めば変わるかもしれません。
src/
フォルダ内のコードに移動すると、コンポーネント ファイルの拡張子が 3 種類あることがわかります。
-
.server.js
拡張子は Server Components -
.client.js
拡張子は React Client Components - 通常の
.js
は共有コンポーネント用の拡張子です。 これらのコンポーネントは、誰がインポートするかによって、サーバーまたはクライアントで実行することができます。
npm start
コマンドでアプリケーションを起動すると、2 つのタスクが同時に実行されます。
-
server/api.server.js
スクリプトを使用して実行されている Node サーバー -
scripts/build.js
スクリプトを使用して、クライアント側の React バンドル用の Webpack ビルド
サーバー スクリプトを見てみると、app.server.js
がファイルに取り込まれつつあることが確認されます。
const ReactApp = require('../src/App.server').default;
そして後で Node Writable ストリームとして処理されます:
const {pipeToNodeWritable} = require('react-server-dom-webpack/writer');async function renderReactTree(res, props) {
await waitForWebpack();
const manifest = readFileSync(
path.resolve(__dirname, '../build/react-client-manifest.json'),
'utf8'
);
const moduleMap = JSON.parse(manifest);
pipeToNodeWritable(React.createElement(ReactApp, props), res, moduleMap);
}
依存関係を含む .server.js
拡張以下のコードはクライアント バンドルに含まれないので、バンドル サイズへの影響はゼロとなります。
Server Components はサーバー上のデータベースまたはファイルシステムに直接アクセスできるので、最初のレンダリングで必要なデータをピックアップしてクライアントに送信することができます。 この例は NoteList.server.js
file:
export default function NoteList({searchText}) {const notes = db.query(
`select * from notes where title ilike order by id desc`,
).rows;
return notes.length > 0 ? (
<ul className="notes-list">
{notes.map((note) => (
<li key={note.id}>
<SidebarNote note={note} />
</li>
))}
</ul>
) : (
<div className="notes-empty">
{searchText
? `Couldn't find any notes titled "${searchText}".`
: 'No notes created yet!'}{' '}
</div>
);
}
Server Components はいかなるインタラクティブ機能も持たないので、サーバー側で useState
やリスナーを作成することはできません。 クライアント側に状態を入れて、Server Components からそれらをインポートする必要があります。
React Server Component の利点はなんですか
- Server components はバンドルには含まれていないのです。 それらはブラウザによって決してダウンロードされず、バンドル サイズにゼロの影響を与えます。 データベースまたはファイルシステムから直接データをフェッチでき、クライアント側と同様に API からもフェッチできます。
- Server components can also read GraphQL queries
How is That Different from Server Side Rendering?
SSR が React アプリケーションで現在どのように機能するかは、単に HTML としてレンダーされたコンポーネントをクライアントに送信し、アプリケーションが高速応答を持っていると思わせることです。 ユーザーは、JavaScript がダウンロードされるまで、アプリで何もできません。
React Server Components は異なります。 デモで示したように、Server Components は HTML としてではなく、クライアントにストリーミングされる特殊なフォーマットとしてレンダリングされます。 このストリームには今のところ標準的なプロトコルはありませんが、JSON 形式によく似ています。 以下は応答の一部です。
M1:{"id":"./src/SearchField.client.js","chunks":,"name":""}
SSR が最初のレンダリングに 1 回だけ使用されるのに対し、Server Components はデータ (デモの場合は markdown 投稿) を再レンダリングするために複数回再フェッチすることが可能です。 これは、React アプリケーションがクライアントのバンドル サイズに影響を与えることなくパッケージをインポートし、クライアント コンポーネントを使用してインタラクティブにすることができるアプリケーションの静的な表現を作成します。
開発者は、単一の DOM ツリーでサーバー コンポーネントとクライアント コンポーネントの両方を使用することもでき、クライアント コンポーネントの状態を破棄せずにサーバー コンポーネントを再取得することが可能になります。
React チームは現在、この機能を Next.js や Gatbsy などのメタフレームワークに導入することに集中しており、PHP、Python、Go、または Ruby などの他のサーバーサイド言語のサポートを見るまでには(もしそうなるとしても)時間がかかるかもしれない。 サーバー側の React はオプションです。
また、React Server Components の設計システムを作成すべきかについて私の考えを共有しましたので、興味を持たれるかもしれません。