[转载]我,一个后端工程师,在前端世界被毒打了两天两夜
文章出处:Asimov Ai
本文链接:github.com/aizhimou/my-blog
一个关于 React, Next.js, Astro 和一个心碎后端仔的真实故事。
0. 故事的开始,一切都那么美好,甚至有点不真实
“嗨,不就是个网站嘛,分分钟搞定!”
我,一个在后端混了七八年的 Java 程序员。
我的世界,纯粹又朴素,信奉的是稳定压倒一切。每天打交道的都是 Spring Boot、MySQL、Redis、Docker、k8s、Linux 这些“实在亲戚”。我们之间的沟通方式简单直接:一个请求,一个响应;一个事务,要么成功,要么回滚。干净利落,没有那么多花里胡哨。
前端那些 JS 和 CSS 的玄学问题,在我看来就是一团乱麻。
直到我搞了个人的小项目,一个叫 PigeonPod 的 WebApp。
后端,那必须是我的舒适区,稳如老狗。
但前端,总得有个脸面。
该怎么选技术?我的思路很简单,典型的后端稳重思维:
- JS 框架要选生态最强的。 就像 Java 选 Spring Boot 一样,不出错,不一定是最好的,但是干啥都能用,出什么问题都能找到答案。React,全世界都在用,社区庞大得像个帝国,遇到问题随便一搜都有答案,简直就是 JS 届的 Spring Boot。用户足够多,文档足够全,简直就是 AI 的最爱。就它了。
- UI 库要选口碑好、够稳定的。 我可不想用个半成品,三天两头出 breaking change。在几个技术社区上研究了一圈,发现 Mantine UI 评价相当不错,样式简洁大气,组件够多,迭代了很久,该踩的坑前人都踩完了。完美。
接下来就是干。
当然,学习 React 和 Mantine 的过程也啃了不少文档,花了不少时间。但这笔“学费”我交得心甘情愿。我就想着,把这套东西搞熟了,以后写前端不就能像用 Spring Boot 一样,一招鲜吃遍天了嘛。
事实证明,前期的投入是值得的,PigeonPod 应用本身开发得还算顺利。
于是,我乘胜追击,准备给我的 PigeonPod 做个时髦的 Landing Page 充充门面。
这不更是小 case?
我直接把 PigeonPod 的前端代码复制一份,把 App 里的组件稍微改改,CV 大法一开,很快啊!一个看起来相当唬人的官网就上线了。
我看着屏幕上自己的杰作,心满意足地往椅背上一靠,长舒一口气。
“咱也是个全栈了!”
当时的我,天真得像个两百斤的孩子。
1. Lighthouse 给了我 85 分,Google 却给了我一记耳光
“我的网站,加载起来像是在进行一场庄严的宗教仪式。”
官网是上线了,但问题也来了。
每次打开我的 Landing Page,总感觉……慢一拍?
那种感觉,作为一个后端,我再熟悉不过了:就像是执行了一条没加索引的 SELECT *,数据量不大,速度也不慢,但是就是没那种爽感。
我不能忍 🫤
熟练地按下 F12,打开 Network 面板,看着那长长的网络请求瀑布,我陷入了沉思。
一顿操作猛如虎:字体加载优化、图片懒加载、分级加载图片……这些都是前端优化里的小门道。效果立竿见影,性能直接提升了 40%。
与此同时,我可不是对 SEO 一无所知的“小白”。我从一开始就知道,单纯的 React SPA 对搜索引擎就是个灾难。
所以,我早就“未雨绸缪”,给我的 Landing Page 上了一套 pre-render 脚本。这玩意儿会在项目构建的时候,提前跑一遍我的页面,把渲染好的 HTML 抓下来,直接塞进 index.html 里。这样,爬虫一来,至少能看到点实实在在的内容,不至于对着一个空的 <div> 发呆。
看着 performance 92; Best Practices 100; SEO 85 的 lighthouse 评分,我长舒一口气,感觉自己又行了。
AI 在手,前端我有 🐮
然后,真正的“耳光”在一个月后扇了过来。
我心血来潮,想看看我的项目有没有被 Google 收录。我在搜索框里郑重地敲下 “PigeonPod”,回车。
结果……比我的钱包还干净 🤷
GitHub 项目页排在第一我倒是能理解,GitHub 这种大站的权重岂是我能比得过的,但是我在 Reddit 上发的帖子都有,甚至还有一个朋友自己部署在群晖上的 PigeonPod 应用都排在第三,就是我自己的 Landing Page 没有,Google 压根不知道我的站点一样。
我不服 🫤
Lighthouse 的 SEO 85 分呢?我那套 pre-render 的“骚操作”呢?难道都是幻觉?
我这才被迫重新、并且是真正深入地去理解前端渲染那点事。我才发现,我那种 pre-render 的小伎俩,顶多算是给爬虫准备了一份“内容简介”。它也许能骗过 Lighthouse 的模拟测试,但在 Google 真正的大规模、复杂的索引算法面前,我这种“作弊”行为,跟裸奔没什么两样。
人家真正看重的是根正苗红的 SSR (服务端渲染) 和 SSG (静态站点生成)。
这两种模式,打个比方就是:请求来了,我在服务器上把逻辑跑完,HTML 页面需要的全部内容都准备好,直接把一个“满汉全席”成品扔给浏览器和爬虫。 而我之前做的 React SPA + pre-render 方案,充其量只是在“满汉全席”的菜单上,用小字附上了一份“菜品介绍”。
Lighthouse 看了看菜单说:“嗯,菜品很丰富,85分。”
Google 的爬虫走进来,看了一眼空荡荡的餐桌,然后把我那份菜单扔进了垃圾桶。
2. Next.js — 声称爱你,却只想带你回 Vercel
“我以为我找到了救世主,结果他是我命中注定的劫。”
行,既然 pre-render 这条小路走不通,那就上正道,搞真正的 SSG。
问题明确了,解决方案也就清晰了:换框架!
我需要一个能支持 SSG、能兼容我现有 React 代码、并且生态足够强大的框架。打开 Google,搜索框还没打完,答案就已经自己跳了出来:
Next.js 🤩
“The React Framework for Production”
这口号,霸气!
再看它的特性:“SSG 快如闪电”、“SEO 天选之子”、“从现有 React 应用无缝切换”……
每一个字都精准地砸在了我的心巴上。这不就是为我量身定做的银弹吗?我甚至都不需要改动太多代码!
我当时就想,这不就是 React 生态里的 Spring Boot 吗?Spring 本身很灵活,但做 Web 开发还是得上 Spring Boot 这个“全家桶”。同理,React 本身只是个库,Next.js 才是那个能带它走向生产环境的“亲哥”啊!
说干就干!
我花了整整几个小时,对着文档,升级依赖、改目录结构、调整路由(虽然超过一半的活都是 AI 干的……终于,在 npm run dev 敲下回车的那一刻,我的 Landing Page 在 Next.js 的框架下,成功运行了!
那一刻,我感觉自己掌控了整个宇宙。
好了,本地跑通了,下一步,部署!
我熟练地打开了 赛博菩萨 Cloudflare 的主页 ,准备走部署流程。
就在这时,Vercel 的铁拳砸了下来。
我这才知道,Next.js 里的某些核心功能,比如它那个吹得神乎其神的图片自动优化 (<Image>),根本不是框架自带的,它依赖 Vercel 平台的后端服务!
我人都傻了 🤯
好家伙,我以为我找的是个技术合伙人,结果是个必须和丈母娘(Vercel)绑死的“上门女婿”!它对你所有的好,所有的承诺,都是为了最后让你心甘情愿地走进 Vercel 这个家门。
Next.js 从来就不是一个纯粹的开源框架,它是 Vercel 的销售手册和护城河。它所有的“最佳实践”,最终都指向一个目的地:“Deploy with Vercel”。
我感到一些 恶心 不适 🤕
我不信邪,难道离了 Vercel 就活不了了?很快,我发现了 OpenNext 这个项目,它宣称能让 Next 项目兼容 AWS、Cloudflare 等平台。
我又燃起了希望。
于是,我又花了几个小时,研究 OpenNext 的文档,改配置,尝试部署……
我又一次失败了。
这个迁移过程遇到了无数稀奇古怪的问题,我顺手点开了它的 GitHub,发现代码提交频繁,issues 区哀鸿遍野。我瞬间意识到,这玩意儿就是个半成品,我可能会掉进一个永远也填不完的坑里。
算了,放弃。
我又想到了 Next.js 的最后一个“和平分手”选项:静态导出 (next export)
官方宣称,使用这个功能,可以将 Next 项目导出为纯静态文件,可以部署在任何地方。这不就行了吗!我赶紧舍弃了图片优化功能,开始修改代码以满足静态导出的条件。
然后,我又失败了。
因为 Next 的静态导出,和我用的国际化库 next-intl 在路由处理上有着莫名其妙的兼容问题。虽然这是 Next 官方推荐的国际化库,但是无论我怎么折腾,它就是没法为我所有的语言页面生成对应的静态 HTML 文件。
这个过程又花了我几个小时。
我看着满屏的错误日志,那一刻,我真的累了。我感觉自己就像个小丑 🤡
3. Astro — 美丽新世界,可惜我的 UI 库没买到船票
“在绝望的尽头,我看到了一座灯塔,然后一头撞了上去”
被 Next.js 这么一折腾,我对整个 React 全家桶生态产生了深深的怀疑。
我不想再挣扎了。我决定和 React 框架暂时分手,去看看外面的世界。Vue、Svelte 这些,虽然名声在外,但设计理念和技术生态完全不同,短时间内再去学一套,我的肝可能不同意。
就在我快要放弃,准备躺平,接受我的 Landing Page 就是个“搜不到的废物”这个设定时,一个名字闯入了我的视野:
Astro 🚀
它的 Slogan 简直是一股清流:“The web framework for content-driven websites.”
Landing Page 不就是最典型的内容驱动网站吗?
我抱着死马当活马医的心态,点开了它的文档。结果越看,眼睛越亮,心跳越快。
- “Island Architecture”(岛屿架构): 默认发送零 JS 到客户端,页面上的交互组件像一个个“孤岛”一样,按需加载。翻译一下:快,极致的快!
- “UI-Agnostic”(UI 框架无关): 你可以在同一个项目里,同时使用 React、Vue、Svelte 等任何你喜欢的组件。翻译一下:我之前的 React 组件还能接着用,不用重写!
- “Deploy Anywhere”(随处部署): 默认输出纯静态文件,你想把它部署在哪都行。翻译一下:彻底告别被平台绑架的恶心感!
这简直就是我的梦中情框啊!
它就像一个编译工具,而不是一个大包大揽的运行时框架。它在编译期就把能干的活全干完了,生成最纯粹、最轻量的 HTML 和 CSS,然后把交互的部分交给具体的 UI 库去处理。
这不就是我们后端最推崇的“关注点分离”吗?专业的事交给专业的工具去做!
我感觉自己被治愈了 ❤️🩹
我仿佛看到了一个没有平台绑架、没有复杂配置、回归 Web 本质的美丽新世界。
吸取了前一次在部署前不知道 Next.js 和 Vercel 强绑定吃过的亏,在开始之前,我就我当前的技术栈和部署平台向地表三大最强 AI 师傅 (Gemini 2.5 Pro, ChatGPT 5, Claude Sonnet 4.5) 咨询,他们都告诉我:超棒的选择! 三大 AI师傅 异口同声的保证,让我信心爆棚,感觉这次稳了。
希望的火焰再次燃起!🔥
我立刻动手,边学边把我的 Landing Page 往 Astro 迁移(当然 AI 还是干活的主力)整个过程出乎意料的顺畅,Astro 的语法简洁又直观。
我开心地把我那些用 Mantine UI 写的 React 组件一个个地请进 Astro 的新家。
然后,在敲下编译命令的那一刻,报错了。
无论我和 AI 师傅怎么修改,Mantine 相关的组件在编译时总是抛出各种奇奇怪怪的错误。
我感觉不对劲,一种不祥的预感笼罩了我。
我立刻去 Google 搜索,然后,我在 Mantine 的官方文档里,找到了一个 FAQ:
“Can I use Mantine with Astro?”
答案只有三个词,却像一把冰冷的刀,插进了我千疮百孔的心里:
“Not a chance.” (门儿都没有。)
官方给出的解释是:“…Astro does not support React context, which is required for Mantine to work.” (Astro 不支持 React context,而这是 Mantine 工作所必需的。)
我这才了解到,所有基于 CSS-in-JS 技术的 UI 库 (比如 Mantine, Styled-Components),都深度依赖 React context 来实现主题切换、样式注入等核心功能。而 Astro 为了追求极致的性能,在它的编译魔法里,把这个 context 给“优化”掉了。
我笑了。
是那种通宵改 bug 最后发现是网线没插的笑。
我绕了一大圈,躲过了 Next.js 的平台绑架,却一头撞死在了 Astro 和 CSS-in-JS 的兼容性墙上。
前前后后,快两天的时间就这么过去了。
我终究还是没能走出这个新手村 🫠
4. 血战后的顿悟 — 写给后端程序员的前端“黑皮书”
“我失去了时间,却看清了整个江湖”
这两天,我没写出几行能用的代码,我的 Landing Page 项目回到了原点。
但我心里反而异常平静 😐
我终于把前端技术圈这些让人眼花缭乱的名词、框架、库,它们之间错综复杂的关系,给彻底搞明白了。这笔“学费”,交得值。
所以,我把这些顿悟写下来,希望能为所有像我一样,对如今百花齐放的前端技术栈感到困惑的后端同行们,提供一份“避坑指南”。
JS Frameworks 的 “路线之争”
我之前天真地以为,这些框架只是实现同一个目标的不同工具。现在我明白了,它们代表着三种截然不同的建站哲学。
-
“SPA 应用专家” (纯 React / Vue / Angular / Svelte ):
- 哲学: “重客户端”的典范,追求极致的交互体验。它们的目标是把浏览器变成一个应用(Application)的运行环境。
- 适合场景: 复杂的、重交互的 Web 应用。比如我的 PigeonPod 主应用本身,各种 SaaS 产品的管理后台,在线画图、文档工具等等。
- 给后端的忠告: 这是造应用的锤子,别用它来钉展示内容的钉子。用它们去做“门面”网站,就是在自找麻烦。
-
“内容至上纯粹派” (Astro):
- 哲学: “重服务器”的回归,追求极致的加载速度和 SEO。它的世界里,内容为王,JS 只是点缀。它信奉“非必要,不加 JS”,把能做的都在构建时做完,给你一个最纯粹的 HTML 页面。
- 适合场景: 内容展示型网站。官网、博客、文档、营销页面。
- 给后端的忠告: 如果你只想做一个高性能、SEO 拉满的“门面”,Astro 就是那个简单、直接、正确的答案。 它符合我们后端“KISS (Keep It Simple, Stupid)”的原则。
-
“大一统全能帝国” (Next.js):
- 哲学: 它是个野心家。它既想拥有 SPA 的交互能力,又想要 SSG/SSR 的性能和 SEO。它不仅是前端框架,还能让你写后端 API。它想做的,是一个“全栈开发平台”。
- 它很强大,真的。 但它的问题也在这里:它的“全能”是以深度绑定自家 Vercel 平台为代价的。它的很多最佳实践,最终都指向一个闭环生态。
- 给后端的忠告: 选择 Next.js 不仅仅是一个技术选型,更是一个平台和生态的抉择。 你得到的是一站式的便利,失去的是部署的自由。如果你愿意拥抱 Vercel 的生态,它会给你丝滑的体验;如果你想挣脱,就会像我一样,被各种“特性”卡住喉咙。
另外 Vue 和 Svelte 生态也有他们自己对标 Next 的全栈框架: Nuxt 和 SvelteKit,但我没深入了解过,不做评价。
UI Components 的 “门派之别”
-
CSS-in-JS 派 (Mantine, Styled-Components): 深度依赖 JS 运行时和 React Context,和 Astro 这种“零 JS”理念的框架天生八字不合。
-
Utility-First / Headless UI 派 (Tailwind CSS, Radix UI): 在构建时就确定好样式,不依赖运行时,是 Astro 这类 JS 框架的灵魂伴侣。
暴论时间
搞清楚了上面这些,一些过去让我困惑的事情,现在都有了答案。
-
暴论一:现代前端的很多复杂性,都是为了解决“用 SPA 去做本不该它做的事情”而产生的。 我们本可以简单地写 HTML 来展示内容,但我们非要先用 JS 去模拟一个应用,然后再发明 SSR、SSG 等一大堆“补丁”去优化这个模拟过程,让它“看起来像”一个静态网站。何苦呢?
-
暴论二:不要迷信任何“无缝迁移”的鬼话。 任何框架的切换,本质上都是哲学思想的切换,伤筋动骨是必然的。所谓“无缝”,往往只是营销口号。作为工程师,你要有把它推倒重来的觉悟。
写到这里,我长舒一口气。我感觉,我 总算 大概是搞清楚了前端娱乐圈的本质。
虽然,还是个菜鸟 😅
5. 路在何方?
那么,我的 PigeonPod Landing Page 升级计划呢?
答案已经很明显了:推倒重来。
我之前以为,这次血战换来的最终答案会是 Astro + Tailwind CSS。理论上,这个组合完美无瑕,性能拉满,自由度最高。
但当我真的开始尝试用它来复刻我之前用 Mantine 做出的页面时,现实又给了我狠狠一巴掌。
我发现,对于一个像我这样 CSS 经验约等于零、审美基本靠“居中对齐”的后端工程师来说,直接使用 Tailwind 这种原子化的 CSS 框架,无异于一场灾难。它给了你无限的自由,但同时也带来了无限的选择。每一个边距、每一个圆角、每一个阴影,都需要我自己去调试。
想做出原来用 Mantine 那种开箱即用的精致感?太难了,这又是一个巨大的时间黑洞。
就在我再次陷入绝望,以为自己注定只能在“性能”和“好看”之间二选一的时候,我找到了这个故事的最后一块拼图:
shadcn/ui ✨
它不是一个传统的 UI 库,而是一系列你可以直接复制粘贴到自己项目里的、用 Tailwind CSS 写好的高质量组件。
这似乎正是我为 Astro 寻找的那个“中间地带”:它既给了我像 Mantine 一样可以直接使用的、设计精美的成品组件,又保留了 Tailwind 的所有优点,能和 Astro 完美协作,还没有额外的 JS 运行时。
于是,我的新计划也清晰了起来:
PigeonPod 应用本身,继续使用 React + Mantine UI,因为它适合做“应用”。
而那个备受折磨的 Landing Page,我准备用 Astro + shadcn/ui 去尝试新生。
当然,这只是一个新的开始。我还没来得及敲下第一行代码,天知道前面还有多少坑在等着我。但我希望,这一次,方向是真的对了。
写到这里,我的这段踩坑经历也就告一段落了。这篇文章,更多的是分享我的心路历程。接下来,我还会再写一篇更严肃纯粹的技术文章,从架构和原理的角度,去仔细对比和分析市面上这些主流的 JS frameworks 和 UI components,到底应该如何选择和取舍。
最后,想对所有和我一样,在前端世界里感到迷茫的后端同仁们说:
搞清楚你要做的,到底是一个“应用”,还是一个“网站”。
这个问题,可能比选择哪个框架,重要一百倍。