javascript如何实现服务端渲染_Next.js是如何处理这个过程的?

发布时间 - 2026-01-10 00:00:00    点击率:
服务端渲染在JavaScript中的本质是代码在Node.js中执行并生成HTML字符串;Next.js的getServerSideProps每次请求时服务端执行并注入props;SSR与hydration断连主因是服务端与客户端渲染不一致;App Router中SSR变为隐式async组件执行,fetch默认缓存。

服务端渲染在 JavaScript 中的本质是什么?

服务端渲染(SSR)不是框架的专利,而是指 JavaScript 代码在 Node.js 环境中执行并生成 HTML 字符串,再返回给浏览器。关键在于:DOM 操作不能依赖浏览器全局对象(如 windowdocument),否则会抛出 ReferenceError

纯手写 SSR 需要手动处理:

  • 入口文件需兼容服务端(无浏览器 API 调用)
  • 组件状态必须可序列化,且首次渲染结果能被 React.renderToStringVue.renderToString 捕获
  • 数据获取逻辑必须在服务端触发,并注入到 HTML 中(如通过 window.__INITIAL_STATE__
  • 客户端 hydrate 时需复用服务端生成的 DOM,避免重复渲染闪烁

Next.js 的 getServerSideProps 是怎么工作的?

这是 Next.js 实现 SSR 的核心约定函数,每次请求都会在服务端执行,返回的数据会作为 props 注入页面组件。它不是“预渲染”,而是真正意义上的请求时服务端执行。

注意点:

  • 只在页面组件(pages/xxx.jsapp/xxx/page.js 的旧版 pages 目录下)中有效
  • 不能在普通组件中使用,也不能在 app 目录的默认 Server Components 中直接调用(新版用 async 组件 + fetch 替代)
  • 函数内可调用数据库、API、fs.readFile 等 Node.js API,但不能访问 window
  • 返回值必须是 { props: { ... } } 对象,否则页面会 500
export async function getServerSideProps(context) {
  const res = await fetch('https://api.example.com/user')
  const user = await res.json()
  return {
    props: { user } // 这个对象会变成组件的 props
  }
}

Next.js 的 SSR 和客户端 hydration 之间容易断连的点

最常见问题是服务端渲染内容与客户端初次 render 结果不一致,导致 React 报错 Hydration failed because the initial UI does not match what was rendered on the server

典型诱因:

  • 组件内部使用了 Math.random()Date.now() 等非确定性值,服务端和客户端结果不同
  • 条件渲染依赖了 typeof window !== 'undefined',服务端为 true(因为 window 不存在),客户端为 false,导致 DOM 结构不一致
  • useEffect 内修改了服务端已渲染的 DOM(比如动态插入广告位),但服务端没做对应输出
  • 样式库(如 styled-components)未正确启用 StyleSheetManager 或未同步服务端的 class name 生成逻辑

App Router(app 目录)下 SSR 的实际形态变了

Next.js 13+ 的 app 目录默认使用 Server Components,不再需要 getServerSideProps。SSR 变成隐式行为:所有 async 组件函数都在服务端执行,await fetch 自动被拦截并去重、缓存。

但这也带来新约束:

  • Server Components 中不能使用 useStateuseEffect、浏览器 API
  • 交互逻辑必须下沉到 "use client" 标记的 Client Components 中
  • fetch 默认开启 cache: 'force-cache',要实现真正的 SSR(每次请求都发新请求),得显式写 fetch(url, { cache: 'no-store' })
  • 服务端生成的 HTML 不再包含完整 JS bundle,hydration 更轻量,但也意味着部分逻辑无法在服务端“提前执行”

真实项目里,很多人卡在“为什么 app 目录下接口没重发”,其实只是 fetch 缓存策略默认变了。


# vue  # react  # javascript  # java  # html  # js  # node.js  # json  # node  # 浏览器  # app 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何快速搭建高效香港服务器网站?  如何用PHP快速搭建高效网站?分步指南  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  uc浏览器二维码扫描入口_uc浏览器扫码功能使用地址  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭  Laravel定时任务怎么设置_Laravel Crontab调度器配置  js实现点击每个li节点,都弹出其文本值及修改  javascript中闭包概念与用法深入理解  如何快速辨别茅台真假?关键步骤解析  JS去除重复并统计数量的实现方法  标题:Vue + Vuex + JWT 身份认证的正确实践与常见误区解析  Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】  公司网站制作价格怎么算,公司办个官网需要多少钱?  Laravel API资源类怎么用_Laravel API Resource数据转换  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】  如何用wdcp快速搭建高效网站?  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  济南网站建设制作公司,室内设计网站一般都有哪些功能?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  Java类加载基本过程详细介绍  Laravel如何创建自定义中间件?(Middleware代码示例)  Laravel如何处理文件下载请求?(Response示例)  高防服务器租用如何选择配置与防御等级?  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  Android利用动画实现背景逐渐变暗  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  Laravel如何创建自定义Facades?(详细步骤)  php嵌入式断网后怎么恢复_php检测网络重连并恢复硬件控制【操作】  如何基于云服务器快速搭建个人网站?  潮流网站制作头像软件下载,适合母子的网名有哪些?  phpredis提高消息队列的实时性方法(推荐)  如何注册花生壳免费域名并搭建个人网站?  国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?  EditPlus中的正则表达式实战(6)  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  Bootstrap CSS布局之列表  JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  常州企业网站制作公司,全国继续教育网怎么登录?  Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】  如何在IIS中新建站点并配置端口与IP地址?  深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?  如何在宝塔面板中创建新站点?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  Laravel如何使用Seeder填充数据_Laravel模型工厂Factory批量生成测试数据【方法】  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  轻松掌握MySQL函数中的last_insert_id()  Laravel路由怎么定义_Laravel核心路由系统完全入门指南