js-cookie vs react-cookie vs universal-cookie
JavaScript 環境における Cookie 管理ライブラリの選定
js-cookiereact-cookieuniversal-cookie類似パッケージ:

JavaScript 環境における Cookie 管理ライブラリの選定

js-cookiereact-cookieuniversal-cookie は、Web アプリケーションで HTTP Cookie を扱うための代表的なライブラリです。js-cookie はブラウザ環境に特化した軽量ライブラリであり、universal-cookie はサーバーサイドレンダリング(SSR)を含む万能な環境で動作するコアライブラリです。react-cookieuniversal-cookie を基盤とし、React 専用のフックやコンテキストを提供して統合を簡素化します。これらはそれぞれ環境要件とフレームワーク依存性において明確な違いがあります。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
js-cookie022,71926.2 kB33年前MIT
react-cookie021378.6 kB310日前MIT
universal-cookie021365.6 kB310日前MIT

Cookie 管理ライブラリ比較:js-cookie vs react-cookie vs universal-cookie

Web 開発において Cookie の扱いは、認証状態の維持やユーザー設定の保存など重要な役割を果たします。js-cookiereact-cookieuniversal-cookie はいずれもこの課題を解決しますが、動作環境と API デザインに大きな違いがあります。アーキテクチャ選定ミスは SSR 環境でのバグや不要な依存関係につながります。ここでは技術的な違いを深掘りします。

🌐 動作環境:ブラウザ専用 vs 万能 vs React 特化

Cookie ライブラリを選ぶ際、最も重要な基準は「サーバーサイドで動作するか」です。

js-cookie はブラウザ環境に特化しています。

  • 内部で document.cookie に直接アクセスします。
  • Node.js やサーバーサイドレンダリング(SSR)環境では動作しません。
  • 起動時にエラーになるため、SSR 構成では使用できません。
// js-cookie: ブラウザ専用
import Cookies from 'js-cookie';

// SSR 環境ではエラー発生(document が未定義)
const value = Cookies.get('session_id');

universal-cookie は名前通り、あらゆる環境で動作します。

  • サーバー側のリクエストオブジェクトから Cookie を読み取れます。
  • クライアント側では document.cookie を使用します。
  • フレームワークに依存しない汎用ロジックに適しています。
// universal-cookie: 万能対応
import Cookies from 'universal-cookie';

// SSR: req/res オブジェクトを渡す
const cookies = new Cookies(req?.res);
const value = cookies.get('session_id');

// Client: 引数なしでインスタンス化
const clientCookies = new Cookies();

react-cookie は React 環境に最適化されています。

  • 内部で universal-cookie を使用しているため、SSR 対応可能です。
  • React のコンテキストとフックを利用して状態を管理します。
  • 構成には CookieProvider のラップが必要です。
// react-cookie: React 特化
import { useCookies } from 'react-cookie';

function Component() {
  // SSR 対応済みフック
  const [cookies] = useCookies(['session_id']);
  const value = cookies.session_id;
}

🛠️ API デザイン:関数型 vs クラス型 vs フック型

ライブラリごとの API スタイルは、コードの書き方とテストのしやすさに影響します。

js-cookie は静的な関数を提供します。

  • インスタンス化不要で、すぐに呼び出せます。
  • 単純なスクリプトや軽量な用途に向いています。
  • 設定は関数の引数で都度指定します。
// js-cookie: 静的メソッド
import Cookies from 'js-cookie';

// 取得
const user = Cookies.get('user');

// 設定(オプションをオブジェクトで渡す)
Cookies.set('user', 'alice', { expires: 7, path: '/' });

// 削除
Cookies.remove('user');

universal-cookie はクラスベースの API です。

  • インスタンスを生成して使用します。
  • 依存性注入(DI)しやすく、テストでモック化しやすいです。
  • 一度インスタンスを作れば、メソッドチェーンで操作できます。
// universal-cookie: クラスインスタンス
import Cookies from 'universal-cookie';

const cookies = new Cookies();

// 取得
const user = cookies.get('user');

// 設定(オプションを第 3 引数で渡す)
cookies.set('user', 'alice', { path: '/', maxAge: 600 });

// 削除
cookies.remove('user');

react-cookie は React フックを提供します。

  • 関数コンポーネント内で状態として Cookie を扱えます。
  • Cookie の変更を検知して再レンダリングさせることができます。
  • 複数の Cookie を一度に取得する機能があります。
// react-cookie: React フック
import { useCookies } from 'react-cookie';

function Component() {
  // 監視する Cookie キーの配列を渡す
  const [cookies, setCookie, removeCookie] = useCookies(['user']);

  const handleLogin = () => {
    setCookie('user', 'alice', { path: '/' });
  };

  return <div>{cookies.user}</div>;
}

⚛️ React 統合:手動管理 vs 自動同期

React アプリケーションにおいて、Cookie の変更をどう状態管理に反映するかは重要な点です。

js-cookie は React 固有の機能を持ちません。

  • useEffect 内で手動で読み書きする必要があります。
  • Cookie が変更されても、コンポーネントは自動で再レンダリングしません。
  • 状態管理は開発者が別途実装する必要があります。
// js-cookie in React
import { useEffect, useState } from 'react';
import Cookies from 'js-cookie';

function Component() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    // 手動で読み込み
    setUser(Cookies.get('user'));
  }, []);

  return <div>{user}</div>;
}

universal-cookie も同様に変化の検知は手動です。

  • React 専用ではないため、ライフサイクル管理は任せられません。
  • 汎用ロジックとして分離したい場合に適しています。
  • カスタムフックを作成してラップするのが一般的です。
// universal-cookie in React
import { useEffect, useState } from 'react';
import Cookies from 'universal-cookie';

const cookies = new Cookies();

function Component() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    setUser(cookies.get('user'));
  }, []);

  return <div>{user}</div>;
}

react-cookie は変更を自動で検知します。

  • setCookie を呼ぶと、関連するコンポーネントが更新されます。
  • 状態と Cookie の同期コストを大幅に削減できます。
  • 提供されたフックを使うだけで реак tive な動作を得られます。
// react-cookie: 自動同期
import { useCookies } from 'react-cookie';

function Component() {
  // Cookie 変更時に自動再レンダリング
  const [cookies, setCookie] = useCookies(['user']);

  return (
    <button onClick={() => setCookie('user', 'bob')}>
      {cookies.user}
    </button>
  );
}

🔒 安全性と設定:シンプル vs 詳細制御

セキュリティ設定(Secure, SameSite, HttpOnly)の扱いも比較ポイントです。

js-cookie は安全なデフォルトを持ちます。

  • 設定オブジェクトで簡単に属性を指定できます。
  • 複雑な設定も直感的な API で扱えます。
  • 最近のバージョンではセキュリティ強化が進んでいます。
// js-cookie: 安全な設定
Cookies.set('session', 'abc', {
  secure: true,
  sameSite: 'Strict',
  path: '/'
});

universal-cookie は詳細な制御が可能です。

  • サーバーサイドで HttpOnly などを設定する際に有利です。
  • React 外でも同じ設定オブジェクトを使えます。
  • 高度なセキュリティ要件がある場合に適しています。
// universal-cookie: 詳細制御
const cookies = new Cookies();
cookies.set('session', 'abc', {
  httpOnly: true, // サーバー側で重要
  secure: true,
  sameSite: 'strict'
});

react-cookie は React 経由で設定を渡します。

  • クライアントサイドからの操作が主目的です。
  • HttpOnly な Cookie は React からは設定できない制約があります。
  • 認証トークンなど機密情報はサーバー側で設定すべきです。
// react-cookie: クライアント側設定
const [cookies, setCookie] = useCookies(['pref']);

// HttpOnly はクライアント側では設定不可
setCookie('pref', 'dark', { path: '/' });

📊 比較サマリー

特徴js-cookieuniversal-cookiereact-cookie
環境🌐 ブラウザ専用🌍 万能(SSR 対応)⚛️ React 環境(SSR 対応)
API🛠️ 静的関数🏗️ クラスインスタンス🎣 React フック
依存関係🍃 なし📦 なし(コア)🔗 universal-cookie 依存
再レンダリング❌ 手動管理❌ 手動管理✅ 自動検知
SSR 対応❌ 非対応✅ 対応✅ 対応(Provider 必要)
サイズ感🪶 軽量📦 標準📦 標準 + React 分

💡 最終的な推奨事項

プロジェクトの要件に応じて、以下の基準で選定してください。

js-cookie は、Next.js や Nuxt などの SSR フレームワークを使わない、シンプルな SPA や静的サイトに向いています — 余計な依存関係を増やさず、ブラウザの機能だけをラップしたい場合に最適です。

universal-cookie は、React 以外を使用している場合や、ビジネスロジック層で Cookie 操作を共通化したい場合に選択してください — サーバーとクライアントで同じコードを動かす必要があるアーキテクチャで真価を発揮します。

react-cookie は、モダンな React アプリケーションで開発効率を最大化したい場合に推奨します — フックによる状態管理と SSR 対応を両立でき、認証フローやユーザー設定の実装を大幅に簡素化します。

結論として、React + SSR 環境なら react-cookie、React なし + SSR なら universal-cookie、それ以外なら js-cookie が適切な選択です。

選び方: js-cookie vs react-cookie vs universal-cookie

  • js-cookie:

    純粋なクライアントサイドアプリケーションで動作し、SSR が必要ない場合に選択してください。依存関係を増やしたくない場合や、ブラウザの document.cookie を単純にラップするだけの軽量ソリューションが必要なプロジェクトに適しています。サーバーサイドでの Cookie 読み書きが必要ないシンプルなケースで最も有効です。

  • react-cookie:

    React アプリケーションを開発しており、フックやコンテキストを使って Cookie 状態を管理したい場合に選択してください。SSR 環境(Next.js など)でも動作する必要があり、React 固有の機能で開発体験を向上させたい場合に最適です。universal-cookie の機能を React 向けに最適化したパッケージです。

  • universal-cookie:

    React 以外のフレームワークを使用しているか、フレームワークに依存しない汎用的な Cookie 管理ロジックが必要な場合に選択してください。SSR とクライアントサイドの両方で動作する必要があるが、React 固有の機能は不要なケースに適しています。react-cookie の内部コアとしても機能する信頼性の高いライブラリです。

js-cookie のREADME

JavaScript Cookie CI BrowserStack JavaScript Style Guide Code Climate npm size jsDelivr Hits

A simple, lightweight JavaScript API for handling cookies

👉👉 If you're viewing this at https://github.com/js-cookie/js-cookie, you're reading the documentation for the main branch. View documentation for the latest release. 👈👈

Installation

NPM

JavaScript Cookie supports npm under the name js-cookie.

npm i js-cookie

The npm package has a module field pointing to an ES module variant of the library, mainly to provide support for ES module aware bundlers, whereas its browser field points to an UMD module for full backward compatibility.

Not all browsers support ES modules natively yet. For this reason the npm package/release provides both the ES and UMD module variant and you may want to include the ES module along with the UMD fallback to account for this:

CDN

Alternatively, include js-cookie via jsDelivr CDN.

Basic Usage

Create a cookie, valid across the entire site:

Cookies.set('name', 'value')

Create a cookie that expires 7 days from now, valid across the entire site:

Cookies.set('name', 'value', { expires: 7 })

Create an expiring cookie, valid to the path of the current page:

Cookies.set('name', 'value', { expires: 7, path: '' })

Read cookie:

Cookies.get('name') // => 'value'
Cookies.get('nothing') // => undefined

Read all visible cookies:

Cookies.get() // => { name: 'value' }

Note: It is not possible to read a particular cookie by passing one of the cookie attributes (which may or may not have been used when writing the cookie in question):

Cookies.get('foo', { domain: 'sub.example.com' }) // `domain` won't have any effect...!

The cookie with the name foo will only be available on .get() if it's visible from where the code is called; the domain and/or path attribute will not have an effect when reading.

Delete cookie:

Cookies.remove('name')

Delete a cookie valid to the path of the current page:

Cookies.set('name', 'value', { path: '' })
Cookies.remove('name') // fail!
Cookies.remove('name', { path: '' }) // removed!

IMPORTANT! When deleting a cookie and you're not relying on the default attributes, you must pass the exact same path and domain attributes that were used to set the cookie:

Cookies.remove('name', { path: '', domain: '.yourdomain.com' })

Note: Removing a nonexistent cookie neither raises any exception nor returns any value.

Namespace conflicts

If there is any danger of a conflict with the namespace Cookies, the noConflict method will allow you to define a new namespace and preserve the original one. This is especially useful when running the script on third party sites e.g. as part of a widget or SDK.

// Assign the js-cookie api to a different variable and restore the original "window.Cookies"
var Cookies2 = Cookies.noConflict()
Cookies2.set('name', 'value')

Note: The .noConflict method is not necessary when using AMD or CommonJS, thus it is not exposed in those environments.

Encoding

This project is RFC 6265 compliant. All special characters that are not allowed in the cookie-name or cookie-value are encoded with each one's UTF-8 Hex equivalent using percent-encoding.
The only character in cookie-name or cookie-value that is allowed and still encoded is the percent % character, it is escaped in order to interpret percent input as literal.
Please note that the default encoding/decoding strategy is meant to be interoperable only between cookies that are read/written by js-cookie. To override the default encoding/decoding strategy you need to use a converter.

Note: According to RFC 6265, your cookies may get deleted if they are too big or there are too many cookies in the same domain, more details here.

Cookie Attributes

Cookie attribute defaults can be set globally by creating an instance of the api via withAttributes(), or individually for each call to Cookies.set(...) by passing a plain object as the last argument. Per-call attributes override the default attributes.

expires

Define when the cookie will be removed. Value must be a Number which will be interpreted as days from time of creation or a Date instance. If omitted, the cookie becomes a session cookie.

To create a cookie that expires in less than a day, you can check the FAQ on the Wiki.

Default: Cookie is removed when the user closes the browser.

Examples:

Cookies.set('name', 'value', { expires: 365 })
Cookies.get('name') // => 'value'
Cookies.remove('name')

path

A String indicating the path where the cookie is visible.

Default: /

Examples:

Cookies.set('name', 'value', { path: '' })
Cookies.get('name') // => 'value'
Cookies.remove('name', { path: '' })

Note regarding Internet Explorer:

Due to an obscure bug in the underlying WinINET InternetGetCookie implementation, IE’s document.cookie will not return a cookie if it was set with a path attribute containing a filename.

(From Internet Explorer Cookie Internals (FAQ))

This means one cannot set a path using window.location.pathname in case such pathname contains a filename like so: /check.html (or at least, such cookie cannot be read correctly).

In fact, you should never allow untrusted input to set the cookie attributes or you might be exposed to a XSS attack.

domain

A String indicating a valid domain where the cookie should be visible. The cookie will also be visible to all subdomains.

Default: Cookie is visible only to the domain or subdomain of the page where the cookie was created, except for Internet Explorer (see below).

Examples:

Assuming a cookie that is being created on site.com:

Cookies.set('name', 'value', { domain: 'subdomain.site.com' })
Cookies.get('name') // => undefined (need to read at 'subdomain.site.com')

Note regarding Internet Explorer default behavior:

Q3: If I don’t specify a DOMAIN attribute (for) a cookie, IE sends it to all nested subdomains anyway?
A: Yes, a cookie set on example.com will be sent to sub2.sub1.example.com.
Internet Explorer differs from other browsers in this regard.

(From Internet Explorer Cookie Internals (FAQ))

This means that if you omit the domain attribute, it will be visible for a subdomain in IE.

secure

Either true or false, indicating if the cookie transmission requires a secure protocol (https).

Default: No secure protocol requirement.

Examples:

Cookies.set('name', 'value', { secure: true })
Cookies.get('name') // => 'value'
Cookies.remove('name')

sameSite

A String, allowing to control whether the browser is sending a cookie along with cross-site requests.

Default: not set.

Note that more recent browsers are making "Lax" the default value even without specifiying anything here.

Examples:

Cookies.set('name', 'value', { sameSite: 'strict' })
Cookies.get('name') // => 'value'
Cookies.remove('name')

Setting up defaults

const api = Cookies.withAttributes({ path: '/', domain: '.example.com' })

Converters

Read

Create a new instance of the api that overrides the default decoding implementation. All get methods that rely in a proper decoding to work, such as Cookies.get() and Cookies.get('name'), will run the given converter for each cookie. The returned value will be used as the cookie value.

Example from reading one of the cookies that can only be decoded using the escape function:

document.cookie = 'escaped=%u5317'
document.cookie = 'default=%E5%8C%97'
var cookies = Cookies.withConverter({
  read: function (value, name) {
    if (name === 'escaped') {
      return unescape(value)
    }
    // Fall back to default for all other cookies
    return Cookies.converter.read(value, name)
  }
})
cookies.get('escaped') // 北
cookies.get('default') // 北
cookies.get() // { escaped: '北', default: '北' }

Write

Create a new instance of the api that overrides the default encoding implementation:

Cookies.withConverter({
  write: function (value, name) {
    return value.toUpperCase()
  }
})

TypeScript declarations

npm i @types/js-cookie

Server-side integration

Check out the Servers Docs

Contributing

Check out the Contributing Guidelines

Security

For vulnerability reports, send an e-mail to js-cookie at googlegroups dot com

Releasing

Releasing should be done via the Release GitHub Actions workflow, so that published packages on npmjs.com have package provenance.

GitHub releases are created as a draft and need to be published manually! (This is so we are able to craft suitable release notes before publishing.)

Supporters

Many thanks to BrowserStack for providing unlimited browser testing free of cost.

Authors