初步认识前端SSR(服务端渲染)

背景知识

  • 最初的php,jsp等技术是曾经主流的前后端不分离的解决方案。当服务器接收到一个请求后,根据一定的逻辑,获取数据库的数据,然后把运算好的数据传递到html模板文件,生成完整的html代码,返回到客户端展示。

  • 前端框架(Vue,React等)是前后端分离思想的优秀产物。它们常见都是生成SPA应用。而SPA的优点是用户体验好,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染。

  • 前端SSR方案结合了MPA和SPA的思想,针对spa首屏加载较慢和不利于seo的缺点,采用了服务端客户端同构的方案。

关键知识点

  • 服务端客户端同构
  • 服务端渲染(SSR)
  • 静态生成(SSG)

渲染方式与spa的差异

js 复制代码
// react JSX渲染
function Hello() {
  return <div>Hello world</div>
}

export default Hello

spa页面例子(蓝湖):

ssr例子(百度):

  • spa应用的特点是依赖 JS 运算生成对应的 DOM 节点, html 文件里本来是不存在具体的DOM节点。而 SSR 是可以在服务器渲染好完整的DOM结构再返回给客户端。

生命周期与spa的差异

  • 服务端渲染时候执行的生命周期顺序和客户端渲染是一致的,但是需要注意是在服务端执行的生命周期钩子内,是无法执行浏览器特有的api

特有的渲染方法(以next.js框架为例)

静态生成(SSG)

出于性能原因,Next官方更推崇使用静态生成。 如果页面没有数据请求,Next会采用静态生成的方式,在构建的时候就生成好对应HTML;

如果页面内容依赖外部数据,可以在页面组件中export一个名叫getStaticProps的方法,这个函数会在构建时被调用,然后将获取的数据传递到页面的props中,进行预渲染;

js 复制代码
function Blog({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li>{post.title}</li>
      ))}
    </ul>
  )
}

// This function gets called at build time
export async function getStaticProps() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // By returning { props: { posts } }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  }
}

export default Blog

服务端渲染(SSR)

通常面对更新比较快,或者跟用户信息相关的页面,我们都不能使用静态生成的方式来提前生成页面,此时就需要使用服务端渲染,每次请求都重新生成页面HTML;要对页面使用服务器端渲染,需要名为getServerSideProps的方法, 服务器将在每次请求时都会调用此函数

javascript 复制代码
function Page({ data }) {
  // Render data...
}

// This gets called on every request
export async function getServerSideProps() {
  // Fetch data from external API
  const res = await fetch(`https://.../data`)
  const data = await res.json()

  // Pass data to the page via props
  return { props: { data } }
}

export default Page

getServerSideProps跟之前静态生成用到的getStaticProps方法非常相似,不同之处在于getServerSideProps在每个请求都会运行,而getStaticProps是在构建时运行。

增量生成(ISR)

SSG这种静态页面虽然好,但缺点也十分突出,如果只能在构建时生成页面,那就意味着,每次在管理后台里改动了业务数据,都需要重新构建以刷新页面。如果没有办法解决这个缺点,SSG虽好,但可使用的业务场景也非常少,所幸,next提供了在构建站点后创建或更新静态页面的能力,这就是ISR。

服务端客户端同构的工作方式

如上介绍,服务端会预先生成需要展示的html结构,那是不是就意味着每次在浏览器输入不同的url,都会访问一次服务器获取新的html内容呢?

如果是这样,就牺牲了spa的特性。所以当访问一个新的url,需要先区分是否由客户端路由跳转产生的访问,如果是则执行spa路由跳转的逻辑,否则就执行产生一条服务端请求最新的html文件内容。这就意味着同一份代码既有可能在服务端执行,也有可能在客户端执行。

SSR优点

  • 利于seo优化,方便搜索引擎抓取数据。
  • 服务端和客户端分工明确,仍保留客户端路由管理,全局数据状态管理等功能。
  • 大幅提高页面访问性能。

在这里,我主要想展开说说为什么可以明显地提升性能。

  1. 把依赖接口的数据提前在服务端获取,节省了等待接口响应的时间。
  2. 获取到了接口数据,根据特定逻辑渲染成真正的DOM结构。这个步骤也放到了服务端执行,节省客户端渲染时间。(客户端机型性能差的时候尤其明显)
  3. 浏览器加载资源,无需等待任何JS文件的加载,就可以渲染出初始页面,LCP和FCP性能指标很好。(客户端网络差的时候尤其明显)

疑问点

  • Q. 现在的前端SSR和以前的PHP等前后端不分离技术方案有何区别?

A. 前后端是否真正解耦,前端是否具备工程化能力(路由管理,全局数据状态管理,前端生态工具链)

  • Q. 使用了nuxt.js或者next.js搭建的项目后,引入一些第三方的库或组件,会报错

A. 一些三方库使用了window,localStorage等客户端特有的对象,如果该逻辑是在服务端运行的,那么这些对象肯定是为空值,所以就报错了。解决方案也不复杂,使用条件控制渲染组件,在特定的生命周期再允许渲染该组件。

总结

从以前的前后端不分离的后端语言渲染html,到spa应用,再到目前的前端SSR解决方案,历史是在螺旋上升的。前端技术方案也越来越成熟,处理大型项目的能力也越来越强大。

相关推荐
王解5 分钟前
一篇文章读懂 Prettier CLI 命令:从基础到进阶 (3)
前端·perttier
乐闻x11 分钟前
最佳实践:如何在 Vue.js 项目中使用 Jest 进行单元测试
前端·vue.js·单元测试
檀越剑指大厂25 分钟前
【Python系列】异步 Web 服务器
服务器·前端·python
我是Superman丶27 分钟前
【前端】js vue 屏蔽BackSpace键删除键导致页面后退的方法
开发语言·前端·javascript
Hello Dam28 分钟前
基于 Spring Boot 实现图片的服务器本地存储及前端回显
服务器·前端·spring boot
小仓桑30 分钟前
利用 Vue 组合式 API 与 requestAnimationFrame 优化大量元素渲染
前端·javascript·vue.js
Hacker_xingchen30 分钟前
Web 学习笔记 - 网络安全
前端·笔记·学习
天海奈奈31 分钟前
前端应用界面的展示与优化(记录)
前端
多多*1 小时前
后端并发编程操作简述 Java高并发程序设计 六类并发容器 七种线程池 四种阻塞队列
java·开发语言·前端·数据结构·算法·状态模式
mubeibeinv1 小时前
列表代码思路
前端