ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Next.js 自定义服务器实战:TypeScript + Nodemon 开发自定义 Server 的完整指南

Next.js 自定义服务器实战:TypeScript + Nodemon 开发自定义 Server 的完整指南 Next.js 自定义服务器实战TypeScript Nodemon 开发自定义 Server 的完整指南【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js本篇基于 Next.js 官方示例 custom-server 展开讲解如何在 Next.js 项目中用 TypeScript 同时编写服务端与客户端代码并通过 Nodemon 实现服务器代码的热重载。读完本文你将掌握next()包装 API 的核心用法getRequestHandler、prepare、服务端独立的 tsconfig 编译策略以及开发态server.ts与生产态dist/server.js两种入口的切换机制能够把 Next.js 嵌入到任意自定义 Node.js 服务中。一、自定义服务器能解决什么问题Next.js 默认提供自己的 Node.js 服务进程next dev/next start。但在真实工程中经常需要接管 HTTP 服务层接入已有的网关或监听逻辑、在服务端做统一鉴权/日志/中间件、复用公司内部的服务框架。自定义服务器custom server就是让开发者自己创建 HTTP 服务再把请求委托给 Next.js 去渲染。官方示例examples/custom-server的定位见 README在服务器端和客户端同时使用 TypeScript并用 Nodemon 实现服务器代码的实时热重载同时不影响 Next.js 自身的 universal 代码热更新。两个关键结论先摆出来开发态入口是server.ts生产态入口是dist/server.js编译产物目录dist应加入.gitignore。二、用 create-next-app 脚手架启动示例仓库 README 给出了三种包管理器的引导命令任选其一npx create-next-app --example custom-server custom-server-appyarn create next-app --example custom-server custom-server-apppnpm create next-app --example custom-server custom-server-app执行后会在custom-server-app目录下生成完整示例项目结构如下对应仓库中的目录examples/custom-server/ ├── app/ # App Router 路由 │ ├── layout.tsx # 根布局 │ └── b/page.tsx # /b 页面 ├── pages/ # Pages Router 路由 │ ├── index.tsx # 首页含导航链接 │ └── a.tsx # /a 页面 ├── server.ts # 开发态服务器入口 ├── nodemon.json # Nodemon 配置 ├── tsconfig.json # 客户端 通用 TS 配置 ├── tsconfig.server.json # 服务端专属 TS 配置 └── package.json值得注意的是这个示例同时保留了app/与pages/两套路由目录。首页 pages/index.tsx 中用next/link同时链接到 Pages Router 的/a和 App Router 的/bimport Link from next/link; export default function Home() { return ( ul li Link href/a/a (Pages Router)/Link /li li Link href/bb (App Router)/Link /li /ul ); }这验证了自定义服务器对两种路由体系是透明且通用的——无论页面来自哪套路由最终都由同一个handle(req, res)处理。三、server.ts自定义服务器的核心代码逐行解析整个示例的服务端逻辑全部集中在 server.ts共 19 行import { createServer } from http; 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(() { createServer((req, res) { handle(req, res); }).listen(port); console.log( Server listening at http://localhost:${port} as ${ dev ? development : process.env.NODE_ENV }, ); });逐步拆解const dev process.env.NODE_ENV ! production以NODE_ENV判断当前是开发还是生产模式这是 Next.js 自定义服务器的惯例判据。const app next({ dev })调用next默认导出创建一个 Next.js 应用包装实例。这个实例是连接自定义 HTTP 服务与 Next.js 渲染引擎的桥。const handle app.getRequestHandler()拿到 Next.js 的请求处理函数。任何进入该函数的req/res都会按 Next.js 的路由规则被渲染页面、静态资源、API 等对开发者完全透明。app.prepare().then(() { ... })prepare是启动前置钩子用于完成 Next.js 内部的初始化加载配置、构建信息等。必须等prepare完成后再开始监听否则首个请求会因内部状态未就绪而出错。createServer((req, res) { handle(req, res); })用 Node 内置http模块创建服务器把每个请求原样转交给handle。端口从process.env.PORT读取缺省 3000便于部署平台注入端口。这段代码的最小骨架可以总结为三行next({ dev })→app.prepare()→handle(req, res)。从源码看 getRequestHandler 的官方地位在 Next.js 源码 packages/next/src/server/next.ts 中NextWrapperServer接口明确注释了“这里的成员是自定义服务器的公开 API改动时需要考虑向后兼容”interface NextWrapperServer { // NOTE: the methods/properties here are the public API for custom servers. // Consider backwards compatibilty when changing something here! options: NextServerOptions ... getRequestHandler(): RequestHandler prepare(serverFields?: ServerFields): Promisevoid close(): Promisevoid ... }同一文件中还定义了一个warnDeprecatedCustomServerMethod机制next.ts#L108-L114像render、renderToHTML、renderError、logError、revalidate等旧式方法在自定义服务器场景下已被标记废弃调用时会输出一次性警告统一引导开发者使用app.getRequestHandler() 自行调整 parsed URL的方式。也就是说示例中只暴露一个handle函数的写法正是官方推荐的现代姿势——不要依赖那些细粒度的 render 方法。四、TypeScript 双配置客户端与服务端各管一摊示例中最有工程价值的设计是两套 tsconfig 分工这解决了浏览器代码与 Node 服务器代码模块格式不同的矛盾。客户端配置 tsconfig.jsontsconfig.json 负责页面、组件等会被 Next.js 编译的代码{ compilerOptions: { target: es5, lib: [dom, dom.iterable, esnext], allowJs: true, skipLibCheck: true, strict: false, forceConsistentCasingInFileNames: true, noEmit: true, esModuleInterop: true, module: esnext, moduleResolution: node, resolveJsonModule: true, isolatedModules: true, jsx: react-jsx, incremental: true, plugins: [{ name: next }], strictNullChecks: true }, include: [next-env.d.ts, **/*.ts, **/*.tsx, .next/types/**/*.ts], exclude: [node_modules] }要点noEmit: true类型检查交给 Next.js 的构建流水线SWCtsc 只做类型校验不产出文件plugins: [{ name: next }]启用 Next.js 的 TS 语言服务插件提供路由类型检查等能力lib包含dom因为客户端代码需要浏览器 API 类型。服务端配置 tsconfig.server.jsontsconfig.server.json 只编译服务器入口{ extends: ./tsconfig.json, compilerOptions: { module: commonjs, outDir: dist, lib: [es2019], target: es2019, isolatedModules: false, noEmit: false }, include: [server.ts] }四个关键覆盖项module: commonjsNode.js 服务端直接node dist/server.js运行CommonJS 最稳妥无需处理 ESM 加载问题noEmit: falseoutDir: dist真正产出编译文件到disttarget/lib提升到es2019服务端运行在现代 Node 上不必像浏览器那样回落到es5include: [server.ts]严格限定只编译服务器文件避免把页面组件也打进dist。这种一个配置管类型、一个配置管编译的拆分正是 README 标题TypeScript Nodemon中服务端 TypeScript落地的方式。五、Nodemon让服务器代码支持热重载开发态下next dev本身会热更新 Next.js 的页面代码但自定义的server.ts属于纯 Node 代码不在其热更新范围内。示例用 Nodemon 补上这块nodemon.json{ watch: [server.ts], exec: ts-node --project tsconfig.server.json server.ts, ext: js ts }watch: [server.ts]只监听服务器入口文件避免页面文件变化触发不必要的重启exec检测到变化时重新执行ts-node --project tsconfig.server.json server.ts——用ts-node直接运行 TS 源码省去开发态编译一步并显式指定服务端 tsconfig 以保证commonjs模块格式正确ext: js ts将.js与.ts扩展名都纳入重载判断。由此形成开发态的双层热更新变更对象负责热更新的机制页面/组件pages/、app/Next.js 自身的开发时 HMR服务器入口server.tsNodemon 重启进程这正是 README 所说live reload the server codewithout affectingthe Next.js universal code的含义。六、package.json 中的三个脚本package.json 定义了完整的开发/构建/启动链路{ scripts: { dev: nodemon, build: next build tsc --project tsconfig.server.json, start: cross-env NODE_ENVproduction node dist/server.js } }dev启动 Nodemon读取上面的nodemon.json即运行ts-node加载server.ts。开发时执行npm run devbuild两步串行——先next build产出.next中的页面与资源再用tsc --project tsconfig.server.json把server.ts编译成dist/server.jsstart用cross-env跨平台设置NODE_ENVproduction后运行编译产物。cross-env作为依赖^7.0.3解决了 Windows 下无法直接用NODE_ENV...内联环境变量赋值的问题。依赖方面运行时依赖仅next、react、react-dom、cross-env四个nodemon、ts-node、typescript、types/*全部位于 devDependencies——这与开发态跑server.ts源码、生产态跑编译产物的设计完全吻合生产环境不再需要 TypeScript 工具链。七、生产部署注意事项结合 README 与示例代码部署自定义服务器版 Next.js 应用时有几条硬性约束入口切换生产环境运行的是node dist/server.jsstart脚本而不是server.ts。dev与start两条链路必须与build的产物严格对应dist目录忽略README 明确要求将dist加入.gitignore编译产物不入库NODE_ENV语义server.ts中dev process.env.NODE_ENV ! production因此任何非production的NODE_ENV如test都会进入开发模式分支启动日志也会显示对应的环境名。这一点在start脚本中通过cross-env NODE_ENVproduction保证了正确性prepare前置无论怎样扩展自定义逻辑鉴权中间件、额外路由都要保证它们注册在app.prepare().then(...)回调内确保 Next.js 初始化完成避免使用废弃的细粒度方法如前文源码所示app.render等方法已被废弃并输出警告新代码应始终只使用getRequestHandler()如需拦截/改写请求应在传给handle之前调整req或 parsed URL。八、小结这个示例的工程价值examples/custom-server虽只有十余行服务端代码但它把三件容易踩坑的事给出了官方参考答案API 面自定义服务器只需next({ dev })、prepare、getRequestHandler三个接触点源码next.ts中它被明确标注为面向自定义服务器的公开 API类型工程用tsconfig.jsonnoEmit管类型tsconfig.server.jsoncommonjs outDir管编译双配置隔离浏览器与 Node 的模块差异开发体验Nodemon ts-node 只监听server.ts让自定义服务代码获得与 Next.js 页面同等的热重载体验。当你需要把 Next.js 嵌入自研服务、加统一网关逻辑或复用现有 Node.js 基础设施时直接以 examples/custom-server 为模板起步即可create-next-app --example custom-server拉取骨架按上文三节改配置、按 README 约定管理dist产物。【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表