昨晚跟 Nuxt 4 和 PHP 死磕到凌晨:全栈开发避坑实录

昨晚两点半,我死死盯着屏幕上 Nuxt 4 抛出的那个 Hydration Mismatch 报错,手里的冰美式差点直接浇在机械键盘上。
事情的起因很简单:我想用 Nuxt 4 做个 SSR 前端,去拉取后端老项目 PHP 接口的数据。听起来多简单一事儿,结果硬是让我从晚上十点折腾到半夜。其实咱们写代码的都知道,很多时候业务逻辑没多复杂,反而是环境配置、前后端对接这些边角料的坑,能把人折磨疯。
今天这篇不整那些虚头巴脑的理论,就把昨晚我踩过的三个大坑扒出来。算是个复盘,也希望能救各位全栈同仁一命。
一、跨域这老生常谈的破事,咋又在 SSR 上发作了?
本地刚起项目,用 fetch 去请求 PHP 接口,浏览器控制台立马给我甩脸:CORS 报错。
这题我熟啊!马上跑去 PHP 接口文件顶部加上 header("Access-Control-Allow-Origin: ")。刷新,还是报错。当时我脑子里嗡的一声。
后来查了半天才发现,Nuxt 4 在 SSR 模式下,服务端渲染时的请求根本不走浏览器,自然也不带那些跨域头。而且开发环境下,前端跑在 localhost:3000,PHP 跑在 localhost:80,端口不同就是跨域。
怎么爬出来的:
别在 PHP 代码里乱加
了,生产环境这不安全。在 nuxt.config.ts 里配个路由规则(Route Rules),让 Nuxt 自带的代理把 API 请求转发过去。

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // 把 /api 的请求都转发到你的 PHP 后端去
    '/api/**': { proxy: 'http://localhost:80' }
  }
})

这样在代码里直接 fetch('/api/xxx'),不仅本地开发丝滑,部署到生产环境也能避免跨域和暴露后端真实地址的风险。
二、服务端和客户端数据打架:Hydration Mismatch
跨域搞定,数据也拿到了,结果页面一渲染,控制台飘红:Hydration Mismatch。
这玩意的意思大概是:Nuxt 在服务端(Node.js 环境)先把你页面画出来,等到了浏览器,Vue 接手再画一遍,发现两边画出来的东西不一样!这在技术写作里属于必须要交代清楚的“环境背景”和“陷阱提示”。
我排查了半天,发现问题出在 PHP 返回的时间戳上。我在模板里直接对时间戳调用了 new Date().toLocaleString()。要知道,服务端渲染时的时间,和客户端浏览器拿到数据渲染时的时间,哪怕只差几百毫秒,转换出来的字符串也不一样,这就导致两边比对不上。
怎么爬出来的:
把依赖客户端环境的逻辑,推迟到组件挂载后再执行。技术博客写作的核心要点之一就是“提供具体的示例”,来看代码:

l<script setup>
const article = ref({})
const formattedDate = ref('')

// 这里的请求在服务端和客户端都会跑,数据是一致的
const { data } = await useFetch('/api/article/1')
article.value = data.value

// 用 onMounted,这段逻辑只在浏览器端执行,完美避开水合报错
onMounted(() => {
  formattedDate.value = new Date(article.value.timestamp).toLocaleString()
})
</script>

三、写技术文章别当“复读机”
折腾完这两个坑,天都快亮了。我一边吃早点一边想,为什么之前看官方文档和别人的教程,碰到这些坑还是得自己摸索?
因为很多技术文章就像冷冰冰的“纯文档”,缺少博主真实的踩坑过程和经验总结。互联网上最不缺的就是文档翻译,如果只是把官方文档抄一遍,那这篇文章的价值就失去了。
写博客也好,写软文也罢,一定要有“人情味”。用语直接一点,不要通篇都是“赋能”、“必要性”这种大词儿。比如我写跨域,我不写“配置代理以实现异构系统间的通信赋能”,我就写“别在 PHP 里加星号了,前端配个代理搞定”。这样读者看着才像是在跟人聊天,而不是对着四面白墙听机器念经。
写文章结构要完整,要有“结果测试和排错过程”。我如果只贴一段代理的配置代码,不告诉你为什么这么配,不告诉你我昨晚踩了什么坑,那你遇到别的报错还是抓瞎。
这就是写博客的初衷:巩固自己的学习,记录成长历程,同时用真实、接地气的经验帮别人少走弯路。添加个人的接触点和情感色彩,哪怕是昨晚差点泼键盘的吐槽,也能让枯燥的技术文章产生共鸣,这种真实性是赢得读者信任的最强指标。
行了,今天的坑就先填到这。代码推上去了,我也得补个觉。如果你在搞 SSR 的时候也遇到什么鬼畜问题,评论区见。

评论区

评论列表(1条)

夕梦
夕梦 江苏省 无锡市 macOS Sonoma Microsoft Edge 148
啊但是的
回复 15 天前