34
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Next.jsでcookieをシンプルに扱うことができるライブラリ nookies を紹介

Next.jsでcookieを扱うのは大変

Next.jsなどのサーバーサイドレンダリング(以下SSR)をしているフレームワークでcookieを扱うのは面倒くさいですよね。
その理由の一つとして、同じコードでもSSRの場合とクライアントでレンダリングしている場合で挙動が違うということがあります。
例をお見せしましょう

クライアントでレンダリングしている場合

console.log(document.cookie); // accessToken=test1234;

SSRの場合

console.log(document.cookie); // ReferenceError: document is not defined

原因

クライアントサイド(ブラウザ)でレンダリングしている時は、ブラウザに保存されているcookieにアクセスできるが,
SSRの時はブラウザに保存されているcookieにアクセスできません。

SSRの時にcookieを扱うには

SSRでcookieの情報はここに入っています

index.tsx
const TestPage: NextPage<Props> = (props) => {
    return <div>test</div>
}

TestPage.getInitialProps(ctx) {
    // ここ
    console.log(ctx.req.headers.cookie) // accessToken=test1234;     

    return {};
}

同じライブラリをクライアントとSSRで共有していたりすると、条件分岐などが大変ですね
そんな時に nookies を使います
https://www.npmjs.com/package/nookies

使い方

以下の例で示すようにクライアントサイドの場合ctxを渡さずに、SSRならctxを渡せば、cookieをオブジェクトに整形して返してくれます。

tool.ts
import { parseCookies } from 'nookies';
import { NextPageContext } from 'next';

export function printCookie(ctx?: NextPageContext) {
    const cookie = parseCookies(ctx);
    console.log(cookie) // { accessToken: 'test1234' }
}

また、cookieの追加もクライアントとSSR分け隔てなく行ってくれます

set_cookie.ts
import { setCookie, destroyCookie } from 'nookies';
import { NextPageContext } from 'next';

export function setCookie(ctx?: NextPageContext, token: string) {
        setCookie(ctx, 'accessToken', token, {
            maxAge: 30 * 24 * 60 * 60,
        });
}

// ついでにcookie削除(動作確認してません)
export function destroyCookie(ctx?: NextPageContext) {
    destroyCookie(ctx, 'accessToken')
}

ライブラリを読んでみた(箇条書きです!)

nookies/src/index.ts
const isBrowser = () => typeof window !== 'undefined' // 今の環境がSSRかクライアントサイドレンダリングか調べてるらしいです

.
.

if (ctx && ctx.req && ctx.req.headers && ctx.req.headers.cookie) { 
    return cookie.parse(ctx.req.headers.cookie as string, options) // SSRだったらctx.req.headers.cookieに入っているcookieをparseして返却
} 

.
.

if (isBrowser()) { 
   return cookie.parse(document.cookie, options) //クライアントだったらdocument.cookieにあるcookieをparseして返却
} 

.
.

ctx.res.setHeader('Set-Cookie', cookiesToSet) // SSRならレスポンスヘッダーにcookieをセットする

.
.

if (isBrowser()) { |
    document.cookie = cookie.serialize(name, value, options) // クライアントならクッキーをセット
}

まとめ

以上です。いかがでしたでしょうか?
参考になりましたら幸いです。

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
34
Help us understand the problem. What are the problem?