在 Next.js 中读写与删除 Cookie:with-cookies-next 示例的前端 / SSR / API 三端实战解析
导读
examples/with-cookies-next 是 Next.js 仓库中一个高度聚焦的入门示例:它演示了如何借助 cookies-next 这个轻量库,在同一套 API 约定下完成 Cookie 的获取(get)、设置(set)与删除(remove),并且同时覆盖三种运行场景——浏览器端任意组件、getServerSideProps 服务端渲染流程、以及 API Route 处理器。读完本指南,你将掌握 cookies-next 在各场景下的完整调用形态与 { req, res } 选项约定,能直接在自己的 Next.js 项目里照搬这套"一套函数、三端通用"的 Cookie 管理方案。
该示例由一个 React 组件页面、一个 SSR 页面与三个 API Route 组成,全部使用 TypeScript,配套依赖仅需 cookies-next@^2.1.1,非常适合作为理解"客户端 Cookie 与 HTTP Cookie 头如何统一"的最小可运行样板。
一、示例整体结构:一屏看遍三种 Cookie 场景
先看清这个示例由哪些文件构成,方便后续对照:
examples/with-cookies-next/
├── package.json # 依赖与 dev/build/start 脚本
├── tsconfig.json # TypeScript 编译配置
├── README.md # 官方示例说明
└── pages/
├── index.tsx # 客户端场景:按钮驱动的 Cookie CRUD
├── ssr-cookies.tsx # SSR 场景:getServerSideProps 中读写
└── api/
├── set-api-cookie.ts # API 场景:写入 Cookie
├── get-api-cookie.ts # API 场景:读取 Cookie
└── remove-api-cookie.ts # API 场景:删除 Cookie
从目录布局即可看出官方想传达的核心信息(README 原文概括为三条):
- 可以在客户端任意位置使用——组件内直接调用,无需服务端上下文;
- 可以在
getServerSideProps中用于服务端渲染——响应前同步写入/读取; - 可以在 API 处理器中使用——面向接口的 Cookie 操作。
也就是说,cookies-next 的价值不在于"换一种 Cookie 写法",而在于把三个原本 API 风格各异的场景统一成同一套函数签名:在浏览器里不传选项直接调用;在 Node 端把 req/res 作为 { req, res } 传入即可。
二、快速开始:用 create-next-app 初始化示例
示例作者明确推荐通过 create-next-app 直接引导出项目骨架,三种主流包管理器均受支持:
npx create-next-app --example with-cookies-next with-cookies-next-app
yarn create next-app --example with-cookies-next with-cookies-next-app
pnpm create next-app --example with-cookies-next with-cookies-next-app
命令会以本仓库中的 with-cookies-next 目录为模板生成一个名为 with-cookies-next-app 的独立应用。生成后进入目录安装依赖并启动开发服务即可:
cd with-cookies-next-app
npm install # 或 yarn / pnpm install
npm run dev # 默认监听 http://localhost:3000
示例的 package.json 展示了完整的最小依赖集:
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"cookies-next": "^2.1.1",
"next": "latest",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@types/react": "^18.0.14",
"typescript": "^4.7.4"
}
}
几点值得注意:
- 业务依赖只有
cookies-next一个,Cookie 能力完全由它承载,Next.js 本体无需任何额外配置; - 项目启用 TypeScript(含
@types/node、@types/react),tsconfig.json使用"jsx": "react-jsx"、strict: false等宽松但不失规范的默认项; - 提供标准三段式脚本
dev/build/start,可本地开发后构建部署。
该示例还内置了"一键部署到 Vercel 云平台"的 Deploy 入口,适合快速把演示应用发布上线体验效果。
三、客户端场景:在浏览器组件里操作 Cookie
客户端用法是整个示例的入口。打开首页后,页面渲染了五个按钮,分别绑定五个 cookies-next API。先看 pages/index.tsx 的完整实现:
import React from "react";
import {
setCookie,
getCookies,
getCookie,
deleteCookie,
hasCookie,
} from "cookies-next";
const Home = () => {
const handleSetCookie = () => setCookie("client-cookie", "mock client value");
const handleCheckCookie = () => console.log(hasCookie("client-cookie"));
const handleGetCookie = () => console.log(getCookie("client-cookie"));
const handleGetCookies = () => console.log(getCookies());
const handleDeleteCookies = () => deleteCookie("client-cookie");
return (
<div>
<h1>Next Cookies</h1>
<button onClick={handleSetCookie}>Set Cookie</button>
<br />
<button onClick={handleCheckCookie}>Check Cookie</button>
<br />
<button onClick={handleGetCookie}>Get Cookie</button>
<br />
<button onClick={handleGetCookies}>Get All Cookies</button>
<br />
<button onClick={handleDeleteCookies}>Remove Cookies</button>
</div>
);
};
export default Home;
这里一共演示了五个命名导出,职责如下:
| 函数 | 示例调用 | 作用 | 返回 |
|---|---|---|---|
setCookie |
setCookie("client-cookie", "mock client value") |
写入单个 Cookie | 无 |
hasCookie |
hasCookie("client-cookie") |
判断指定 Cookie 是否存在 | boolean |
getCookie |
getCookie("client-cookie") |
读取单个 Cookie 的值 | 值或 undefined |
getCookies |
getCookies() |
读取当前全部 Cookie | 键值对象 |
deleteCookie |
deleteCookie("client-cookie") |
删除指定 Cookie | 无 |
要点说明:
- 客户端调用不需要传
req/res。此时函数内部直接操作浏览器的document.cookie,与纯前端代码无差别,因此可以在任何组件、事件回调、Hook 或工具函数中自由使用。 - 结果是可观测的:示例把
hasCookie/getCookie/getCookies的结果打到console,配合浏览器 DevTools 的 Application → Cookies 面板,可以直观核对"点击 Set Cookie 后出现client-cookie、点击 Remove Cookies 后消失"。 - 读取与写入形态解耦:
hasCookie、getCookie、getCookies都只在发起 HTTP 请求时回读,是典型的"检查再读取"组合,适合做条件渲染或表单默认值回填。
四、SSR 场景:在 getServerSideProps 中读写 Cookie
客户端 API 只能影响当前浏览器。当需要在页面首屏渲染前决定 Cookie 的读取结果(例如登录态判断),就必须走服务端。示例用 pages/ssr-cookies.tsx 演示了在 Pages Router 的 getServerSideProps 中操作 Cookie:
import React from "react";
import { getCookies, getCookie, setCookies, removeCookies } from "cookies-next";
const SsrCookies = () => {
return <div>SSR Cookies</div>;
};
export const getServerSideProps = ({ req, res }) => {
setCookies("ssr-cookie", "mock-ssr-value", { req, res, maxAge: 60 * 6 * 24 });
getCookie("client-cookie", { req, res });
getCookies({ req, res });
removeCookies("client-cookie", { req, res });
return { props: {} };
};
export default SsrCookies;
这段代码信息量很大,逐条拆解:
- 多了一个
{ req, res }选项——这是cookies-next在服务端运行的"环境开关"。只要传入该选项,函数就会从 HTTP 层读取与写入,而不是操作document.cookie。 setCookies("ssr-cookie", "mock-ssr-value", { req, res, maxAge: 60 * 6 * 24 })在 SSR 阶段向响应注入Set-Cookie头。maxAge单位为秒,60 * 6 * 24即 8640 秒(约 2.4 天),该 Cookie 会随首屏 HTML 响应一起下发并被浏览器持久化。- 读取与删除同样以
{ req, res }为基础:getCookie("client-cookie", { req, res })读取的是请求携带的 Cookie(上一节在首页写入的client-cookie会出现在这里);removeCookies("client-cookie", { req, res })则通过设置过期时间为过去时刻来删除它。 - 组件本身
SsrCookies只渲染一行文本,所有 Cookie 操作都发生在getServerSideProps中——这说明该库在服务端是同步、纯函数式的调用形态,逻辑上独立于 React 渲染层,数据通过props传给组件即可。
结合本仓库的 Pages Router 语义,getServerSideProps 每次请求都会在服务端执行,因此这里设置的 Set-Cookie 会被 Next.js 合并进最终响应头,天然满足"首次请求即种下 Cookie"的服务端场景需求。
补充:示例中同时出现了
setCookies与setCookie、removeCookies与deleteCookie两组命名。从页面代码分布看,它们是该库为不同书写习惯提供的等价 API(如首页用setCookie/deleteCookie,SSR 页用setCookies/removeCookies),实际使用时可统一风格,避免混用。
五、API 场景:在 Route Handler 中管理 Cookie
第三块拼图是 API Route。该目录下三个文件分别对应"写入 / 读取 / 删除",并且统一采用 try/catch 包裹、出错时返回 400 与错误信息的稳健写法。逐一来看:
5.1 写入 Cookie —— pages/api/set-api-cookie.ts
import { setCookie } from "cookies-next";
export default async function setApiCookie(req, res) {
try {
setCookie("api-cookie", "mock-value", { req, res, maxAge: 60 * 60 * 24 });
res.status(200).send("set api cookies");
} catch (error) {
res.status(400).send(error.message);
}
}
maxAge: 60 * 60 * 24 把 api-cookie 的生命周期设为 86400 秒(1 天)。客户端只要请求该端点,就会在响应中收到 Set-Cookie: api-cookie=mock-value; Max-Age=86400。
5.2 读取 Cookie —— pages/api/get-api-cookie.ts
import { getCookie, getCookies } from "cookies-next";
import { NextApiRequest, NextApiResponse } from "next";
export default async function getApiCookie(
req: NextApiRequest,
res: NextApiResponse,
) {
try {
const currentCookie = getCookie("api-cookie", { req, res });
const allCookies = getCookies({ req, res });
console.log("currentCookie: ", currentCookie);
console.log("allCookies: ", allCookies);
res.status(200).send("get api cookies");
} catch (error) {
res.status(400).send(error.message);
}
}
这一版显式标注了 req: NextApiRequest 与 res: NextApiResponse 类型(来自 next),是在 API Route 中使用 cookies-next 的推荐类型写法。getCookie("api-cookie", { req, res }) 读取单个 Cookie,getCookies({ req, res }) 读取请求携带的全部 Cookie,结果在服务端日志可见。
5.3 删除 Cookie —— pages/api/remove-api-cookie.ts
import { deleteCookie } from "cookies-next";
export default async function setApiCookie(req, res) {
try {
deleteCookie("api-cookie", { req, res });
res.status(200).send("remove api cookies");
} catch (error) {
res.status(400).send(error.message);
}
}
通过 deleteCookie("api-cookie", { req, res }) 在响应中下发删除指令(将 Cookie 的 Max-Age 置为过期)完成清除。
三个端点合起来,便构成一套完整的"接口版"Cookie 生命周期:GET/POST set-api-cookie 写入 → GET get-api-cookie 读取 → GET remove-api-cookie 删除。这与浏览器端五个按钮形成镜像,让你可以在同一应用中对比两种环境下 API 的异同。
六、三种场景的调用约定速查
把示例中的全部调用点汇总成一张对照表,可在实际开发时快速检索:
| 运行场景 | 代表文件 | 写入 | 读取单个 | 读取全部 | 删除 | 是否需 { req, res } |
|---|---|---|---|---|---|---|
| 客户端(浏览器) | pages/index.tsx |
setCookie |
getCookie |
getCookies |
deleteCookie |
否 |
SSR(getServerSideProps) |
pages/ssr-cookies.tsx |
setCookies |
getCookie |
getCookies |
removeCookies |
是 |
| API Route | pages/api/*.ts |
setCookie |
getCookie |
getCookies |
deleteCookie |
是 |
由此可以推断该库的设计哲学(结合示例代码的调用形态,而非源码内部实现):
- 统一的函数家族:
set、get、getAll、remove/has等动词在浏览器与 Node 端完全一致,学习成本被压到最低; - 环境由选项驱动:传入
{ req, res }即进入 HTTP 上下文(读取请求头中的 Cookie、把写入结果附加到响应头),不传则回退到document.cookie; maxAge统一按秒计:示例中 8640 秒(约 2.4 小时级 SSR 演示)与 86400 秒(1 天级 API 演示)都是秒为单位,可直接按业务换算,不设置则默认为会话级 Cookie。
七、上手该方案时的注意事项
基于本示例代码,整理几条实操时最容易被忽略的边界:
- 服务端写入本质是写响应头。
setCookies在getServerSideProps中生效的前提是 Next.js 会把该阶段设置的响应头合入最终 HTML 响应;因此在纯客户端静态页面或不使用 Pages Router 数据获取函数的地方,服务端写入没有意义,应走客户端 API。 - 读取"别人种下的 Cookie"依赖请求头。SSR/API 中
getCookie("client-cookie", { req, res })读到的是客户端后续请求自动携带的 Cookie——这要求写入端与读取端的域名、路径保持一致。 - TypeScript 项目记得为 API handler 标注类型。参考 get-api-cookie.ts 中
NextApiRequest/NextApiResponse的用法,可获得完整的参数提示与错误检查。 - 错误处理可复用示例的
try/catch模式。三个 API 端点都捕获异常并回400 + error.message,避免 Cookie 解析失败时抛出未处理异常导致 500。 - 安全性仍由开发者负责。示例只用于演示 API 形态,生产环境若存放会话标识或敏感信息,仍需自行配置
HttpOnly、Secure、SameSite等属性(cookies-next支持将 Cookie 选项透传)。
若想继续深入,可对照阅读仓库中其他 Pages Router 数据获取与 API Route 的示例(如 with-cookies-next 目录外的 examples/with-iron-session 等基于 Cookie 的会话方案),观察在真实业务中如何在此基础上叠加加密与校验逻辑。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00