ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Payload 3 自定义服务器实战:用 Express 接管 Next.js 请求生命周期的完整方案

Payload 3 自定义服务器实战:用 Express 接管 Next.js 请求生命周期的完整方案 Payload 3 自定义服务器实战用 Express 接管 Next.js 请求生命周期的完整方案【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload本篇指南基于 Payload 官方仓库的examples/custom-server示例讲解如何脱离 Next.js 默认的next dev/next start改用 Express 搭建一个完全可控的自定义 Node.js 服务器Custom Server来托管 Payload 3。读完本文你能掌握自定义服务器的请求路由机制getRequestHandler与parse的配合、开发环境与生产环境两套启动链路nodemon tsx 热重载、tsc编译后node dist/server.js、以及 Payload 在自定义服务器架构下的集成点withPayload配置包裹、REST/GraphQL 路由、admin 视图适用于需要 WebSocket、自定义中间件、SSE 或自有进程管理的团队。为什么需要自定义服务器Next.js 默认由next dev与next start管理 HTTP 服务但在以下场景需要接管整个 Node.js 进程需要自定义中间件链限流、日志、鉴权前置处理并在所有请求上生效需要 WebSocket、SSE、长连接或流式响应需要自管进程模型热重载策略、多端口、优雅退出需要把 Payload 的后端与自有的业务 API 服务在同一个 Express 应用里路由分发。Payload 3 官方示例examples/custom-server正是基于 Next.js 官方的 custom-server 示例改造而来核心思路是Express 作为唯一入口所有无法匹配的业务请求最终委托给 Next.js 的请求处理器而 Payload 的 REST API、GraphQL 和 admin 后台则以 Next.js App Router 路由文件的形式存在被这个处理器一并承载。项目结构与关键文件示例的完整结构如下所有自定义服务器相关逻辑集中在server.ts与两个 tsconfig 中Payload 部分则是标准的payloadcms/next集成examples/custom-server/ ├── src/ │ ├── server.ts # 自定义服务器入口Express Next.js │ ├── payload.config.ts # Payload 配置 │ ├── collections/ # Users / Media 集合 │ ├── payload-types.ts # 生成的类型文件 │ └── app/ │ ├── (app)/ # 你自己的前台页面 │ │ ├── layout.tsx │ │ └── b/page.tsx │ └── (payload)/ # Payload 生成的路由勿手改 │ ├── admin/[[...segments]]/page.tsx # admin 后台 │ ├── api/[...slug]/route.ts # REST API │ ├── api/graphql/route.ts # GraphQL │ └── api/graphql-playground/route.ts ├── next.config.ts # 用 withPayload 包裹 Next 配置 ├── tsconfig.json # 前端/Next 侧 tsconfig ├── tsconfig.server.json # 服务器端独立 tsconfig编译到 dist ├── nodemon.json # 开发热重载配置 └── package.json自定义服务器核心实现server.ts 的全部逻辑只有 25 行这是整个方案的核心import express from express import { parse } from url import next from next const port parseInt(process.env.PORT || 3000, 10) const dev process.env.NODE_ENV ! production const app next({ dev }) const handle app.getRequestHandler() app.prepare().then(() { const server express() server.all(*, (req, res) { const parsedUrl parse(req.url!, true) handle(req, res, parsedUrl) }) server.listen(port, () { console.log( Server listening at http://localhost:${port} as ${ dev ? development : process.env.NODE_ENV }, ) }) })逐段解析其工作机制next({ dev })dev由NODE_ENV ! production推导。同一份server.ts既用于开发Next 走 watch 编译支持 HMR也用于生产走预构建产物dist/.next。app.getRequestHandler()拿到 Next.js 的请求处理器它负责把 App Router 的路由包括 Payload 生成的 REST/GraphQL/admin 路由解析成响应。app.prepare().then(...)prepare()在开发模式下完成初始编译、在生产模式下加载构建产物。Express 服务器必须在其 resolve 之后才启动否则第一个请求会因 Next 未就绪而失败。server.all(*, ...)兜底路由这里用 Node 内置url.parse(req.url, true)解析出parsedUrlparse的第二个参数true表示同时解析 query string 到query属性再交给handle(req, res, parsedUrl)。这是 Next.js 自定义服务器的标准委托模式。扩展点由于 Express 是入口你可以在兜底路由之前插入任意中间件和路由例如server.use(/internal, myInternalApi) // 自己的业务路由 server.use(rateLimitMiddleware) // 自定义中间件 server.all(*, (req, res) { ... }) // 其余请求交给 Next/Payload从源码结构看示例本身只保留了最简形态直接全部委托但 Express 的路由匹配规则保证先注册的路由优先命中因此扩展并不侵入 Payload 的既有行为。开发模式nodemon tsx 热重载package.json 中的脚本定义了完整的工作流scripts: { build: payload build tsc --project tsconfig.server.json, dev: nodemon, generate:importmap: cross-env NODE_OPTIONS--no-deprecation payload generate:importmap, generate:types: cross-env NODE_OPTIONS--no-deprecation payload generate:types, payload: cross-env NODE_OPTIONS--no-deprecation payload, start: cross-env NODE_ENVproduction node dist/server.js }开发时执行pnpm dev实际行为由 nodemon.json 驱动{ watch: [src/server.ts], exec: tsx src/server.ts, ext: ts }tsx直接以 ESM/TS 执行src/server.ts无需预编译nodemon 监视server.ts变化后重启进程由于dev trueNext 侧的 HMR 仍正常工作只是 Node 进程本身在 server 文件改动时重启前端页面代码的热更新走 Next.js 自身机制两者互不干扰。生产模式独立编译服务器端代码pnpm build依次做两件事payload build执行 Next.js 构建Payload 的 CLI 在此会先运行类型/导入映射相关准备再触发next buildtsc --project tsconfig.server.json单独把服务器端代码编译进dist/。tsconfig.server.json 与主 tsconfig.json 的关键差异值得注意{ extends: ./tsconfig.json, compilerOptions: { module: ESNext, outDir: dist, lib: [es2019], target: ESNext, isolatedModules: false, noEmit: false }, include: [src/server.ts] }主 tsconfig 服务于 Next 侧设置了noEmit: trueNext 自己转译服务器端必须noEmit: false并指定outDir: dist因为最终是裸node dist/server.js运行include只包含src/server.ts避免把 React 组件也编译进服务器产物module: ESNext与type: module的package.json一致保证 ESM 输出。生产启动pnpm start即NODE_ENVproduction node dist/server.js。此时dev为falseNext 从.next构建产物提供请求Express 依旧作为唯一监听端口默认 3000可用PORT环境变量覆盖。Payload 在自定义服务器架构下的集成自定义服务器只改变了“谁来监听端口”Payload 的集成方式与标准 Next.js 模板一致1. Next 配置包裹— next.config.ts 仅 6 行import { withPayload } from payloadcms/next/withPayload import type { NextConfig } from next const nextConfig: NextConfig {} export default withPayload(nextConfig)withPayload会为构建过程注入 Payload 所需的 webpack/turbopack 配置如 admin 相关资源的处理这一步与是否使用自定义服务器无关必须保留。2. REST API 路由— src/app/(payload)/api/[...slug]/route.ts 由 Payload 自动生成文件头明确标注 DO NOT MODIFY把六个 HTTP 动词分别映射到payloadcms/next/routes导出的处理器export const GET REST_GET(config) export const POST REST_POST(config) export const DELETE REST_DELETE(config) export const PATCH REST_PATCH(config) export const PUT REST_PUT(config) export const OPTIONS REST_OPTIONS(config)3. GraphQL— src/app/(payload)/api/graphql/route.ts/api/graphql/route.ts) 导出GRAPHQL_POST(config)另有graphql-playground路由提供调试界面。4. Admin 后台— src/app/(payload)/admin/[[...segments]]/page.tsx 使用RootPage与generatePageMetadata配合 importMap.js/admin/importMap.js) 渲染整个管理面板。5. 配置— src/payload.config.ts 使用mongooseAdapter连接 MongoDBURL 取自DATABASE_URLsecret 取自PAYLOAD_SECRETexport default buildConfig({ admin: { user: Users.slug, importMap: { baseDir: path.resolve(dirname) }, }, collections: [Users, Media], editor: lexicalEditor(), secret: process.env.PAYLOAD_SECRET || , typescript: { outputFile: path.resolve(dirname, payload-types.ts) }, db: mongooseAdapter({ url: process.env.DATABASE_URL || }), plugins: [], })关键点server.ts并不直接 import 任何 Payload 代码——Payload 的所有能力都通过 Next.js 路由承载最终由getRequestHandler()委托的handle响应。这正是该架构的简洁之处Express 层与 Payload 层完全解耦你可以自由增删 Express 侧的路由而不触碰 Payload 的任何生成文件。运行前置条件与启动步骤MongoDB 必须先启动且DATABASE_URL指向它。示例给出的取值形如mongodb://127.0.0.1/payload-example-custom-server见 README。准备环境变量DATABASE_URL、PAYLOAD_SECRET、可选的PORT默认 3000。依赖安装后执行pnpm generate:importmap # 生成 admin importMap pnpm generate:types # 生成 payload-types.ts pnpm dev # 开发模式nodemon tsx热重载生产环境pnpm build # payload build tsc --project tsconfig.server.json pnpm start # NODE_ENVproduction node dist/server.js适用前提与限制该示例面向 Payload 3 payloadcms/db-mongodbMongoDB 适配器若使用 PostgreSQL/SQLite仅替换payload.config.ts中的db适配器即可server.ts完全不受影响next版本在 package.json 中锁定为15.4.11express为^4.21.1Next.js 的 Custom Server 机制本身是 Pages/App Router 通用能力但具体 API 行为以所用 Next 版本为准生产模式依赖pnpm build的完整产物不能直接node dist/server.js跳过构建。从仓库快速创建同款项目官方脚手架支持直接用该示例初始化新项目来自 READMEnpx create-payload-app --example custom-server脚手架会基于 create-payload-app 的模板机制生成完整项目生成后按上文“运行前置条件”配置数据库与 secret 即可。小结Payload 3 的自定义服务器方案可以概括为三层解耦层职责关键文件Express 层端口监听、自有中间件/路由、进程模型server.ts委托层app.prepare()getRequestHandler()url.parse透传server.tsPayload 层REST/GraphQL/admin 以 App Router 路由存在由 Next 处理器承载app/(payload)/api/api/[...slug]/route.ts)、app/(payload)/admin/admin/[[...segments]]/page.tsx)这种结构下Express 负责“进程与中间件”Next 负责“路由与渲染”Payload 负责“数据与后台”三者各自独立演进。若你的诉求是 WebSocket 或自定义限流只需要在 Express 层增加代码Payload 侧零改动若诉求仅是自定义中间件也可以考虑在 packages/next 提供的标准 Next.js 集成上做扩展两者按需选择即可。【免费下载链接】payloadPayload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.项目地址: https://gitcode.com/GitHub_Trending/pa/payload创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表