サーバーサイドレンダリング
このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →
SSRを有効化するには、createTRPCNextの設定コールバックでssr: trueを設定するだけです。
SSRを有効にすると、tRPCはサーバー上ですべてのクエリをプリフェッチするためにgetInitialPropsを使用します。これにより、getServerSidePropsを使用する際にこのような問題が発生する可能性があり、この解決は当方の手に負えません。
代わりに、SSRを無効(デフォルト)のままにし、Server-Side Helpersを使用してgetStaticPropsまたはgetServerSidePropsでクエリをプリフェッチすることもできます。
サーバーサイドレンダリングのステップでクエリを適切に実行するには、configに追加のロジックを組み込む必要があります:
さらに、Response Cachingの利用も検討してください。
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import { ssrPrepass } from '@trpc/next/ssrPrepass';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({ssr: true,ssrPrepass,config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import { ssrPrepass } from '@trpc/next/ssrPrepass';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({ssr: true,ssrPrepass,config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},});
あるいは、特定のリクエストに基づいてSSRを条件付きで行いたい場合、ssrにコールバック関数を渡せます。このコールバックはboolean、またはbooleanに解決するPromiseを返します:
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
utils/trpc.tstsximport { httpBatchLink } from '@trpc/client';import { createTRPCNext } from '@trpc/next';import superjson from 'superjson';import type { AppRouter } from './api/trpc/[trpc]';export const trpc = createTRPCNext<AppRouter>({config(config) {const { ctx } = opts;if (typeof window !== 'undefined') {// during client requestsreturn {links: [httpBatchLink({url: '/api/trpc',}),],};}return {links: [httpBatchLink({// The server needs to know your app's full urlurl: `${getBaseUrl()}/api/trpc`,/*** Set custom request headers on every request from tRPC* @see https://trpc.io/docs/v10/header*/headers() {if (!ctx?.req?.headers) {return {};}// To use SSR properly, you need to forward client headers to the server// This is so you can pass through things like cookies when we're server-side renderingreturn {cookie: ctx.req.headers.cookie,};},}),],};},ssr(opts) {// only SSR if the request is coming from a botreturn opts.ctx?.req?.headers['user-agent']?.includes('bot');},});
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
pages/_app.tsxtsximport { trpc } from '~/utils/trpc';import type { AppProps } from 'next/app';import React from 'react';const MyApp: AppType = ({ Component, pageProps }: AppProps) => {return <Component {...pageProps} />;};export default trpc.withTRPC(MyApp);
よくある質問
Q: クライアントのヘッダーをサーバーに手動で転送する必要があるのはなぜですか? tRPCが自動で転送しないのはなぜですか?
SSR実行時にクライアントのヘッダーをサーバーに転送したくないケースは稀ですが、ヘッダーに動的に要素を追加したい場合があるからです。そのためtRPCは、ヘッダーキーの衝突などの責任を負いたくありません。
Q: Node 18でSSRを使用する際、なぜconnectionヘッダーを削除する必要があるのですか?
connectionヘッダーを削除しない場合、データ取得がTRPCClientError: fetch failedで失敗します。これはconnectionが禁止ヘッダー名だからです。
Q: ネットワークタブに依然としてリクエストが表示されるのはなぜですか?
デフォルトでは、データ取得フックに使用している@tanstack/react-queryは、SSR経由で初期データを取得済みの場合でも、マウント時やウィンドウのフォーカス時にデータを再取得します。これによりデータが常に最新状態に保たれます。この動作を無効化したい場合は、SSGのページを参照してください。