当前位置: 首页 > article >正文

Node.js 中间层我维护了两年,这周终于摊牌了——成本账单算完我人傻了

背景先交代一下我在一个 20 人的创业团队做全栈两年前入职第一件事就是搭 Node.js 中间层。当时的理由很充分scss前端React SPA中间层Node.js (Express) ← 我搭的后端Java 微服务 × 6老板说前端不能直接调 Java原因有三接口格式不统一——有的返回 {code, data}有的返回 {status, result}跨域问题——6 个微服务 6 个域名前端需要做接口聚合——一个页面要调 3-4 个接口拼数据听起来确实需要一个 BFF 对吧我当时也这么想的。两年后的真实状态来看看我的 BFF 层现在长什么样bashsrc/├── routes/ # 87 个路由文件├── controllers/ # 87 个 controller一一对应├── services/ # 92 个 service├── middleware/ # 15 个中间件├── utils/ # 各种 helper└── config/ # 3 套环境配置87 个路由。你没看错。其中有多少是有意义的聚合逻辑我数了一下12 个。剩下的 75 个在干嘛javascript// 真实代码脱敏过占 BFF 总代码量的 85%router.get(/api/users/:id, async (req, res) {try {const result await javaService.get(/user-service/users/${req.params.id});res.json({ code: 0, data: result.data });} catch (err) {res.json({ code: -1, message: err.message });}});透传。纯透传。85% 的代码就是把前端的请求原封不动转发给 Java再把 Java 的响应原封不动还给前端。连参数校验都没做Java 那边做了。我维护了两年的中间层本质上是个超大号的 nginx proxy_pass。算一笔账这才是让我下定决心的原因。服务器成本BFF 层跑了 3 台 2C4G 的云服务器高可用嘛每台 ¥280/月iniBFF 服务器: ¥280 × 3 ¥840/月PM2 进程管理: 包含在内Nginx SSL: 包含在内监控告警Datadog: ¥200/月──────────────────────合计: ≈¥1,040/月人力成本这个才是大头markdown我每周花在 BFF 上的时间: ≈10 小时- 后端新增接口 → 我同步加 BFF 路由: 4h- Bug 修复 维护: 3h- 升级依赖 / 安全补丁: 2h- 写测试虽然覆盖率一直上不去: 1h按我的时薪折算: ≈¥1,500/周 ¥6,000/月一个月 ¥7,000维护一个高级转发器。而且这还不算隐性成本——每次后端改了接口我得同步改 BFF。经常出现「后端改了字段名忘了告诉我前端页面挂了半天才发现」的情况。这周动手了热榜那篇文章让我下定了决心。我列了个清单1. 75 个纯透传路由 → Nginx 反向代理直接搞定nginx# 原来 87 个 Node.js 路由文件 → 现在 15 行 nginx 配置location /api/user-service/ {proxy_pass http://java-user-service:8080/;proxy_set_header X-Real-IP $remote_addr;}location /api/order-service/ {proxy_pass http://java-order-service:8081/;proxy_set_header X-Real-IP $remote_addr;}# ...6 个微服务全部直连是的就这么简单。CORSNginx 加几行 header。认证Java 那边本来就有鉴权中间件。砍掉 BFF 的第一刀省了 85% 的代码量。2. 12 个聚合接口 → 前端用 Promise.all 自己聚合typescript// 以前BFF 聚合三个接口// GET /api/dashboard → 内部调 user order statistics// 现在前端直接并发请求const [user, orders, stats] await Promise.all([fetch(/api/user-service/me),fetch(/api/order-service/recent),fetch(/api/stat-service/dashboard),]);有人会说这不就是把复杂度推给前端了吗对但前端框架现在处理这个太轻松了。React Query / SWR 几行代码还自带缓存和错误重试。比我手写的 BFF 聚合逻辑健壮得多。3. 接口格式不统一写个前端拦截器typescript// axios 拦截器统一格式10 行代码解决api.interceptors.response.use((response) {const data response.data;// Java 服务 A: {code, data}// Java 服务 B: {status, result}return {success: (data.code 0 || data.status ok),data: data.data || data.result,message: data.message || data.error,};});以前用 BFF 做的格式统一一个拦截器就搞定了。重构结果花了两天时间结果makefile代码变化:删除: 87 个路由文件 92 个 service 所有 BFF 代码新增: 15 行 Nginx 配置 1 个前端拦截器 3 个 Promise.all 聚合服务器变化:关掉: 3 台 BFF 云服务器省钱: ¥1,040/月人力变化:我每周在 BFF 上的时间: 10h → 0h后端改接口不用通知我了: priceless 部署流程:之前: 前端 BFF 后端 3 个部署流水线现在: 前端 后端 2 个部署流水线但是不是所有中间层都该删说几个真正需要 Node.js 中间层的场景1. SSR / SSG— Next.js、Nuxt 这类框架本身就是 Node.js 中间层这个有真实价值2. 复杂的 BFF 编排— 如果你的聚合逻辑涉及条件分支、错误回退、事务补偿前端处理确实吃力3. AI API 代理— 这个是我新发现的场景说来有点讽刺我删掉 BFF 之后一个月团队开始往产品里加 AI 功能。结果发现又需要一个中间层了javascript// 又特么需要代理了 // 前端不能直接调 AI API密钥暴露 CORSrouter.post(/api/ai/chat, async (req, res) {const result await openai.chat.completions.create({model: gpt-4o,messages: req.body.messages,});res.json(result);});不过这次我学聪明了——没有自己搭 Node 服务而是用了 API 聚合平台做代理。类似 ofox.ai 这种统一一个 endpoint 调不同的模型前端只需要配一个 base_url 就行连 Node 中间层都省了。typescript// 前端直接调API Key 通过后端环境变量注入到 SSR 页面const client new OpenAI({apiKey: process.env.NEXT_PUBLIC_AI_KEY,baseURL: https://api.ofox.ai/v1,dangerouslyAllowBrowser: true, // 仅限内部工具});当然如果是面向用户的产品密钥肯定还是得走后端。但对内部工具来说这种方案省了一整个服务。给还在纠结的人几个建议先审计你的中间层代码——数一下有多少路由是纯透传的。如果超过 60%认真考虑砍掉。别因为万一以后需要而保留——YAGNI 原则。我在 BFF 层留了两年的预留扩展点一个都没用上。分步来——不用一口气全砍。我是先灰度切了 10 个低风险接口观察一周没问题再切剩下的。计算真实成本——不只是服务器费用。你的时间才是最贵的。每周花在同步 BFF 路由上的时间完全可以用来做更有价值的事。考虑团队现状——如果你的后端接口真的很乱、没有统一规范BFF 层可能还是必要的过渡方案。但目标应该是推动后端统一而不是用 BFF 永远兜底。最后Node.js 中间层不是原罪。无脑加中间层才是。两年前我搭 BFF 的时候确实解决了实际问题但随着项目发展它的维护成本已经远超收益。热榜说的从前端救星到成本噩梦我的体会是它确实当过救星但别让它变成你的舒适区。该摊牌的时候就摊牌吧 ✌️全栈开发一枚最近在折腾去中间层化。下一篇可能会写 Nginx 反向代理的完整配置方案感兴趣的朋友关注一波 原文链接https://juejin.cn/post/7611861210603257862

相关文章:

Node.js 中间层我维护了两年,这周终于摊牌了——成本账单算完我人傻了

背景先交代一下,我在一个 20 人的创业团队做全栈,两年前入职第一件事就是搭 Node.js 中间层。当时的理由很充分:scss前端:React SPA中间层:Node.js (Express) ← 我搭的后端:Java 微服务 6老板说前端不能直…...

SDC设计约束进阶:工作条件与功耗约束的实战解析

1. 工作条件约束的实战应用 在芯片设计中,工作条件约束就像是给运动员设定比赛环境。想象一下,同一个运动员在高原和平原的跑步表现会完全不同。set_operating_conditions命令就是用来定义芯片工作的"气候环境",它会直接影响时序分…...

超越官方文档:用Jetson Nano和CSI摄像头打造你的第一个AI视觉项目

超越官方文档:用Jetson Nano和CSI摄像头打造你的第一个AI视觉项目 当你第一次点亮Jetson Nano上的CSI摄像头时,那种兴奋感可能很快会被一个现实问题取代:"接下来我能用它做什么?"本文将带你跨越基础测试阶段&#xff0c…...

NLopt实战指南:从算法原理到工程应用

1. NLopt入门:非线性优化的瑞士军刀 第一次接触NLopt是在三年前的一个机器人路径规划项目里,当时需要解决一个带约束的多目标优化问题。试过几个开源库后,NLopt以其简洁的API设计和丰富的算法支持让我眼前一亮。这个由MIT开发的非线性优化库&…...

Phi-3 Mini 128K效果展示:长小说理解与代码库分析真实案例

Phi-3 Mini 128K效果展示:长小说理解与代码库分析真实案例 1. 引言:当轻量级模型遇上超长文本 在AI模型领域,参数规模往往与性能成正比,但微软的Phi-3 Mini 128K打破了这一常规。这款仅有3.8B参数的轻量级模型,凭借1…...

告别Designer!在VS2019里用Qt Creator高效编辑.ui文件的正确姿势

告别Designer!在VS2019里用Qt Creator高效编辑.ui文件的正确姿势 每次在Visual Studio 2019中双击.ui文件时,那个熟悉的Qt Designer界面弹出,随之而来的可能是卡顿、崩溃,或是编译后界面显示异常的问题。作为一个长期使用Qt进行跨…...

nginx proxy_redirect指令实战:精准修复代理重定向后的404与域名复用跳转难题

1. 为什么你的Nginx代理总跳404?从Location头说起 最近在帮朋友排查一个诡异的Nginx问题:他的电商网站通过Nginx反向代理多个微服务,用户登录时总随机出现404页面。我打开Chrome开发者工具,发现点击登录按钮后出现302跳转&#xf…...

Navicat16/17 Mac版试用期终极重置指南:3种方法实现无限免费使用

Navicat16/17 Mac版试用期终极重置指南:3种方法实现无限免费使用 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac …...

为什么M9A智能助手能成为《重返未来:1999》玩家的首选自动化方案

为什么M9A智能助手能成为《重返未来:1999》玩家的首选自动化方案 【免费下载链接】M9A 重返未来:1999 小助手 | Assistant For Reverse: 1999 项目地址: https://gitcode.com/gh_mirrors/m9/M9A 还在为《重返未来:1999》中每日重复的资…...

极域电子教室破解终极指南:如何重获课堂电脑控制权

极域电子教室破解终极指南:如何重获课堂电脑控制权 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 你是否曾在课堂上遇到过这样的困境?老师开启极域电子教…...

如何用lunar-javascript快速搞定农历计算?3个实用技巧让你轻松应对传统历法需求

如何用lunar-javascript快速搞定农历计算?3个实用技巧让你轻松应对传统历法需求 【免费下载链接】lunar-javascript 日历、公历(阳历)、农历(阴历、老黄历)、佛历、道历,支持节假日、星座、儒略日、干支、生肖、节气、节日、彭祖百忌、每日宜忌、吉神宜趋…...

Wear OS手表开发避坑:地图应用如何禁用全局滑动返回(附完整style.xml配置)

Wear OS手表开发实战:地图应用中禁用全局滑动返回的深度解决方案 在智能手表的小尺寸屏幕上开发地图导航应用时,最令人头疼的莫过于用户误触侧滑返回手势。想象一下这样的场景:用户正在骑行导航中,手腕自然摆动时不小心触发了返回…...

如何用BilibiliDown轻松提取B站音频:3分钟搞定高质量音乐下载 [特殊字符]

如何用BilibiliDown轻松提取B站音频:3分钟搞定高质量音乐下载 🎵 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://git…...

AI建站工具避坑指南:企业用户最关心的十大核心问题解答

AI建站工具避坑指南:企业用户最关心的十大核心问题解答企业在考虑采用AI建站工具时,决策链条上的每个角色都有自己的顾虑:市场部担心内容质量,IT部门忧虑安全隐患,采购部纠结成本是否透明。这份指南汇总了十个最高频的…...

MathType 7安装激活全攻略:从下载到Word插件配置(附常见问题解决)

MathType 7终极配置指南:从零开始打造高效公式编辑环境 在学术写作和科研工作中,数学公式的编辑效率直接影响着文档产出的质量与速度。作为专业数学公式编辑器的标杆,MathType 7凭借其强大的兼容性和直观的操作界面,已成为教育工作…...

【DDRNet实战】单GPU环境下,从零构建细胞图像分割数据集与训练测试全流程

1. 环境准备与数据收集 在开始细胞图像分割项目前,我们需要先搭建好基础环境。我的实验设备是一台搭载NVIDIA GeForce RTX 3060笔记本显卡的Windows 11电脑,配置了CUDA 11.7驱动。这个配置对于小规模细胞图像分割任务已经足够,但需要注意显存…...

SAP ABAP开发实战:5分钟搞定调用外部REST API(含Basic Auth认证完整代码)

SAP ABAP实战:5分钟集成外部REST API的终极指南 当业务部门突然要求将钉钉审批流接入SAP系统时,作为ABAP开发者的你是否感到手足无措?别担心,这份实战指南将带你快速突破技术壁垒。不同于教科书式的理论讲解,我们将直击…...

如何在Windows 7上运行最新版Blender:终极兼容性解决方案

如何在Windows 7上运行最新版Blender:终极兼容性解决方案 【免费下载链接】BlenderCompat Windows 7 support for Blender 3.x and newer 项目地址: https://gitcode.com/gh_mirrors/bl/BlenderCompat 还在使用Windows 7系统却想体验Blender 3.x的强大3D创作…...

ESP-SR语音识别框架实战:嵌入式设备智能语音交互解决方案

ESP-SR语音识别框架实战:嵌入式设备智能语音交互解决方案 【免费下载链接】esp-sr Speech recognition 项目地址: https://gitcode.com/gh_mirrors/es/esp-sr ESP-SR是乐鑫推出的高效语音识别开发框架,专为ESP32系列芯片设计,提供完整…...

别再死记硬背公式了!用Python+NumPy手把手带你理解B样条曲线的局部支撑性

用PythonNumPy实战B样条曲线:可视化理解局部支撑性 在汽车设计或游戏建模中,设计师经常需要对曲线进行微调——比如只改动车灯轮廓而不影响车门线条。这种"牵一发而不动全身"的特性,正是B样条曲线被称为"工业建模基石"的…...

MediaPipe Holistic实战:用这个镜像快速搭建你的第一个动作分析应用

MediaPipe Holistic实战:用这个镜像快速搭建你的第一个动作分析应用 1. 引言:为什么选择MediaPipe Holistic? 想象一下,你正在开发一个健身应用,需要同时追踪用户的肢体动作、面部表情和手势。传统方案可能需要分别调…...

Windows Cleaner终极指南:彻底解决C盘爆红的开源清理工具

Windows Cleaner终极指南:彻底解决C盘爆红的开源清理工具 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服! 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 你是否经常遇到C盘爆红的困扰?系…...

基于STC89C52的智能避障循迹小车优化与扩展功能实现

1. STC89C52智能小车基础功能实现 刚接触单片机开发时,用STC89C52做智能小车是最经典的练手项目。这个51内核的单片机虽然性能比不上现在的STM32,但胜在价格便宜、资料丰富,特别适合初学者。我当年做的第一辆小车就是基于这个方案&#xff0c…...

为什么你的ChatBI总答非所问?深度拆解知识库向量化失效的3类隐性数据腐化场景

第一章:生成式AI应用知识库集成 2026奇点智能技术大会(https://ml-summit.org) 生成式AI与企业知识库的深度集成,正从“文档检索增强”迈向“语义化决策中枢”的演进阶段。该集成并非简单叠加向量数据库与大语言模型,而是构建具备上下文感知…...

SAP与Concur通信中断?别慌!手把手教你用STRUST搞定SSL证书过期(附Concur证书下载)

SAP与Concur通信中断?手把手教你用STRUST解决SSL证书信任问题 当SAP系统与Concur之间的通信突然中断,屏幕上跳出"SSL Peer Certificate Untrusted"的红色报错时,很多运维人员的第一反应往往是头皮发麻。这种跨系统间的SSL证书信任问…...

若依WMS仓库管理系统:10分钟掌握现代化仓储管理的终极解决方案

若依WMS仓库管理系统:10分钟掌握现代化仓储管理的终极解决方案 【免费下载链接】RuoYi-WMS-VUE 若依wms是一套基于若依的wms仓库管理系统,支持lodop和网页打印入库单、出库单。包括仓库/库区/货架管理,出入库管理,客户/供应商/承运…...

Windows APK安装终极指南:告别模拟器,轻松安装安卓应用

Windows APK安装终极指南:告别模拟器,轻松安装安卓应用 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 想在Windows电脑上直接安装安卓应用吗&a…...

从碳排放到城市健康:土地利用强度如何成为评估可持续发展的新标尺?

从碳排放到城市健康:土地利用强度如何成为评估可持续发展的新标尺? 当我们在讨论城市可持续发展时,碳排放往往是最受关注的指标。但一个更本质的问题却被忽视了:我们脚下的土地,究竟在以怎样的方式支撑或制约着城市的未…...

多频带融合实战:从Alpha融合的鬼影到拉普拉斯金字塔的平滑过渡

1. 图像融合的痛点:Alpha融合为什么会产生鬼影? 第一次尝试用Alpha融合拼接全景图时,我盯着结果里的半透明重影愣了半天——这就是传说中的"鬼影"现象。简单来说,当两张图片的重叠区域采用线性渐变融合时,由…...

离散数学核心概念精讲:从集合论到图论的面试通关指南

1. 离散数学:计算机科学的基石 离散数学是计算机科学最重要的数学基础之一,它研究的是离散对象及其关系,而不是连续变化的量。我第一次接触离散数学是在大二的数据结构课上,当时教授说"不懂离散数学就写不出好算法"&…...