你的项目真的需要SSR吗?还是只是你的简历需要?

技术选型不是为了简历好看,是为了解决问题

上周和一个前同事约饭,他现在在一家创业公司带前端团队。

聊到一半他突然问我:"我们准备把项目重构成 Next.js,上服务端渲染,你觉得怎么样?"

我放下筷子:"你们现在遇到什么坑了要重构?"

他挠挠头:"坑倒是没有......就是现在出去面试,人家都问有没有 Next.js 经验,我们不用会不会显得技术栈太旧了。"

"那你们产品要 SEO 吗?用户网络环境咋样?"

"用户都在一二线城市,网速挺好的。SEO 的话......产品得登录才能用,搜索引擎也爬不到。"

我看着他,不知道该说什么。

又一个被技术流行绑架的老同事。


一、SSR不是银弹,它是一把双刃剑

这两年,Next.js、Nuxt.js确实火得不行。

打开技术社区,满屏都是"从CSR迁移到SSR后,FCP提升50%"、"SSR才是前端正确的打开方式"。

但你有没有发现,很少有人告诉你:为了这点性能提升,你和你团队接下来半年要填多少坑。

1. 服务器账单:以前不要钱,现在要钱了

纯静态页面放OSS上,流量不大时一年可能就几百块。

上了SSR呢?

  • 你需要一台服务器,或者云函数实例
  • 你需要考虑并发,一台扛不住要上负载均衡
  • 你还要担心服务器宕机,得配监控、告警、容灾

我一个朋友的项目,上了SSR后第一个月,云账单从300涨到了3000。老板拿着账单问他:"用户感受到变快了吗?多出来的钱能从收入里赚回来吗?"

他答不上来。

更扎心的是,后来发现大部分用户都是从首页跳详情页,首屏优化的收益根本覆盖不了成本

2. 复杂度转移:以前是纯前端问题,现在是全栈问题

CSR项目,前端只管写页面,接口调不通那是后端的事。

SSR项目呢?

javascript 复制代码
// 以前写页面,岁月静好
function UserProfile({ userId }) {
  const [user, setUser] = useState(null)
  
  useEffect(() => {
    fetch(`/api/user/${userId}`).then(setUser)
  }, [userId])
  
  return <div>{user?.name}</div>
}
javascript 复制代码
// 上了SSR之后,噩梦开始
export async function getServerSideProps({ params }) {
  try {
    // 要处理接口超时
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), 3000)
    
    const res = await fetch(`http://internal-api/user/${params.id}`, {
      signal: controller.signal
    }).catch(() => null)
    
    clearTimeout(timeoutId)
    
    if (!res || !res.ok) {
      // 降级策略怎么写?
      return { props: { user: null, fallback: true } }
    }
    
    const user = await res.json()
    return { props: { user } }
  } catch (error) {
    // 服务端报错,用户看到什么?
    return { notFound: true }
  }
}

function UserProfile({ user, fallback }) {
  // 客户端还要再校验一遍状态
  const [mounted, setMounted] = useState(false)
  
  useEffect(() => {
    setMounted(true)
  }, [])
  
  if (!mounted) {
    return <div>加载中...</div> // 防止hydrate报错
  }
  
  return <div>{user?.name}</div>
}

数据在服务端取,取不到怎么办?页面直接500还是降级成CSR? 服务端取的接口超时了,是要等待还是超时返回? 服务端和客户端的状态怎么对齐?一不小心就 hydrate 报错

我一个同事转做Next.js项目后发朋友圈:"自从上了SSR,我不仅要写React,还要会配Nginx、懂PM2、会分析内存泄漏。工资没涨,责任翻倍。"

底下点赞的全是前端。

3. 开发体验的割裂感

以前写CSR,window、document随便用,反正都在浏览器里。

写了SSR之后:

javascript 复制代码
// 以前一行代码
const width = window.innerWidth
const token = localStorage.getItem('token')
const height = document.getElementById('app').offsetHeight
javascript 复制代码
// 现在
const width = typeof window !== 'undefined' ? window.innerWidth : 1024
const token = typeof window !== 'undefined' 
  ? localStorage.getItem('token') 
  : null
const [height, setHeight] = useState(0)

useEffect(() => {
  setHeight(document.getElementById('app')?.offsetHeight || 0)
}, [])
  • 第三方库如果不兼容服务端渲染,要动态导入
  • localStorage、sessionStorage都不能直接用
  • 路由跳转要小心,服务端没有history API

原本简单的逻辑,现在要写一堆防御代码。你在给代码做安检,但业务逻辑一点没变复杂。


二、你真的需要SSR吗?问自己三个扎心的问题

每次有人问我该不该上SSR,我都让他先回答三个问题。回答完,80%的人自己就放弃了。

问题一:你的产品靠搜索引擎吃饭吗?

这是最硬性的指标,也是最容易被拿来当借口的。

如果你的产品是:

  • 内容型网站(博客、新闻、官网)
  • 电商网站(需要被搜索引擎收录商品页)

那SSR确实有必要。因为爬虫可能不执行JS,或者执行不完整。

但如果你的产品是:

  • 需要登录的后台管理系统
  • 工具类、游戏类H5
  • B端SaaS应用
  • 社区类App的H5版(用户得先登录)

搜索引擎根本爬不到,SEO就是伪需求。

别拿SEO当借口,你只是想让简历里多一行Next.js。

问题二:你的首屏速度真的慢到不能忍了吗?

很多时候,我们觉得首屏慢,其实不是因为CSR不行,是代码写得太糙。

我见过一个"慢"的项目,分析下来:

javascript 复制代码
// 问题代码示例
function App() {
  const [data, setData] = useState(null)
  const [user, setUser] = useState(null)
  const [config, setConfig] = useState(null)
  
  useEffect(() => {
    // 串行调用,一个等一个
    fetch('/api/data').then(res => res.json()).then(data => {
      setData(data)
      return fetch('/api/user')
    }).then(res => res.json()).then(user => {
      setUser(user)
      return fetch('/api/config')
    }).then(res => res.json()).then(setConfig)
    
    // 图片没处理
    new Image().src = 'https://example.com/big-banner.png'
    
    // 第三方脚本同步加载
    const script = document.createElement('script')
    script.src = 'https://analytics.com/sdk.js'
    document.head.appendChild(script)
  }, [])
  
  return <div>...</div>
}

这些问题,优化代码比换架构性价比高得多

我去年优化过一个Vue2项目,纯CSR,首屏从3.2秒优化到1.1秒,只做了四件事:

javascript 复制代码
// 优化后
useEffect(() => {
  // 1. 并行调用
  Promise.all([
    fetch('/api/data'),
    fetch('/api/user'),
    fetch('/api/config')
  ]).then(...)
  
  // 2. 图片转WebP + 懒加载
  // 3. 第三方脚本异步
  const script = document.createElement('script')
  script.async = true
  script.src = 'https://analytics.com/sdk.js'
  
  // 4. 路由懒加载
  const List = lazy(() => import('./pages/List'))
}, [])

没动架构,没重构,没加班。

问题三:你的团队准备好了吗?

这是最容易被忽略的,也是上线后最痛苦的。

上SSR意味着你的前端团队要开始写服务端代码:

  • 有人写过Node.js吗?
  • 有人配过Nginx吗?
  • 有人处理过内存泄漏吗?
bash 复制代码
# 线上出问题了,你能处理吗?
curl -X POST https://your-site.com/api/user -H "Content-Type: application/json" -d '{"id":123}'

# 如果返回 502
# 是Node进程挂了?Nginx配置错了?接口超时了?

# 登录服务器
ssh user@your-server
pm2 logs
df -h # 磁盘满了?
free -m # 内存泄漏?
top # CPU爆了?
  • 线上出问题了,有人能在凌晨两点爬起来回滚吗?

如果答案都是"没有",那SSR上线的那天,就是团队噩梦的开始。

技术选型不仅要看技术好不好,还要看团队接不接得住。


三、那些比SSR更香的选择

如果你确实有性能痛点,但又不是非要SSR,其实有很多折中方案。

方案一:静态站点生成(SSG)

如果你的内容是静态的,或者更新不频繁,SSG是完美的选择。

javascript 复制代码
// next.config.js
module.exports = {
  // 构建时生成HTML
  exportPathMap: async function() {
    return {
      '/': { page: '/' },
      '/about': { page: '/about' },
      '/blog/1': { page: '/blog/[id]', query: { id: '1' } },
    }
  }
}
  • 构建时生成HTML,部署在CDN上
  • 首屏速度极快,SEO友好
  • 没有服务器成本,没有运维负担

Next.js、Nuxt.js、VitePress都支持。既有了SSR的首屏优势,又保留了CSR的简单部署。

方案二:静态部署 + 客户端渲染

大部分场景,这才是最优解。

javascript 复制代码
// index.html
<!DOCTYPE html>
<html>
<head>
  <!-- 骨架屏,让用户看到东西 -->
  <style>
    .skeleton { background: #f0f0f0; height: 20px; margin: 10px; }
  </style>
</head>
<body>
  <div id="root">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
    <div class="skeleton"></div>
  </div>
  
  <!-- 资源放CDN,并行加载 -->
  <link rel="preconnect" href="https://api.example.com">
  <script src="https://cdn.example.com/react.js" async></script>
  <script src="https://cdn.example.com/app.js" async></script>
</body>
</html>
  • HTML放CDN,全球加速
  • 接口走API网关,BFF层做聚合
  • 配合预加载、懒加载、骨架屏,体验一点都不差

我现在的项目就是这种方案:React + Vite,打包后放OSS,CDN加速。首屏1.2秒,月PV百万,服务器成本主要是BFF层的几个云函数,加起来不到500块。

够用就好,别为了炫技给自己挖坑。

方案三:部分页面SSR,大部分页面CSR

如果你确实有少数页面需要SEO(比如官网、 landing page),其他页面需要登录。

javascript 复制代码
// next.config.js
module.exports = {
  // 只有这些页面走SSR
  pageExtensions: ['ssr.js', 'page.js'],
  
  async rewrites() {
    return [
      // landing page走SSR
      {
        source: '/',
        destination: '/landing.ssr',
      },
      // 其他页面走静态CSR
      {
        source: '/app/:path*',
        destination: '/app.html',
      }
    ]
  }
}

那可以只把这几个页面抽出来做SSR,剩下的保持CSR。

Next.js支持多页应用模式,Vue也有混合渲染方案。没必要为了10%的页面,让90%的页面承担复杂度。


四、写在最后:技术选型不是为了简历好看

写这篇文章,不是为了否定SSR。

SSR是好技术,Next.js是好框架。我在合适的项目里也用它,确实能解决问题。

但我不喜欢一种风气:明明是个简单的H5活动页,非要上Next.js;明明是个后台管理系统,非要搞服务端渲染;明明首屏已经1.5秒了,非要重构到1.2秒。

为了那0.5秒的优化,搭进去团队半年的维护成本,值吗?

技术选型的标准,不是"别人都用",也不是"大厂在用",而是:

  • 能解决我们现在的痛点吗?
  • 团队能驾驭吗?
  • 维护成本扛得住吗?
  • 换来的收益对得起付出的代价吗?

别让技术选型,变成一场给简历镀金的表演。


最后想问问大家: 你们见过哪些"没必要上SSR但硬上"的项目?踩过哪些坑?欢迎在评论区互相伤害。

如果你也看不惯那些为了炫技而复杂化的技术选型,欢迎关注我,一起聊聊真实的前端。

相关推荐
恋猫de小郭2 小时前
移动端开发稳了?AI 目前还无法取代客户端开发,小红书的论文告诉你数据
前端·flutter·ai编程
文心快码BaiduComate2 小时前
百度云与光本位签署战略合作:用AI Agent 重构芯片研发流程
前端·人工智能·架构
闲云一鹤3 小时前
nginx 快速入门教程 - 写给前端的你
前端·nginx·前端工程化
QCY3 小时前
「完全理解」1 分钟实现自己的 Coding Agent
前端·agent·claude
一拳不是超人3 小时前
Electron主窗口弹框被WebContentView遮挡?独立WebContentView弹框方案详解!
前端·javascript·electron
anyup4 小时前
🔥2026最推荐的跨平台方案:H5/小程序/App/鸿蒙,一套代码搞定
前端·uni-app·harmonyos
雮尘4 小时前
如何在非 Claude IDE (TARE、 Cursor、Antigravity 等)下使用 Agent Skills
前端·agent·ai编程
icebreaker4 小时前
Weapp-vite:原生模式之外,多一种 Vue SFC 选择
前端·vue.js·微信小程序
icebreaker4 小时前
重走 Vue 长征路 Weapp-vite:编译链路与 Wevu 运行时原理拆解
前端·vue.js·微信小程序