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

狠狠吐槽一下SSR/Next.js(二):服务端和客户端代码缠在一起,剪不断,理还乱。

上回我吐槽了Next.js和SSR的“花活”,很多人说我是“因爱生恨”。但今天,我要聊一个真正让我夜不能寐、每天写代码都想砸键盘的核心痛点——

代码混杂。

什么是代码混杂?就是在一个.tsx文件里,服务端的逻辑和客户端的逻辑像两团被猫玩过的毛线,缠在一起,剪不断,理还乱。

Next.js 美其名曰“全栈框架”、“前后端融合”,在我看来,这根本就是一场心智负担的灾难

一、同一个文件,两个世界

让我们来看一个“经典”的Next.js页面:

tsx

// pages/profile/[id].tsx // 这行代码是在哪里执行??? export async function getServerSideProps(context) { const userId = context.params.id; // 这是服务器端的秘密!里面有数据库密码! const dbSecret = process.env.DATABASE_PASSWORD; // 去数据库捞数据... const userData = await db.query('SELECT * FROM users WHERE id = ?', [userId]); return { props: { user: userData } }; } // 这个组件又是在哪里执行??? export default function UserProfile({ user }) { // 这看起来是客户端代码... const [isFollowed, setIsFollowed] = useState(false); // 但是!这个 useEffect 在服务端也跑了一次! useEffect(() => { // 只能客户端做的事 console.log('窗口宽度:', window.innerWidth); // 服务端直接报错! }, []); const handleFollow = async () => { // 这又是在哪里?客户端,因为有点击事件 const res = await fetch('/api/follow', { method: 'POST' }); // ... }; return ( <div> <h1>{user.name}</h1> <button onClick={handleFollow}> {isFollowed ? '已关注' : '关注'} </button> </div> ); }

看到没有?一个文件里,服务器端的逻辑(getServerSideProps)、客户端的逻辑(useState, useEffect, onClick)、以及一些暧昧不清、两头都跑的代码(组件的render),全挤在一块。

我每次打开这种文件,脑子里都要启动一次“双核处理器”:

  • 左脑:这段代码在Node.js环境跑,有process.env,有数据库连接。
  • 右脑:这段代码在浏览器环境跑,有window,有document

问题是,我的脑子不是双核的啊!

二、“水合”灾难:两边都得伺候的祖宗

Next.js 最引以为傲的“水合”(Hydration),恰恰是代码混杂最恶心的体现。

你的组件代码,先在服务器上跑一遍,生成HTML字符串。然后,到了浏览器,再跑一遍,给这个HTML“注入生命”。

这就导致了一个致命问题:

你写的每一行组件代码,都必须同时服务端和客户端“两开花”。

你一不小心在组件顶层用了一个localStorage.getItem('token'),好了,服务端直接报错——“localStorage is not defined”。

你小心翼翼地加了个typeof window !== 'undefined'的判断,代码变得丑陋不堪。

更恶心的是,就算你处理好了报错,水合不匹配(Hydration Mismatch)又会找上门。服务器渲染的HTML和客户端第一次渲染的Virtual DOM对不上,React就给你报警告,甚至直接重渲染,把你“SSR优化”带来的那点性能优势,全部葬送。

我写的是React,不是兼容性测试工具!

三、“我到底该把逻辑放哪?”——一个哲学问题

在Next.js里,你无时无刻不在面临这种灵魂拷问:

  • 这个数据获取逻辑,放在getServerSideProps里?还是放在useEffect里用fetch?还是放在getStaticProps里构建时拿?还是用SWR在客户端“重新验证”?
  • 这个环境变量,是NEXT_PUBLIC_开头的吗?不是的话,它只存在于服务端,客户端用不了。是的话,它又会被打包进客户端的JS里,万一里面有敏感信息呢?
  • 这个工具函数,它用了fs模块读文件,又用了fetch请求API。它到底是一个“服务端工具”还是“客户端工具”?要不要加个'use client'指令?

我每天不是在写业务逻辑,我是在给代码做“环境归属鉴定”。

这种心智负担,不是来自于技术的复杂性,而是来自于框架设计本身对“关注点分离”原则的背叛。

四、所谓的“全栈”,不过是“全混”

有人说:“你可以在/pages/api里写后端逻辑,在/pages里写页面逻辑,这不就分开了吗?”

这更是个笑话。

  • pages/api里的代码,本质上就是一个个Serverless函数。但你依然要在同一个项目里,跟你的UI代码共享node_modules,共享tsconfig.json
  • 你的前端代码可以轻易地import一个原本只想在getServerSideProps里用的工具函数,然后发现它在客户端打包时引用了crypto核心模块,直接导致你的页面体积暴涨。

Next.js 的“全栈”,不是前后端分离,而是前后端“大乱炖”。它用一个模糊的边界,吞噬了开发者对代码执行环境的清晰认知。

五、我只是个前端,我不想当“全栈背锅侠”

我真的只是想写一个漂亮的UI,处理一些用户的点击交互。

但现在,我被迫要关心:

  • Node.js 的内存限制
  • 数据库连接池的配置
  • Serverless 函数的冷启动时间
  • API 路由的 CORS 问题
  • 服务端渲染的缓存策略

我只是个前端啊!我当初入这行,是因为我喜欢视觉反馈、喜欢交互、喜欢用代码创造界面。我不是来给运维和后端擦屁股的。

当我把一个useState写错了,导致整个页面的SSR崩溃,返回一个500错误页面时,我真的想仰天长啸:

“我特么只是想加个按钮的状态啊!!!”

结语:把“关注点分离”还给我

所以,亲爱的Next.js,求求你了。

别再跟我吹什么“全栈”、“统一”、“融合”了。

我怀念的,是那个前端代码只跑在浏览器的时代。
我怀念的,是那个后端接口明明白白写在另一个项目里的时代。
我怀念的,是那个src/下面是客户端,server/下面是服务端,井水不犯河水的时代。

清晰的边界,让团队可以分工协作,让新人可以快速上手,让我的脑子可以不用时刻切换上下文。

你问我为什么还在用?

因为老板看了营销文,说“大家都在用”,因为技术选型不是我能决定的。

但至少,请让我在代码里,保留最后一声呐喊:

别再让我在一个文件里,同时写服务器和客户端的代码了!我的大脑,它真的会过载!

http://www.jsqmd.com/news/1147016/

相关文章:

  • HarmonyOS 7小艺Agent有多强?一句话帮你搞定10件事
  • 户外视觉语言导航的语义韧性设计:应对山野语义中断的四层架构
  • 一体成型电感广东专业供应商排名
  • 物流企业物流调度和单据处理优化用哪款Agent?主流方案深度测评与工程化选型指南
  • 采用 mem0 之前,先决定 Agent 到底允许记住什么
  • 短时过零率与自相关函数:2种方法在语音端点检测(VAD)中的实战对比与性能分析
  • 2026 最新 AI 学习路线全景图:从零基础到 AI 全栈测试与开发实战(附一站式智能测试平台)
  • MediaPipe TouchDesigner插件实战:3种虚拟摄像头集成方案全解析
  • 华硕 ProArt KD300 键盘评测:优缺点并存,适合多设备连接用户
  • OpenClaw部署实战:AI技能编排中枢的零基础落地指南
  • WebLogic Server 12.2.1.4 漏洞防御:5项临时缓解措施与补丁部署验证
  • 视频分析网络穿透性能优化指南
  • 【JAVA毕设源码分享】基于SpringBoot+vue的高校学生实习综合服务平台设计与实现(程序+文档+代码讲解+一条龙定制)
  • ES4X:让 JavaScript 在 Vert.x 上跑得更快
  • 跨国收购后需要全球实体合规整合,有哪些机构推荐?
  • STM32L031C6与L9958电机驱动方案设计与优化
  • 英雄联盟智能助手Seraphine:如何通过实时数据分析和自动化BP提升你的游戏胜率
  • I Doc View <13.10.1_20231115 5个高危漏洞原理与修复方案深度解析
  • 终极DLSS版本管理指南:免费工具一键提升显卡性能
  • MAX77654与PIC32MX电源管理方案设计指南
  • STM32L011K4与CMT-8540S-SMT蜂鸣器的低成本声音交互方案
  • 2026年AI大模型API中转站性能实测与综合性价比排名
  • 后勤人手不足怎么管好变电所?安科瑞校园电力监控一站式方案
  • 案例分享—地下水位监测仪多通道同时显示液位南京地下空间项目,地下水位自动监测设备电池供电低功耗投入式远程水位监测仪#水利 #水位监测仪 #投入式 #供电 #低功耗
  • DLSS Swapper:一键智能切换游戏DLSS版本,彻底释放显卡性能潜力
  • 2026年,市面上专业Geo系统优化及源码公司选哪家?
  • SSR框架:单阶段视觉驱动的人形机器人越障新范式
  • 高精度ADC与MCU信号采集系统设计指南
  • AMD Ryzen系统管理单元调试工具:硬件级性能优化的技术实现与实战应用
  • 8月1日起实施!民政部规定社会团体不得下设二级分支,违规将担责