見出し画像

nextjs with typescript:29 SSRとCSRとCookie

【1】SSR側にもCookieが必要

 前回まではCSR(Client Side Rendering)を前提としたCookieの話。今の状態では、SSR(Server Side Rendering)のページは認証エラー扱いとなり動かない。これを確認してみる。

■動作確認のための準備
細かなエラー処理などは省略。
【/pages/index.tsx】:リンクを追加

import Link from 'next/link'
import Layout from '../components/Layout'

const IndexPage = () => (
   <Layout title="Home | Next.js + TypeScript Example">
     <h1>Hello Next.js 👋</h1>
     <p>
       <Link href="/about">
         <a>About</a>
       </Link>
     </p>

     <div>
       <Link href="/csrpeople">
         <a>CSRpeople</a>
       </Link>
     </div>


   </Layout>
 )

export default IndexPage

画像1

【./pages/csrpeople.tsx】:クライアント側でデータフェッチをするページ

import axios from "axios";
import useSWR from "swr";


const CsrPeople =()=>{
   const {data,error} = useSWR(
           'http://localhost:3000/api/people',
           (url:string)=> axios(url).then(res => res.data)
       );
   
       console.log(data);

   return(
       <div>
           <h1>Client Side Rendering</h1>
           {JSON.stringify(data,null,4)}
       </div>
   );

}

export default CsrPeople

↓ 未/login状態での挙動確認

画像2

【./pages/ssrpeople.tsx】:サーバサイドレンダリングのページ

import { GetServerSideProps } from "next";

interface Person{
   id:number;
   name:string;
   email:string;
}

//SsrPeopleコンポーネントがうけつけるpropsの型
interface PeopleProps {
   people:Person[]
}


const SsrPeople =({people}:PeopleProps)=>{

   return (
       <div>
           <h1>SSR rendering </h1>

           {JSON.stringify(people,null,4)}
       </div>
   );

}

export default SsrPeople


export const getServerSideProps:GetServerSideProps = async (ctx)=>{
   
   const cookie = ctx.req?.headers.cookie;
   
   const res = await fetch('http://localhost:3000/api/people',
       {
           headers:{
               cookie:cookie!
           }
       }
   );
   const people = await res.json();
   return {props:{people}};
}

↓ 未/login状態での挙動確認

画像3

この時点ではどちらも未/login状態で認証エラーをだす。次に/loginで認証してみる。(認証したJWTをCookieにセットしてブラウザに入れる)

■/loginで認証(Cookieをブラウザにいれる)して再確認

画像4

■CSR側のページ【./pages/csrpeople.tsx】の動作

画像5

■SSR側のページ【./pages/ssrpeople.tsx】の動作

画像6

あくまでクライアント側であるブラウザがCookieを持っているだけで、SSR側は発行されたCookieを持っていない。その結果、サーバサイドでデータフェッチをしにいっているが、認証エラーを返されてしまう。

画像7

【2】SSR側にCookie情報をセットする

SSRする際にもリクエストヘッダCookieは存在しているので、これを取り出してfetch関数のheaderにセットすればよい。

画像8

【./pages/ssrpeople.tsx】

import { GetServerSideProps } from "next";

interface Person{
   id:number;
   name:string;
   email:string;
}

//SsrPeopleコンポーネントがうけつけるpropsの型
interface PeopleProps {
   people:Person[]
}


const SsrPeople =({people}:PeopleProps)=>{

   return (
       <div>
           <h1>SSR rendering </h1>

           {JSON.stringify(people,null,4)}
       </div>
   );

}

export default SsrPeople


export const getServerSideProps:GetServerSideProps = async (ctx)=>{
   
   const cookie = ctx.req?.headers.cookie;
   
   const res = await fetch('http://localhost:3000/api/people',
       {
           headers:{
               cookie:cookie!
           }
       }
   );
   const people = await res.json();
   return {props:{people}};
}

・動作確認

画像9


■その他

Cookie処理のヘルパーとして例えば「nookies」がある。Cookie処理にはこのようなライブラリを使うと楽になる。

なお、httpOnly属性が「true」の場合は、JavaScriptからアクセスできなくなる、ということを覚えておこう。
 Cookieの値をとれない、操作できない、という場合にこれが原因であることもありえる。うっかり忘れてて何時間も悩む、なんてことにならないようにしよう。

もっと応援したいなと思っていただけた場合、よろしければサポートをおねがいします。いただいたサポートは活動費に使わせていただきます。